screen: make better use of the available space in the titlebar

When the terminal is very narrow, there is little point in showing only
part of the version string -- and chewing off one or two digits from the
version number might even give someone a wrong idea.  The user is better
served with always showing the full filename, as long as it fits in the
available screen width.

This fixes https://savannah.gnu.org/bugs/?47703.
master
Benno Schulenberg 2016-04-29 10:42:20 +02:00
parent 338807a327
commit 577f7fafa9
1 changed files with 84 additions and 127 deletions

View File

@ -1915,27 +1915,18 @@ char *display_string(const char *buf, size_t start_col, size_t len, bool
* of path on the titlebar. */
void titlebar(const char *path)
{
int space = COLS;
/* The space we have available for display. */
size_t verlen = strlenpt(BRANDING);
/* The length of the version message in columns. */
const char *prefix;
/* "DIR:", "File:", or "New Buffer". Goes before filename. */
size_t prefixlen;
/* The length of the prefix in columns, plus one for padding. */
const char *state;
/* "Modified", "View", or "". Shows the state of this
* buffer. */
size_t statelen = 0;
/* The length of the state in columns, or the length of
* "Modified" if the state is blank and we're not in the file
* browser. */
char *exppath = NULL;
/* The filename, expanded for display. */
bool newfie = FALSE;
/* Do we say "New Buffer"? */
bool dots = FALSE;
/* Do we put an ellipsis before the path? */
size_t verlen, prefixlen, pathlen, statelen;
/* The width of the different titlebar elements, in columns. */
size_t pluglen = 0;
/* The width that "Modified" would take up. */
size_t offset = 0;
/* The position at which the center part of the titlebar starts. */
const char *prefix = "";
/* What is shown before the path -- "File:", "DIR:", or "". */
const char *state = "";
/* The state of the current buffer -- "Modified", "View", or "". */
char *fragment;
/* The tail part of the pathname when dottified. */
assert(path != NULL || openfile->filename != NULL);
@ -1945,123 +1936,89 @@ void titlebar(const char *path)
blank_titlebar();
/* Limit the length of the version message to a third of the width of
* the screen, minus three columns for spaces. */
if (verlen > (COLS / 3) - 3)
verlen = (COLS / 3) - 3;
/* Leave two spaces before the version message, and account also
* for the space after it. */
mvwaddnstr(topwin, 0, 2, BRANDING, actual_x(BRANDING, verlen));
verlen += 3;
/* Account for the full length of the version message. */
space -= verlen;
/* Do as Pico: if there is not enough width available for all items,
* first sacrifice the version string, then eat up the side spaces,
* then sacrifice the prefix, and only then start dottifying. */
/* Figure out the path, prefix and state strings. */
#ifndef DISABLE_BROWSER
/* Don't display the state if we're in the file browser. */
if (path != NULL)
state = "";
else
#endif
state = openfile->modified ? _("Modified") : ISSET(VIEW_MODE) ?
_("View") : "";
statelen = strlenpt((*state == '\0' && path == NULL) ?
_("Modified") : state);
/* If possible, add a space before state. */
if (space > 0 && statelen < space)
statelen++;
else
goto the_end;
#ifndef DISABLE_BROWSER
/* path should be a directory if we're in the file browser. */
if (path != NULL)
prefix = _("DIR:");
else
#endif
if (openfile->filename[0] == '\0') {
prefix = _("New Buffer");
newfie = TRUE;
} else
prefix = _("File:");
prefixlen = strnlenpt(prefix, space - statelen) + 1;
/* If newfie is FALSE, add a space after prefix. */
if (!newfie && prefixlen + statelen < space)
prefixlen++;
/* If we're not in the file browser, set path to the current
* filename. */
if (path == NULL)
path = openfile->filename;
/* Account for the full lengths of the prefix and the state. */
if (space >= prefixlen + statelen)
space -= prefixlen + statelen;
else
space = 0;
/* space is now the room we have for the filename. */
if (!newfie) {
size_t lenpt = strlenpt(path), start_col;
/* Don't set dots to TRUE if we have fewer than eight columns
* (i.e. one column for padding, plus seven columns for a
* filename). */
dots = (space >= 8 && lenpt >= space);
if (dots) {
start_col = lenpt - space + 3;
space -= 3;
} else
start_col = 0;
exppath = display_string(path, start_col, space, FALSE);
}
/* If dots is TRUE, we will display something like "File:
* ...ename". */
if (dots) {
mvwaddnstr(topwin, 0, verlen - 1, prefix, actual_x(prefix,
prefixlen));
if (space <= -3 || newfie)
goto the_end;
waddch(topwin, ' ');
waddnstr(topwin, "...", space + 3);
if (space <= 0)
goto the_end;
waddstr(topwin, exppath);
} else {
size_t exppathlen = newfie ? 0 : strlenpt(exppath);
/* The length of the expanded filename. */
/* There is room for the whole filename, so we center it. */
mvwaddnstr(topwin, 0, verlen + ((space - exppathlen) / 3),
prefix, actual_x(prefix, prefixlen));
if (!newfie) {
waddch(topwin, ' ');
waddstr(topwin, exppath);
}
}
the_end:
free(exppath);
if (state[0] != '\0') {
if (statelen >= COLS - 1)
mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
{
if (openfile->filename[0] == '\0')
path = _("New Buffer");
else {
assert(COLS - statelen - 1 >= 0);
path = openfile->filename;
prefix = _("File:");
}
mvwaddnstr(topwin, 0, COLS - statelen - 1, state,
actual_x(state, statelen));
if (openfile->modified)
state = _("Modified");
else if (ISSET(VIEW_MODE))
state = _("View");
pluglen = strlenpt(_("Modified")) + 1;
}
/* Determine the widths of the four elements, including their padding. */
verlen = strlenpt(BRANDING) + 3;
prefixlen = strlenpt(prefix);
if (prefixlen > 0)
prefixlen++;
pathlen= strlenpt(path);
statelen = strlenpt(state) + 2;
if (statelen > 2) {
pathlen++;
pluglen = 0;
}
/* Only print the version message when there is room for it. */
if (verlen + prefixlen + pathlen + pluglen + statelen <= COLS)
mvwaddstr(topwin, 0, 2, BRANDING);
else {
verlen = 2;
/* If things don't fit yet, give up the placeholder. */
if (verlen + prefixlen + pathlen + pluglen + statelen > COLS)
pluglen = 0;
/* If things still don't fit, give up the side spaces. */
if (verlen + prefixlen + pathlen + pluglen + statelen > COLS) {
verlen = 0;
statelen -= 2;
}
}
/* If we have side spaces left, center the path name. */
if (verlen > 0)
offset = verlen + (COLS - (verlen + pluglen + statelen) -
(prefixlen + pathlen)) / 2;
/* Only print the prefix when there is room for it. */
if (verlen + prefixlen + pathlen + pluglen + statelen <= COLS) {
mvwaddstr(topwin, 0, offset, prefix);
if (prefixlen > 0)
waddstr(topwin, " ");
} else
wmove(topwin, 0, offset);
/* Print the full path if there's room; otherwise, dottify it. */
if (pathlen + pluglen + statelen <= COLS)
waddstr(topwin, path);
else if (5 + statelen <= COLS) {
waddstr(topwin, "...");
fragment = display_string(path, 3 + pathlen - COLS + statelen,
COLS - statelen, FALSE);
waddstr(topwin, fragment);
free(fragment);
}
/* Right-align the state if there's room; otherwise, trim it. */
if (statelen > 0 && statelen <= COLS)
mvwaddstr(topwin, 0, COLS - statelen, state);
else if (statelen > 0)
mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
wattroff(topwin, A_BOLD);
wattroff(topwin, interface_color_pair[TITLE_BAR].pairnum);