From fa394047ba05020da91025dfc430870fa8ec57b8 Mon Sep 17 00:00:00 2001 From: David Lawrence Ramsey Date: Sun, 23 May 2004 21:11:14 +0000 Subject: [PATCH] add DB's changes to titlebar() (with a few tweaks of mine) to make it handle shorter screen widths better and display the filename using display_string(), my strnlen() equivalent so the new titlebar() will work on systems without strnlen(), and a few of DB's other minor changes to make other display-related functions handle shorter screen widths better, among other things git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1754 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- ChangeLog | 58 ++++++++++-- configure.ac | 2 +- src/files.c | 18 ++-- src/nano.c | 49 +++++----- src/nano.h | 8 +- src/proto.h | 10 +- src/search.c | 2 +- src/utils.c | 15 +++ src/winio.c | 257 ++++++++++++++++++++++++++++++++++----------------- 9 files changed, 283 insertions(+), 136 deletions(-) diff --git a/ChangeLog b/ChangeLog index b2b92083..ea28c312 100644 --- a/ChangeLog +++ b/ChangeLog @@ -63,6 +63,8 @@ CVS code - true beginning of the line. This option is disabled in tiny mode. Changes to do_home(), nanogetstr(), etc. (DLR; suggested by Stephan T. Lavavej) + - Minor tweaks to the punctuation in some statusbar messages. + (DLR) - files.c: add_open_file() - Rearrange the NANO_SMALL #ifdef so that the code to set the @@ -71,6 +73,9 @@ CVS code - do_writeout() - Refactor so that no recursion is needed if we try to exit with a modified file that has no name when TEMP_OPT is set. (DLR) + do_browser() + - Call check_statblank() instead of blanking the statusbar + unconditionally, for consistency. (David Benbennick) - nano.c: do_toggle(), finish() - Call blank_statusbar() and blank_bottombars() to blank out @@ -83,12 +88,21 @@ CVS code - during wait() and can then call cancel_fork() properly. (DLR) do_delete() - Tweak for efficiency. (David Benbennick) + do_spell() + - Tweak for efficiency. (David Benbennick) + - Change the statusbar entries used in cases of failure so that + they all display the actual error that occurred. (David + Benbennick and DLR) + do_int_speller(), do_alt_speller() + - Make these functions return const char*'s instead of char*'s. + (David Benbennick) justify_format() - Remove redundant assignment. (DLR) do_para_search() - Remove unneeded edit_update() calls. (David Benbennick) do_justify() - - Remove unneeded edit_update() calls. (David Benbennick) + - Remove unneeded edit_update() calls, and add a few minor + efficiency tweaks. (David Benbennick) - Simplify an if statement. (DLR) do_exit() - Refactor so that no recursion is needed if we try to exit with @@ -170,8 +184,8 @@ CVS code - since 1.3.0. (David Benbennick) - utils.c: is_blank_char() - - Add new function is_blank_char() as an isblank() equivalent, - since isblank() is a GNU extension. (DLR) + - New function used as an isblank() equivalent, since isblank() + is a GNU extension. (DLR) nstricmp(), nstrnicmp() - Add extra blank lines for greater readability, and remove unneeded test for n's being less than zero (since it's already @@ -183,6 +197,9 @@ CVS code - nstrnicmp(). (DLR) David Benbennick: Tweak for efficiency. - Include and use only when strcasestr() is unavailable, since strcasestr() is a GNU extension. (DLR) + nstrnlen() + - New function used as a strnlen() equivalent, since strnlen() + is a GNU extension. (DLR) - winio.c: get_verbatim_kbinput() - Refactor the output in the DEBUG #ifdef. It didn't work @@ -197,11 +214,25 @@ CVS code - get_escape_seq_kbinput() - Add proper support for the keypad values and escape sequences generated by the NumLock glitch. (DLR) + get_mouseinput() + - Don't ungetch() anything if there's no control key and no meta + key defined in the shortcut we clicked. (DLR) bottombars() - Don't display any more than MAIN_VISIBLE shortcuts. Adding justification of the entire file above made the search shortcut list longer than this and hence made the shortcuts in it so short as to be almost incomprehensible. (DLR) + - Tweak for efficiency and to better handle shorter screen + widths. (David Benbennick) + - Restructure the if block used for the sentinel key values, + dynamically allocate keystr based on the number of columns + available, and make sure we can display shortcuts even when + the number of available columns is too short for any complete + one. (DLR) + onekey() + - Don't bother padding the displayed shortcuts with spaces. + (David Benbennick) + - Convert len to a size_t. (DLR) edit_add() - Minor cosmetic reformatting. Also remove unused int searched_later_lines. (DLR) @@ -210,9 +241,24 @@ CVS code - (David Benbennick) blank_titlebar() - New function used to blank the titlebar in topwin. (DLR) + blank_statusbar_refresh() + - Removed, as it's now unnecessary. (David Benbennick) + titlebar() + - Overhaul to use display_string() to display the filename, and + to better handle shorter screen widths. Also remove + now-unneeded wrefresh(topwin) calls. (David Benbennick) + DLR: Tweak to reserve enough space for "Modified" in all + cases, to make sure that the version message takes up no more + more than 1/3 of the available width, and to include a + reset_cursor() call so that the cursor is always in the right + place. bottombars() - Call blank_bottombars() instead of blank_bottomwin(). (David Benbennick) + check_statblank() + - Overhaul for efficiency, (David Benbennick) DLR: Add + reset_cursor() call to ensure that the cursor is always in the + right place. edit_refresh() - Remove apparently unneeded leaveok() calls. (David Benbennick) statusbar() @@ -228,9 +274,9 @@ CVS code - translations are done after initialization in order to avoid an error when compiling with -pedantic. (David Benbennick) - configure.ac: - - Add tests for isblank() and strcasestr(), and define - _GNU_SOURCE so that the tests work properly. Increase the - minimum required autoconf version to 2.54. (DLR) + - Add tests for isblank(), strcasestr(), and strnlen(), and + define _GNU_SOURCE so that the tests work properly. Increase + the minimum required autoconf version to 2.54. (DLR) - Reformat the test programs so that they aren't packed into fewer lines than usual, so as to make them easier to read, and remove unnecessary inclusion of stdio.h in the slang test diff --git a/configure.ac b/configure.ac index 18e3fb62..0c774f88 100644 --- a/configure.ac +++ b/configure.ac @@ -289,7 +289,7 @@ AC_MSG_WARN([*** Can not use slang when cross-compiling])), esac], [AC_MSG_RESULT(no)]) dnl Checks for functions -AC_CHECK_FUNCS(snprintf vsnprintf isblank strcasecmp strncasecmp strcasestr) +AC_CHECK_FUNCS(snprintf vsnprintf isblank strcasecmp strncasecmp strcasestr strnlen) if test "x$ac_cv_func_snprintf" = "xno" -o "xac_cv_func_vsnprintf" = "xno" then AM_PATH_GLIB_2_0(2.0.0,, diff --git a/src/files.c b/src/files.c index d0a80383..ec737597 100644 --- a/src/files.c +++ b/src/files.c @@ -1453,7 +1453,7 @@ int write_file(const char *name, int tmp, int append, int nonamechange) /* If NOFOLLOW_SYMLINKS is set, it doesn't make sense to prepend or * append to a symlink. Here we warn about the contradiction. */ if (ISSET(NOFOLLOW_SYMLINKS) && anyexists && S_ISLNK(lst.st_mode)) { - statusbar(_("Cannot prepend or append to a symlink with --nofollow set.")); + statusbar(_("Cannot prepend or append to a symlink with --nofollow set")); goto cleanup_and_exit; } @@ -2592,7 +2592,7 @@ char *do_browser(const char *inpath) char *new_path; /* Used by the Go To Directory prompt. */ - blank_statusbar_refresh(); + check_statblank(); #if !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE) currshortcut = browser_list; @@ -2951,7 +2951,7 @@ void load_history(void) if (errno != ENOENT) { /* Don't save history when we quit. */ UNSET(HISTORYLOG); - rcfile_error(_("Unable to open ~/.nano_history file, %s"), strerror(errno)); + rcfile_error(_("Unable to open ~/.nano_history file: %s"), strerror(errno)); } free(nanohist); } else { @@ -3001,28 +3001,28 @@ void save_history(void) if (homenv != NULL || userage != NULL) { hist = fopen(nanohist, "wb"); if (hist == NULL) { - rcfile_msg(_("Unable to write ~/.nano_history file, %s"), strerror(errno)); + rcfile_msg(_("Unable to write ~/.nano_history file: %s"), strerror(errno)); } else { /* set rw only by owner for security ?? */ chmod(nanohist, S_IRUSR | S_IWUSR); /* write oldest first */ - for (h = search_history.tail ; h->prev ; h = h->prev) { + for (h = search_history.tail; h->prev; h = h->prev) { h->data = charealloc(h->data, strlen(h->data) + 2); strcat(h->data, "\n"); if (fputs(h->data, hist) == EOF) { - rcfile_msg(_("Unable to write ~/.nano_history file, %s"), strerror(errno)); + rcfile_msg(_("Unable to write ~/.nano_history file: %s"), strerror(errno)); goto come_from; } } if (fputs("\n", hist) == EOF) { - rcfile_msg(_("Unable to write ~/.nano_history file, %s"), strerror(errno)); + rcfile_msg(_("Unable to write ~/.nano_history file: %s"), strerror(errno)); goto come_from; } - for (h = replace_history.tail ; h->prev ; h = h->prev) { + for (h = replace_history.tail; h->prev; h = h->prev) { h->data = charealloc(h->data, strlen(h->data) + 2); strcat(h->data, "\n"); if (fputs(h->data, hist) == EOF) { - rcfile_msg(_("Unable to write ~/.nano_history file, %s"), strerror(errno)); + rcfile_msg(_("Unable to write ~/.nano_history file: %s"), strerror(errno)); goto come_from; } } diff --git a/src/nano.c b/src/nano.c index 8246592c..d0b5501d 100644 --- a/src/nano.c +++ b/src/nano.c @@ -1531,7 +1531,7 @@ int do_int_spell_fix(const char *word) /* Integrated spell checking using 'spell' program. Return value: NULL * for normal termination, otherwise the error string. */ -char *do_int_speller(char *tempfile_name) +const char *do_int_speller(char *tempfile_name) { char *read_buff, *read_buff_ptr, *read_buff_word; size_t pipe_buff_size, read_buff_size, read_buff_read, bytesread; @@ -1717,7 +1717,7 @@ char *do_int_speller(char *tempfile_name) /* External spell checking. Return value: NULL for normal termination, * otherwise the error string. */ -char *do_alt_speller(char *tempfile_name) +const char *do_alt_speller(char *tempfile_name) { int alt_spell_status, lineno_cur = current->lineno; int x_cur = current_x, y_cur = current_y, pww_cur = placewewant; @@ -1814,11 +1814,11 @@ char *do_alt_speller(char *tempfile_name) int do_spell(void) { int i; - char *temp, *spell_msg; + char *temp = safe_tempnam(0, "nano."); + const char *spell_msg; - if ((temp = safe_tempnam(0, "nano.")) == NULL) { - statusbar(_("Could not create a temporary filename: %s"), - strerror(errno)); + if (temp == NULL) { + statusbar(_("Could not create temp file: %s"), strerror(errno)); return 0; } @@ -1830,7 +1830,7 @@ int do_spell(void) i = write_file(temp, 1, 0, 0); if (i == -1) { - statusbar(_("Spell checking failed: unable to write temp file!")); + statusbar(_("Unable to write temp file: %s"), strerror(errno)); free(temp); return 0; } @@ -1841,19 +1841,18 @@ int do_spell(void) add_open_file(1); #endif - if (alt_speller != NULL) - spell_msg = do_alt_speller(temp); - else - spell_msg = do_int_speller(temp); + spell_msg = alt_speller != NULL ? do_alt_speller(temp) : + do_int_speller(temp); unlink(temp); free(temp); if (spell_msg != NULL) { - statusbar(_("Spell checking failed: %s"), spell_msg); + statusbar(_("Spell checking failed: %s: %s"), spell_msg, + strerror(errno)); return 0; - } + } else + statusbar(_("Finished checking spelling")); - statusbar(_("Finished checking spelling")); return 1; } #endif /* !DISABLE_SPELLER */ @@ -2436,8 +2435,8 @@ int do_justify(int full_justify) int break_pos; /* Where we will break the line. */ - indent_len = indent_length(current->data + quote_len) + - quote_len; + indent_len = quote_len + indent_length(current->data + + quote_len); /* justify_format() removes excess spaces from the line, and * changes tabs to spaces. After calling it, we call @@ -2540,7 +2539,7 @@ int do_justify(int full_justify) #ifndef NANO_SMALL if (mark_beginbuf == current->next) { if (mark_beginx < indent_len + break_pos) { - mark_beginbuf = current; + mark_beginbuf = current; if (mark_beginx <= indent_len) mark_beginx = line_len + 1; else @@ -2616,7 +2615,6 @@ int do_justify(int full_justify) /* Now get a keystroke and see if it's unjustify; if not, unget the * keystroke and return. */ - { int meta_key; i = get_kbinput(edit, &meta_key); @@ -2624,11 +2622,10 @@ int do_justify(int full_justify) /* If it was a mouse click, parse it with do_mouse() and it * might become the unjustify key. Else give it back to the * input stream. */ - if (i == KEY_MOUSE) + if (i == KEY_MOUSE) { do_mouse(); - else - ungetch(i); - i = get_kbinput(edit, &meta_key); + i = get_kbinput(edit, &meta_key); + } #endif } @@ -2655,7 +2652,6 @@ int do_justify(int full_justify) cutbuffer->prev->next = cutbuffer; } else fileage = cutbuffer; - cutbuffer = NULL; last_par_line->next = NULL; free_filestruct(first_par_line); @@ -2668,14 +2664,13 @@ int do_justify(int full_justify) mark_beginx = mark_beginx_save; #endif flags = flags_save; - if (!ISSET(MODIFIED)) { + if (!ISSET(MODIFIED)) titlebar(NULL); - wrefresh(topwin); - } edit_refresh(); } cutbuffer = cutbuffer_save; - blank_statusbar_refresh(); + /* Note that now cutbottom is invalid, but that's okay. */ + blank_statusbar(); /* Display the shortcut list with UnCut. */ shortcut_init(0); display_main_list(); diff --git a/src/nano.h b/src/nano.h index c979a27d..3a9386e6 100644 --- a/src/nano.h +++ b/src/nano.h @@ -92,8 +92,8 @@ # endif #endif -/* If no isblank(), strcasecmp(), strncasecmp(), or strcasestr(), use - * the versions we have. */ +/* If no isblank(), strcasecmp(), strncasecmp(), strcasestr(), or + * strnlen(), use the versions we have. */ #ifndef HAVE_ISBLANK #define isblank is_blank_char #endif @@ -110,6 +110,10 @@ #define strcasestr nstristr #endif +#ifndef HAVE_STRNLEN +#define strnlen nstrnlen +#endif + /* Assume ERR is defined as -1. To avoid duplicate case values when * some key definitions are missing, we have to set all of these, and * all of the special sentinel values below, to different negative diff --git a/src/proto.h b/src/proto.h index a3cf85c2..becfc7e2 100644 --- a/src/proto.h +++ b/src/proto.h @@ -295,8 +295,8 @@ int do_wrap(filestruct *inptr); #endif #ifndef DISABLE_SPELLER int do_int_spell_fix(const char *word); -char *do_int_speller(char *tempfile_name); -char *do_alt_speller(char *tempfile_name); +const char *do_int_speller(char *tempfile_name); +const char *do_alt_speller(char *tempfile_name); int do_spell(void); #endif #if !defined(DISABLE_WRAPPING) && !defined(NANO_SMALL) || !defined(DISABLE_JUSTIFY) @@ -447,6 +447,9 @@ const char *revstrstr(const char *haystack, const char *needle, const const char *revstristr(const char *haystack, const char *needle, const char *rev_start); #endif +#ifndef HAVE_STRNLEN +size_t nstrnlen(const char *s, size_t maxlen); +#endif const char *strstrwrapper(const char *haystack, const char *needle, const char *start); void nperror(const char *s); @@ -484,7 +487,6 @@ size_t strlenpt(const char *buf); void blank_titlebar(void); void blank_edit(void); void blank_statusbar(void); -void blank_statusbar_refresh(void); void check_statblank(void); void blank_bottombars(void); char *display_string(const char *buf, size_t start_col, size_t len); @@ -502,7 +504,7 @@ void titlebar(const char *path); void set_modified(void); void statusbar(const char *msg, ...); void bottombars(const shortcut *s); -void onekey(const char *keystroke, const char *desc, int len); +void onekey(const char *keystroke, const char *desc, size_t len); #ifndef NDEBUG int check_linenumbers(const filestruct *fileptr); #endif diff --git a/src/search.c b/src/search.c index 588111f8..0102cfe3 100644 --- a/src/search.c +++ b/src/search.c @@ -539,7 +539,7 @@ char *replace_line(const char *needle) /* Calculate the size of the new line. */ #ifdef HAVE_REGEX_H if (ISSET(USE_REGEXP)) { - search_match_count = regmatches[0].rm_eo - regmatches[0].rm_so; + search_match_count = regmatches[0].rm_eo - regmatches[0].rm_so; new_line_size = replace_regexp(NULL, 0); } else { #endif diff --git a/src/utils.c b/src/utils.c index 4e5cbe0b..f18d11dd 100644 --- a/src/utils.c +++ b/src/utils.c @@ -209,6 +209,21 @@ const char *revstristr(const char *haystack, const char *needle, const } #endif /* !NANO_SMALL */ +#ifndef HAVE_STRNLEN +/* This function is equivalent to strnlen(). */ +size_t nstrnlen(const char *s, size_t maxlen) +{ + size_t n = 0; + + assert(s != NULL); + + for (; maxlen > 0 && *s != '\0'; maxlen--, n++, s++) + ; + + return n; +} +#endif + /* If we are searching backwards, we will find the last match that * starts no later than start. Otherwise we find the first match * starting no earlier than start. If we are doing a regexp search, we diff --git a/src/winio.c b/src/winio.c index 2ca439c5..d5a4879c 100644 --- a/src/winio.c +++ b/src/winio.c @@ -1002,7 +1002,7 @@ int get_mouseinput(int *mouse_x, int *mouse_y, int allow_shortcuts) * both. */ if (s->ctrlval != NANO_NO_KEY) ungetch(s->ctrlval); - else { + else if (s->ctrlval != NANO_NO_KEY) { ungetch(s->metaval); ungetch(NANO_CONTROL_3); } @@ -1109,19 +1109,16 @@ void blank_statusbar(void) mvwaddstr(bottomwin, 0, 0, hblank); } -void blank_statusbar_refresh(void) -{ - blank_statusbar(); - wrefresh(bottomwin); -} - void check_statblank(void) { if (statblank > 1) statblank--; else if (statblank == 1 && !ISSET(CONSTUPDATE)) { - statblank--; - blank_statusbar_refresh(); + statblank = 0; + blank_statusbar(); + wnoutrefresh(bottomwin); + reset_cursor(); + wrefresh(edit); } } @@ -1544,50 +1541,143 @@ int nanogetstr(int allowtabs, const char *buf, const char *def, void titlebar(const char *path) { - int namelen, space; - const char *what = path; - - if (path == NULL) - what = filename; + size_t space; + /* The space we have available for display. */ + size_t verlen = strlen(VERMSG) + 1; + /* The length of the version message. */ + const char *prefix; + /* "File:", "Dir:", or "New Buffer". Goes before filename. */ + size_t prefixlen; + /* strlen(prefix) + 1. */ + const char *state; + /* "Modified", "View", or spaces the length of "Modified". + * Tells the state of this buffer. */ + size_t statelen = 0; + /* strlen(state) + 1. */ + char *exppath = NULL; + /* The file name, expanded for display. */ + size_t explen = 0; + /* strlen(exppath) + 1. */ + int newbuffer = FALSE; + /* Do we say "New Buffer"? */ + int dots = FALSE; + /* Do we put an ellipsis before the path? */ + + assert(path != NULL || filename != NULL); + assert(COLS >= 0); wattron(topwin, A_REVERSE); blank_titlebar(); - mvwaddnstr(topwin, 0, 2, VERMSG, COLS - 3); - space = COLS - sizeof(VERMSG) - 23; + if (COLS <= 5 || COLS - 5 < verlen) + space = 0; + else { + space = COLS - 5 - verlen; + /* Reserve 2/3 of the screen for after the version message. */ + if (space < COLS - (COLS / 3)) + space = COLS - (COLS / 3); + } - namelen = strlen(what); + if (COLS > 4) { + /* The version message should only take up 1/3 of the screen. */ + mvwaddnstr(topwin, 0, 2, VERMSG, COLS / 3); + waddstr(topwin, " "); + } - if (space > 0) { - if (what[0] == '\0') - mvwaddnstr(topwin, 0, COLS / 2 - 6, _("New Buffer"), - COLS / 2 + COLS % 2 - 6); - else if (namelen > space) { - if (path == NULL) - waddstr(topwin, _(" File: ...")); - else - waddstr(topwin, _(" DIR: ...")); - waddstr(topwin, &what[namelen - space]); - } else { - if (path == NULL) - mvwaddstr(topwin, 0, COLS / 2 - (namelen / 2 + 1), - _("File: ")); - else - mvwaddstr(topwin, 0, COLS / 2 - (namelen / 2 + 1), - _(" DIR: ")); - waddstr(topwin, what); - } - } /* If we don't have space, we shouldn't bother */ if (ISSET(MODIFIED)) - mvwaddnstr(topwin, 0, COLS - 11, _(" Modified "), 11); - else if (ISSET(VIEW_MODE)) - mvwaddnstr(topwin, 0, COLS - 11, _(" View "), 11); + state = _("Modified"); + else if (path == NULL && ISSET(VIEW_MODE)) + state = _("View"); + else { + if (space > 0) + statelen = strnlen(_("Modified"), space - 1) + 1; + state = &hblank[COLS - statelen]; + } + statelen = strnlen(state, COLS); + /* We need a space before state. */ + if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS) + statelen++; + + assert(space >= 0); + if (space == 0 || statelen >= space) + goto the_end; + +#ifndef DISABLE_BROWSER + if (path != NULL) + prefix = _("DIR:"); + else +#endif + if (filename[0] == '\0') { + prefix = _("New Buffer"); + newbuffer = TRUE; + } else + prefix = _("File:"); + assert(statelen < space); + prefixlen = strnlen(prefix, space - statelen); + /* If newbuffer is FALSE, we need a space after prefix. */ + if (!newbuffer && prefixlen + statelen < space) + prefixlen++; + + if (path == NULL) + path = filename; + if (space > prefixlen + statelen) + space -= prefixlen + statelen; + else + space = 0; + /* space is now the room we have for the file name. */ + if (!newbuffer) { + size_t lenpt = strlenpt(path), start_col; + + if (lenpt > space) + start_col = actual_x(path, lenpt - space); + else + start_col = 0; + exppath = display_string(path, start_col, space); + dots = (lenpt > space); + explen = strlen(exppath); + } + + if (!dots) { + /* There is room for the whole filename, so we center it. */ + waddnstr(topwin, hblank, (space - explen) / 3); + waddnstr(topwin, prefix, prefixlen); + if (!newbuffer) { + assert(strlen(prefix) + 1 == prefixlen); + waddch(topwin, ' '); + waddstr(topwin, exppath); + } + } else { + /* We will say something like "File: ...ename". */ + waddnstr(topwin, prefix, prefixlen); + if (space == 0 || newbuffer) + goto the_end; + waddch(topwin, ' '); + waddnstr(topwin, "...", space); + if (space <= 3) + goto the_end; + space -= 3; + assert(explen = space + 3); + waddnstr(topwin, exppath + 3, space); + } + + the_end: + + free(exppath); + + if (COLS <= 1 || statelen >= COLS - 1) + mvwaddnstr(topwin, 0, 0, state, COLS); + else { + assert(COLS - statelen - 2 >= 0); + mvwaddch(topwin, 0, COLS - statelen - 2, ' '); + mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen); + } wattroff(topwin, A_REVERSE); - wrefresh(topwin); + wnoutrefresh(topwin); reset_cursor(); + wrefresh(edit); } /* If modified is not already set, set it and update titlebar. */ @@ -1596,7 +1686,6 @@ void set_modified(void) if (!ISSET(MODIFIED)) { SET(MODIFIED); titlebar(NULL); - wrefresh(topwin); } } @@ -1650,79 +1739,75 @@ void statusbar(const char *msg, ...) void bottombars(const shortcut *s) { - int i, j, numcols; - char keystr[9]; - int slen; + size_t i, colwidth, slen; + char *keystr; if (ISSET(NO_HELP)) return; if (s == main_list) { slen = MAIN_VISIBLE; - assert(MAIN_VISIBLE <= length_of_list(s)); + assert(slen <= length_of_list(s)); } else { slen = length_of_list(s); - /* Don't show any more shortcuts than the main list does */ + /* Don't show any more shortcuts than the main list does. */ if (slen > MAIN_VISIBLE) slen = MAIN_VISIBLE; } - /* There will be this many columns of shortcuts */ - numcols = (slen + (slen % 2)) / 2; + /* There will be this many characters per column. We need at least + * 3 to display anything properly.*/ + colwidth = COLS / ((slen / 2) + (slen % 2)); + keystr = charalloc(colwidth); blank_bottombars(); - for (i = 0; i < numcols; i++) { - for (j = 0; j <= 1; j++) { - - wmove(bottomwin, 1 + j, i * (COLS / numcols)); + for (i = 0; i < slen; i++, s = s->next) { + wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth); - /* Yucky sentinel values we can't handle a better way */ - if (s->ctrlval != NANO_NO_KEY) { + /* Yucky sentinel values we can't handle a better way. */ #ifndef NANO_SMALL - if (s->ctrlval == NANO_HISTORY_KEY) - strncpy(keystr, _("Up"), 8); - else + if (s->ctrlval == NANO_HISTORY_KEY) + strncpy(keystr, _("Up"), colwidth); + else #endif - if (s->ctrlval == NANO_CONTROL_SPACE) - strcpy(keystr, "^ "); - else if (s->ctrlval == NANO_CONTROL_8) - strcpy(keystr, "^?"); - else - sprintf(keystr, "^%c", s->ctrlval + 64); - } else if (s->metaval != NANO_NO_KEY) - sprintf(keystr, "M-%c", toupper(s->metaval)); - - onekey(keystr, s->desc, COLS / numcols); - - s = s->next; - if (s == NULL) - goto break_completely_out; - } + if (s->ctrlval == NANO_CONTROL_SPACE) + strncpy(keystr, "^ ", colwidth); + else if (s->ctrlval == NANO_CONTROL_8) + strncpy(keystr, "^?", colwidth); + /* Normal values. Assume that the shortcut has an equivalent + * control key, meta key sequence, or both. */ + else if (s->ctrlval != NANO_NO_KEY) + snprintf(keystr, colwidth, "^%c", s->ctrlval + 64); + else if (s->metaval != NANO_NO_KEY) + snprintf(keystr, colwidth, "M-%c", toupper(s->metaval)); + + onekey(keystr, s->desc, colwidth); } - break_completely_out: - wrefresh(bottomwin); + free(keystr); + + wnoutrefresh(bottomwin); + reset_cursor(); + wrefresh(edit); } -/* Write a shortcut key to the help area at the bottom of the window. - * keystroke is e.g. "^G" and desc is e.g. "Get Help". - * We are careful to write exactly len characters, even if len is - * very small and keystroke and desc are long. */ -void onekey(const char *keystroke, const char *desc, int len) +/* Write a shortcut key to the help area at the bottom of the window. + * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful + * to write at most len characters, even if len is very small and + * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds + * the whole string! We do not bother padding the entry with blanks. */ +void onekey(const char *keystroke, const char *desc, size_t len) { + assert(keystroke != NULL && desc != NULL && len >= 0); wattron(bottomwin, A_REVERSE); waddnstr(bottomwin, keystroke, len); wattroff(bottomwin, A_REVERSE); - len -= strlen(keystroke); + len -= strlen(keystroke) + 1; if (len > 0) { waddch(bottomwin, ' '); - len--; waddnstr(bottomwin, desc, len); - len -= strlen(desc); - for (; len > 0; len--) - waddch(bottomwin, ' '); } } @@ -2330,7 +2415,7 @@ int do_yesno(int all, const char *msg) nostr = _("Nn"); allstr = _("Aa"); - /* Remove gettext call for keybindings until we clear the thing + /* Remove gettext() call for keybindings until we clear the thing * up. */ if (!ISSET(NO_HELP)) { char shortstr[3]; /* Temp string for Y, N, A. */ -- 2.39.5