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