From c1bfead58f4b943a6f694accb3de6ae3a1fd0427 Mon Sep 17 00:00:00 2001 From: Rishabh Dave Date: Tue, 25 Oct 2016 21:26:12 +0530 Subject: [PATCH] feature: add search facility to help Allow user to search all help text with ^W. This accomplishes https://savannah.gnu.org/bugs/?28994. --- src/files.c | 6 +- src/global.c | 8 +-- src/help.c | 227 ++++++++++++++++++++++++++++++++--------------------------- src/prompt.c | 10 ++- src/winio.c | 16 +++-- 5 files changed, 148 insertions(+), 119 deletions(-) diff --git a/src/files.c b/src/files.c index a4ac750..c94ed2c 100644 --- a/src/files.c +++ b/src/files.c @@ -553,8 +553,10 @@ void replace_buffer(const char *filename) /* Update the screen to account for the current buffer. */ void display_buffer(void) { - /* Update the titlebar, since the filename may have changed. */ - titlebar(NULL); + /* Update the titlebar, since the filename may have changed. In case, + * MHELP, titlebar() in done in help.c. */ + if (currmenu != MHELP) + titlebar(NULL); #ifndef DISABLE_COLOR /* Make sure we're using the buffer's associated colors. */ diff --git a/src/global.c b/src/global.c index dd2e71a..df059e2 100644 --- a/src/global.c +++ b/src/global.c @@ -694,7 +694,7 @@ void shortcut_init(void) #endif } - add_to_funcs(do_search, MMAIN, + add_to_funcs(do_search, MMAIN|MHELP, whereis_tag, IFSCHELP(nano_whereis_msg), TOGETHER, VIEW); add_to_funcs(do_replace, MMAIN, @@ -713,8 +713,6 @@ void shortcut_init(void) * because the help viewer does not have a help text. */ add_to_funcs(do_exit, MHELP, exit_tag, "x", 0, VIEW); - add_to_funcs(total_refresh, MHELP, refresh_tag, "x", 0, VIEW); - add_to_funcs(do_up_void, MHELP, prev_line_tag, "x", 0, VIEW); add_to_funcs(do_down_void, MHELP, next_line_tag, "x" , 0, VIEW); #endif @@ -1045,8 +1043,8 @@ void shortcut_init(void) add_to_sclist(MMAIN, "^R", 0, do_insertfile_void, 0); add_to_sclist(MMAIN, "F5", 0, do_insertfile_void, 0); add_to_sclist(MMAIN, "Ins", 0, do_insertfile_void, 0); - add_to_sclist(MMAIN|MBROWSER, "^W", 0, do_search, 0); - add_to_sclist(MMAIN|MBROWSER, "F6", 0, do_search, 0); + add_to_sclist(MMAIN|MBROWSER|MHELP, "^W", 0, do_search, 0); + add_to_sclist(MMAIN|MBROWSER|MHELP, "F6", 0, do_search, 0); add_to_sclist(MMAIN, "^\\", 0, do_replace, 0); add_to_sclist(MMAIN, "M-R", 0, do_replace, 0); add_to_sclist(MMAIN, "F14", 0, do_replace, 0); diff --git a/src/help.c b/src/help.c index b694192..e874210 100644 --- a/src/help.c +++ b/src/help.c @@ -25,6 +25,7 @@ #include #include #include +#include #ifndef DISABLE_HELP @@ -40,31 +41,30 @@ void do_help(void) { int kbinput = ERR; bool old_no_help = ISSET(NO_HELP); - size_t line = 0; - /* The line number in help_text of the first displayed help - * line. This variable is zero-based. */ - size_t last_line = 0; - /* The line number in help_text of the last help line. This - * variable is zero-based. */ int oldmenu = currmenu; /* The menu we were called from. */ - const char *ptr; - /* The current line of the help text. */ - size_t old_line = (size_t)-1; - /* The line we were on before the current line. */ functionptrtype func; /* The function of the key the user typed in. */ - /* Don't show a cursor in the help screen. */ - curs_set(0); - blank_edit(); - blank_statusbar(); - /* Set help_text as the string to display. */ help_init(); assert(help_text != NULL); + FILE *fp; + char *tempfilename = safe_tempfile(&fp); + if (tempfilename == NULL) { + statusline(ALERT, _("Error writing temp file: %s"), strerror(errno)); + return; + } + fprintf(fp, "%s", help_text); + rewind(fp); + char *title = charalloc(50 * sizeof(char)); + title = fgets(title, 50, fp); + if (title[strlen(title) - 1] == '\n') + title[strlen(title) - 1] = '\0'; + fclose(fp); + if (ISSET(NO_HELP)) { /* Make sure that the help screen's shortcut list will actually * be displayed. */ @@ -75,48 +75,17 @@ void do_help(void) bottombars(MHELP); wnoutrefresh(bottomwin); - while (TRUE) { - size_t i; - - ptr = help_text; - - /* Find the line number of the last line of the help text. */ - for (last_line = 0; *ptr != '\0'; last_line++) { - ptr += help_line_len(ptr); - if (*ptr == '\n') - ptr++; - } - - if (last_line > 0) - last_line--; - - /* Redisplay if the text was scrolled or an invalid key was pressed. */ - if (line != old_line || kbinput == ERR) { - blank_edit(); - - ptr = help_text; - - /* Advance in the text to the first line to be displayed. */ - for (i = 0; i < line; i++) { - ptr += help_line_len(ptr); - if (*ptr == '\n') - ptr++; - } - - /* Now display as many lines as the window will hold. */ - for (i = 0; i < editwinrows && *ptr != '\0'; i++) { - size_t j = help_line_len(ptr); - - mvwaddnstr(edit, i, 0, ptr, j); - ptr += j; - if (*ptr == '\n') - ptr++; - } - } - - wnoutrefresh(edit); + if (!ISSET(MULTIBUFFER)) { + SET(MULTIBUFFER); + open_buffer(tempfilename, FALSE); + UNSET(MULTIBUFFER); + } else + open_buffer(tempfilename, FALSE); - old_line = line; + display_buffer(); + titlebar(title); + while (TRUE) { + edit_refresh(); lastmessage = HUSH; @@ -128,7 +97,6 @@ void do_help(void) continue; /* Redraw the screen. */ } #endif - #ifndef DISABLE_MOUSE if (kbinput == KEY_MOUSE) { int mouse_x, mouse_y; @@ -142,27 +110,31 @@ void do_help(void) if (func == total_refresh) { total_redraw(); } else if (func == do_up_void) { - if (line > 0) - line--; + do_up(TRUE); } else if (func == do_down_void) { - if (line + (editwinrows - 1) < last_line) - line++; + do_down(TRUE); } else if (func == do_page_up) { - if (line > editwinrows - 2) - line -= editwinrows - 2; - else - line = 0; + do_page_up(); } else if (func == do_page_down) { - if (line + (editwinrows - 1) < last_line) - line += editwinrows - 2; + do_page_down(); } else if (func == do_first_line) { - line = 0; + do_first_line(); } else if (func == do_last_line) { - if (line + (editwinrows - 1) < last_line) - line = last_line - (editwinrows - 1); + do_last_line(); } else if (func == do_exit) { /* Exit from the help viewer. */ + close_buffer(); break; + } else if (func == do_search) { + if (answer != NULL) { + char *answer_copy = strdup(answer); + do_search(); + answer = mallocstrcpy(answer, answer_copy); + free(answer_copy); + } else + do_search(); + bottombars(MHELP); + wnoutrefresh(bottomwin); } else unbound_key(kbinput); } @@ -183,6 +155,9 @@ void do_help(void) #endif edit_refresh(); + remove(tempfilename); + free(tempfilename); + free(title); /* We're exiting from the help screen. */ free(help_text); } @@ -388,12 +363,83 @@ void help_init(void) /* Allocate space for the help text. */ help_text = charalloc(allocsize + 1); - /* Now add the text we want. */ - strcpy(help_text, htx[0]); - if (htx[1] != NULL) - strcat(help_text, htx[1]); - if (htx[2] != NULL) - strcat(help_text, htx[2]); + /* Add the paragraph/s to the help_text. */ + int i, line_size; + /* Get rid of garbage value for the sake of strlen(help_text). */ + for (i = 0; i <= allocsize; ++i) + help_text[i] = '\0'; + + i = 0; + const char *p = htx[0]; + int txtlen = strlen(htx[0]); + while (txtlen > 0) { + size_t wrapping_point = (COLS > 24) ? COLS - 1 : 24; + if (COLS > 74) + wrapping_point = 74; + + /* Make sure we have space at the beginning of each line we print. + * And, spare the title for the sake of standard format. */ + if (p[0] != ' ' && p[0] != htx[0][0]) { + strcpy(help_text + strlen(help_text), " "); + line_size = break_line(p, wrapping_point - 1, TRUE); + } else + line_size = break_line(p, wrapping_point, TRUE); + + strncpy(help_text + strlen(help_text), p, line_size); + p += line_size; + + /* If there are newlines at the end of htx, add them to help_text. */ + if (*p == '\n') + while (*p == '\n') { + help_text[strlen(help_text)] = '\n'; + ++line_size; + ++p; + } + /* Add text from next htx in current line, if it can take more. */ + else if (line_size < wrapping_point - 10 && i < 2 && htx[++i] != NULL) { + p = htx[i]; + txtlen = strlen(htx[i]); + + if (p[0] != ' ') { + strcpy(help_text + strlen(help_text), " "); + line_size = break_line(p, wrapping_point - line_size - 1, TRUE); + } else + line_size = break_line(p, wrapping_point - line_size, TRUE); + + strncpy(help_text + strlen(help_text), p, line_size); + help_text[strlen(help_text)] = '\n'; + p += line_size; + /* If it can't, continue on a new line. */ + } else if (txtlen <= wrapping_point && i < 2 && htx[++i] != NULL) { + help_text[strlen(help_text)] = '\n'; + p = htx[i]; + txtlen = strlen(htx[i]); + + if (p[0] != ' ') { + strcpy(help_text + strlen(help_text), " "); + line_size = break_line(p, wrapping_point - 1, TRUE); + } else + line_size = break_line(p, wrapping_point, TRUE); + + strncpy(help_text + strlen(help_text), p, line_size); + help_text[strlen(help_text)] = '\n'; + p += line_size; + /* Neither current line can't take more, nor there is need for + * new htx. */ + } else { + help_text[strlen(help_text)] = '\n'; + ++line_size; + } + + txtlen -= line_size; + /* Current htx is done, current paragraph is done but another + * htx is waiting. */ + if (txtlen <= 0) + if (i < 2 && htx[++i] != NULL) { + p = htx[i]; + txtlen = strlen(htx[i]); + } + } ptr = help_text + strlen(help_text); @@ -492,35 +538,6 @@ functionptrtype parse_help_input(int *kbinput) return func_from_key(kbinput); } -/* Calculate the displayable length of the help-text line starting at ptr. */ -size_t help_line_len(const char *ptr) -{ - size_t wrapping_point = (COLS > 24) ? COLS - 1 : 24; - /* The target width for wrapping long lines. */ - ssize_t wrap_location; - /* Actual position where the line can be wrapped. */ - size_t length = 0; - /* Full length of the line, until the first newline. */ - - /* Avoid overwide paragraphs in the introductory text. */ - if (ptr < end_of_intro && COLS > 74) - wrapping_point = 74; - - wrap_location = break_line(ptr, wrapping_point, TRUE); - - /* Get the length of the entire line up to a null or a newline. */ - while (*(ptr + length) != '\0' && *(ptr + length) != '\n') - length = move_mbright(ptr, length); - - /* If the entire line will just fit the screen, don't wrap it. */ - if (strnlenpt(ptr, length) <= wrapping_point + 1) - return length; - else if (wrap_location > 0) - return wrap_location; - else - return 0; -} - #endif /* !DISABLE_HELP */ /* Start the help viewer. */ diff --git a/src/prompt.c b/src/prompt.c index 34e7b4c..65a9314 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -662,9 +662,17 @@ int do_prompt(bool allow_tabs, #endif /* Save a possible current statusbar x position. */ size_t was_statusbar_x = statusbar_x; + char *prompt_save = NULL; + /* In case we need prompt again before completing previous one, + * above variables become useful. */ bottombars(menu); + if (prompt != NULL) { + prompt_save = strdup(prompt); + free(prompt); + } + answer = mallocstrcpy(answer, curranswer); #ifndef NANO_TINY @@ -687,7 +695,7 @@ int do_prompt(bool allow_tabs, refresh_func); free(prompt); - prompt = NULL; + prompt = prompt_save; #ifndef NANO_TINY if (retval == KEY_WINCH) diff --git a/src/winio.c b/src/winio.c index 18f98f0..e265a5a 100644 --- a/src/winio.c +++ b/src/winio.c @@ -1913,10 +1913,11 @@ char *display_string(const char *buf, size_t start_col, size_t span, /* If path is NULL, we're in normal editing mode, so display the current * version of nano, the current filename, and whether the current file - * has been modified on the titlebar. If path isn't NULL, we're in the - * file browser, and path contains the directory to start the file - * browser in, so display the current version of nano and the contents - * of path on the titlebar. */ + * has been modified on the titlebar. If path isn't NULL, either we're + * in the file browser or help. If we are in file browser, path contains + * the directory to start the file browser in, so display the current + * version of nano and the contents of path on the titlebar. If we are + * in help, path contains the name of title of the help text. */ void titlebar(const char *path) { size_t verlen, prefixlen, pathlen, statelen; @@ -1926,7 +1927,7 @@ void titlebar(const char *path) 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 "". */ + /* What is shown before the path -- "File:", "Help:", "DIR:", or "". */ const char *state = ""; /* The state of the current buffer -- "Modified", "View", or "". */ char *fragment; @@ -1948,7 +1949,10 @@ void titlebar(const char *path) /* Figure out the path, prefix and state strings. */ #ifndef DISABLE_BROWSER - if (path != NULL) + if (currmenu == MHELP && path != NULL) { + prefix = _("Help:"); + state = _("View"); + } else if (path != NULL) prefix = _("DIR:"); else #endif -- 2.7.4