From 07017111d17fa62c97ab1ade6c893f3295c578c1 Mon Sep 17 00:00:00 2001
From: Rishabh Dave <rishabhddave@gmail.com>
Date: Thu, 6 Oct 2016 21:30:02 +0530
Subject: [PATCH] feature: add search facility to help

One can now search in help by pressing "S" in help menu. The first
occurence of the string will be indicated by making that line as the
first line on the screen

Signed-off-by: Rishabh Dave <rishabhddave@gmail.com>
---
 src/help.c  | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/nano.h  |   4 +-
 src/proto.h |   1 +
 3 files changed, 155 insertions(+), 1 deletion(-)

diff --git a/src/help.c b/src/help.c
index b694192..18a3e9a 100644
--- a/src/help.c
+++ b/src/help.c
@@ -35,6 +35,132 @@ static char *end_of_intro = NULL;
 	/* The point in the help text where the introductory paragraphs end
 	 * and the shortcut descriptions begin. */
 
+int searchhelp_init(void)
+{
+    int input;
+    char *buf;
+
+    if (*last_search != '\0') {
+	char *disp = display_string(last_search, 0, COLS / 3, FALSE);
+
+	buf = charalloc(strlen(disp) + 7);
+	/* We use (COLS / 3) here because we need to see more on the line. */
+	sprintf(buf, " [%s%s]", disp,
+	    (strlenpt(last_search) > COLS / 3) ? "..." : "");
+	free(disp);
+    } else
+	/* buf will contain last search.*/
+	buf = mallocstrcpy(NULL, "");
+
+    input = do_prompt(FALSE,
+#ifndef DISABLE_TABCOMP
+                FALSE,
+#endif
+                MSEARCHHELP, NULL,
+#ifndef DISABLE_HISTORIES
+                &search_history,
+#endif
+                edit_refresh, "%s%s", _("Search"), buf);
+
+    /* Release buf now. */
+    free(buf);
+
+    /* If only Enter was pressed but we have a previous string, it's okay. */
+    if (input == -2 && *last_search != '\0')
+	return 0;
+
+    /* Otherwise negative inputs are a bailout. */
+    if (input < -1)
+        statusbar(_("Cancelled"));
+
+    return input;
+}
+
+int do_searchhelp()
+{
+    int input = searchhelp_init();
+    if (input != 0)
+	return -1;
+
+//1. Haven't understood why input can be non-zero and positive -- the meaning
+//   of "return input" in searchhelp_init() (ie filesearch_init()).
+
+    /* If answer is now "", copy last_search into answer. */
+    if (*answer == '\0')
+	answer = mallocstrcpy(answer, last_search);
+    else
+	last_search = mallocstrcpy(last_search, answer);
+
+#ifndef DISABLE_HISTORIES
+    /* If answer is not empty, add the string to the search history list. */
+    if (*answer != '\0')
+	update_history(&search_history, answer);
+#endif
+
+    char c, word[50];
+    int i = 0, screenlineno = 0;
+    /* screenlineno is initialized to 0 because line numbers in windows
+     * begin with zero. */
+    int charinlineno = 1, columnno = 1;
+    /* Count of character/column number must begin with. */
+    FILE *fp = fopen("help.txt", "r");
+
+    while ((c = fgetc(fp)) != EOF) {
+	/* For the sake of allowing to search key combinations in second
+	 * column, never consider parenthesis. */
+	if (c != ' ' && c != '\t' && c != '\n') {
+	    if (c == '(' || c == ')')
+		continue;
+	    else
+		word[i++] = c;
+	} else if (c == ' ' || c == '\t' || c == '\n') {
+	    /* If we have any characters in 'word', then compare. */
+	    if (i != 0) {
+		if (strcmp(word, answer) == 0) {
+		    /* Needle found. */
+		    return screenlineno;
+
+//Just in case we find a way to move cursor along columns.
+		    if (screenlineno > 18) {
+			if (charinlineno < 7)
+			    columnno = charinlineno - strlen(answer) - 2;
+			else if (charinlineno < 18)
+			    columnno = charinlineno - strlen(answer);
+			else
+			    columnno = charinlineno - 1;
+	            } else
+			columnno = charinlineno - strlen(answer);
+
+		    break;
+//Code above is dead code; read above comment.
+		}
+		/* Since, we have a word in variable 'word' but it is not
+		 * the word we are looking for, make it ready for future
+		 * use. */
+		for (int j = 0; j <= i; ++j)
+		    word[j] = '\0';
+		i = 0;
+	    }
+
+	    if (c == '\n') {
+		++screenlineno;
+		charinlineno = 1;
+	    }
+	}
+
+	++charinlineno;
+	/* When we exceed 74 characters, we would be on a new line on the
+	 * help screen. */
+	if (charinlineno > 74) {
+	    ++screenlineno;
+	    charinlineno = 1;
+	}
+    }
+
+    fclose(fp);
+    return -1;
+}
+
 /* Our main help-viewer function. */
 void do_help(void)
 {
@@ -75,11 +201,19 @@ void do_help(void)
     bottombars(MHELP);
     wnoutrefresh(bottomwin);
 
+    bool first_iteration = TRUE;
     while (TRUE) {
 	size_t i;
 
 	ptr = help_text;
 
+	if (first_iteration) {
+	    first_iteration = FALSE;
+	    FILE *fp = fopen("help.txt", "w");
+	    fprintf(fp, ptr);
+	    fclose(fp);
+	}
+
 	/* 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);
@@ -163,6 +297,21 @@ void do_help(void)
 	} else if (func == do_exit) {
 	    /* Exit from the help viewer. */
 	    break;
+	} else if (func == (void *)do_searchhelp) {
+	    oldmenu = currmenu;
+	    int screenlineno = do_searchhelp();
+	    bottombars(oldmenu);
+
+	    /* Make the line containing needle as the first line of the
+	     * window. */
+	    if (line > screenlineno)
+		while (line > screenlineno)
+		    --line;
+	    else if (line < screenlineno)
+		while (line < screenlineno)
+		    ++line;
+	    else
+		;
 	} else
 	    unbound_key(kbinput);
     }
@@ -487,6 +636,8 @@ functionptrtype parse_help_input(int *kbinput)
 	    case 'E':
 	    case 'e':
 		return do_exit;
+	   case 'S':
+		return (void *)do_searchhelp;
 	}
     }
     return func_from_key(kbinput);
diff --git a/src/nano.h b/src/nano.h
index 474e8c2..bab040b 100644
--- a/src/nano.h
+++ b/src/nano.h
@@ -555,9 +555,11 @@ enum
 #define MGOTODIR		(1<<12)
 #define MYESNO			(1<<13)
 #define MLINTER			(1<<14)
+#define MSEARCHHELP		(1<<15)
 /* This is an abbreviation for all menus except Help and YesNo. */
 #define MMOST  (MMAIN|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE|MWRITEFILE|MINSERTFILE|\
-		MEXTCMD|MBROWSER|MWHEREISFILE|MGOTODIR|MSPELL|MLINTER)
+		MEXTCMD|MBROWSER|MWHEREISFILE|MGOTODIR|MSPELL|MLINTER|\
+		MSEARCHHELP)
 
 /* Basic control codes. */
 #define TAB_CODE  0x09
diff --git a/src/proto.h b/src/proto.h
index e5588e9..83f093b 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -385,6 +385,7 @@ void thanks_for_all_the_fish(void);
 
 /* All functions in help.c. */
 #ifndef DISABLE_HELP
+int do_searchhelp();
 void do_help(void);
 void help_init(void);
 functionptrtype parse_help_input(int *kbinput);
-- 
2.7.4

