From 5e263ecd27b513638e009dbaa5502b3e1630ddc0 Mon Sep 17 00:00:00 2001 From: "sumedh.pendurkar" Date: Fri, 14 Oct 2016 01:29:14 +0530 Subject: [PATCH] Just a preview of statusbar that allows user to select words --- src/global.c | 7 ++- src/text.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/winio.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 280 insertions(+), 2 deletions(-) diff --git a/src/global.c b/src/global.c index 029b68b..9bcf57f 100644 --- a/src/global.c +++ b/src/global.c @@ -246,6 +246,7 @@ size_t length_of_list(int menu) #define TOGETHER FALSE /* Just throw this here. */ +void auto_complete_void(void); void case_sens_void(void) { } @@ -483,6 +484,7 @@ const char *unjust_tag = N_("Unjustify"); /* Initialize the list of functions and the list of shortcuts. */ void shortcut_init(void) { + const char *auto_complete_tag = N_("Auto Complete"); const char *read_file_tag = N_("Read File"); const char *whereis_tag = N_("Where Is"); const char *replace_tag = N_("Replace"); @@ -526,6 +528,7 @@ void shortcut_init(void) const char *nano_browser_lefthand_msg = N_("Go to lefthand column"); const char *nano_browser_righthand_msg = N_("Go to righthand column"); #endif + const char *nano_auto_complete_msg = ("Look up for the current word in the file"); const char *nano_prevpage_msg = N_("Go one screenful up"); const char *nano_nextpage_msg = N_("Go one screenful down"); const char *nano_cut_msg = @@ -721,7 +724,8 @@ void shortcut_init(void) add_to_funcs(goto_dir_void, MBROWSER, N_("Go To Dir"), IFSCHELP(nano_gotodir_msg), BLANKAFTER, VIEW); #endif - + add_to_funcs(auto_complete_void, MMAIN, auto_complete_tag, + IFSCHELP(nano_auto_complete_msg), TOGETHER, VIEW); #ifndef DISABLE_HELP /* The description ("x") and blank_after (0) are irrelevant, * because the help viewer does not have a help text. */ @@ -1064,6 +1068,7 @@ void shortcut_init(void) add_to_sclist(MMAIN, "^\\", do_replace, 0); add_to_sclist(MMAIN, "M-R", do_replace, 0); add_to_sclist(MMAIN, "F14", do_replace, 0); + add_to_sclist(MMAIN, "^]", auto_complete_void, 0); add_to_sclist(MMOST, "^K", do_cut_text_void, 0); add_to_sclist(MMOST, "F9", do_cut_text_void, 0); add_to_sclist(MMAIN, "^U", do_uncut_text, 0); diff --git a/src/text.c b/src/text.c index d0d1955..082ff5b 100644 --- a/src/text.c +++ b/src/text.c @@ -46,6 +46,142 @@ static filestruct *jusbottom = NULL; /* Pointer to the end of the justify buffer. */ #endif +#define WORD_MAX 30 + +/* Complete the common parts found in the results */ +void complete_max(char **words, int start, int no_of_words) +{ + int i = start, j; + + while (1) { + for (j = 0; j < no_of_words - 1; j++) { + if (words[j][i] != words[j + 1][i]) + return; + } + do_output(&words[j][i], 1, FALSE); + i++; + } +} + +/* Copy the word from the line which contains the pattern + * Removes duplicates from the words + * returns -1 for error + * else returns string length of the word + */ +int copy_arrays(char **words, char *check_line, int start, int *len_match) +{ + int i = start; + int len_of_word = 0; + + while (is_word_mbchar(&check_line[i], FALSE)) { + i++; + len_of_word++; + } + words[*len_match - 1] = (char *)malloc((len_of_word + 1) * sizeof(char)); + if (words[*len_match - 1] == NULL) + return 1; + i = start; + int j = 0; + + while (is_word_mbchar(&check_line[i], FALSE)) { + words[*len_match - 1][j++] = check_line[i]; + i++; + } + words[*len_match - 1][j] = '\0'; + if (*len_match == 1) + return len_of_word; + for (i = *len_match - 2; i >= 0; i--) + if (strcmp(words[i], words[*len_match - 1]) == 0) + break; + if (i != -1) { + (*len_match)--; + return 0; + } + return len_of_word; +} + +/* This function finds out the current word which the user is typing + * searches for the word in the entire file + * replaces it, if only 1 match is found, else it suggests the possible completions + */ +void auto_complete_void(void) +{ + filestruct *check_line = openfile->current; + char *to_find; + int curpos = openfile->current_x, len_to_find = 0; + int to_find_start_pos = curpos, len_of_words = 0; + int to_find_end_pos = curpos, i = 0, j = 0, match = 0, curr_line_no = check_line->lineno; + char *words[WORD_MAX]; + + while (to_find_start_pos-- != 0) + if (!is_word_mbchar(&check_line->data[to_find_start_pos], FALSE)) + break; + to_find_start_pos++; + to_find = (char *)malloc((to_find_end_pos - to_find_start_pos + 1) * sizeof(char)); + if (to_find == NULL) { + statusline(HUSH, "Insufficient Memory"); + return; + } + /*copy what is to be searched in to find*/ + while (to_find_start_pos + i < curpos) + to_find[len_to_find++] = check_line->data[to_find_start_pos + i++]; + to_find[len_to_find] = '\0'; + if (len_to_find == 0) + return; + +/*Finding the current word in the entire file*/ + check_line = openfile->fileage; + while (check_line != NULL) { + int len_data = strlen(check_line->data); + + for (i = 0; i < len_data; i++) { + for (j = 0; (i == 0 || !is_word_mbchar(&check_line->data[i - 1], FALSE)) && j < len_to_find; j++) + if (to_find[j] != check_line->data[i + j] || + (check_line->lineno == curr_line_no && i == to_find_start_pos)) + break; + if (j == len_to_find && (i + j != len_data && is_word_mbchar(&check_line->data[i + j], FALSE))) { + match++; + if (match >= WORD_MAX) { + statusline(HUSH, "Please type more characters for suggestions"); + return; + } + int tmp = copy_arrays(words, check_line->data, i , &match); + + if (tmp == -1) { + statusline(HUSH, "Insufficient Memory"); + return; + } + /*Add the length of word to len_of_words require to make the final string */ + else + len_of_words+=tmp; + } + } + check_line = check_line->next; + } + /*No match found*/ + if (match == 0) + statusline(HUSH, "No matches found"); + /*One match found*/ + else if (match == 1) { + statusline(HUSH, "Done"); + do_output(&words[0][len_to_find], strlen(words[0]) - len_to_find, FALSE); + } + /*else find out the common parts and complete it and display the rest part as suggestions*/ + else { + complete_max(words, len_to_find, match); + char *to_be_replaced = auto_complete_status_bar(words, match); + if (to_be_replaced != NULL) { + do_output(&to_be_replaced[len_to_find], strlen(to_be_replaced) - len_to_find, FALSE); + statusline(HUSH, "Done"); + free(to_be_replaced); + } + } + free(to_find); + /*free words*/ + for (i = 0; i < match; i++) + free(words[i]); +} + #ifndef NANO_TINY /* Toggle the mark. */ void do_mark(void) diff --git a/src/winio.c b/src/winio.c index eccf41c..9e1ed37 100644 --- a/src/winio.c +++ b/src/winio.c @@ -2038,8 +2038,145 @@ void statusbar(const char *msg) statusline(HUSH, msg); } +void auto_complete_bar(message_type importance, char **words, int match, int highlight) +{ + size_t start_x; + bool bracketed; +#ifndef NANO_TINY + bool old_whitespace = ISSET(WHITESPACE_DISPLAY); + + UNSET(WHITESPACE_DISPLAY); +#endif + + + /* Curses mode is turned off. If we use wmove() now, it will muck + * up the terminal settings. So we just use vfprintf(). */ + if (isendwin()) { + //vfprintf(stderr, msg, ap); + //va_end(ap); + return; + } + + /* If there already was an alert message, ignore lesser ones. */ + if ((lastmessage == ALERT && importance != ALERT) || + (lastmessage == MILD && importance == HUSH)) + return; + + /* Delay another alert message, to allow an earlier one to be noticed. */ + if (lastmessage == ALERT) + napms(1200); + + if (importance == ALERT) + beep(); + + lastmessage = importance; + + /* Turn the cursor off while fiddling in the statusbar. */ + curs_set(0); + + blank_statusbar(); + + /* Construct the message out of all the arguments. */ + int i = 0, max_len = 0; + + for(i = 0; i < match; i++) { + max_len += 3; + max_len += strlen(words[i]); + } + start_x = (COLS - max_len) / 2; + bracketed = (start_x > 1); + + wmove(bottomwin, 0, (bracketed ? start_x - 2 : start_x)); + wattron(bottomwin, interface_color_pair[STATUS_BAR]); + wattroff(bottomwin, A_REVERSE); + if (bracketed) + waddstr(bottomwin, "[ "); + for (i = 0;i < match; i++) { + if (i == highlight) { + wattron(bottomwin, A_REVERSE); + waddstr(bottomwin, words[i]); + wattroff(bottomwin, A_REVERSE); + } + else + waddstr(bottomwin, words[i]); + if ( i != match - 1) + waddstr(bottomwin, " "); + } + if (bracketed) + waddstr(bottomwin, " ]"); + wattroff(bottomwin, interface_color_pair[STATUS_BAR]); + + /* Push the message to the screen straightaway. */ + wnoutrefresh(bottomwin); + doupdate(); + + suppress_cursorpos = TRUE; + +#ifndef NANO_TINY + if (old_whitespace) + SET(WHITESPACE_DISPLAY); + + /* If doing quick blanking, blank the statusbar after just one keystroke. + * Otherwise, blank it after twenty-six keystrokes, as Pico does. */ + if (ISSET(QUICK_BLANK)) + statusblank = 1; + else +#endif + statusblank = 26; +} + +int kbinput(WINDOW *); +char *auto_complete_status_bar(char **words, int match) +{ + int highlight = 0, oldmenu = currmenu; + int choice = -2; + int c; + char ca; + + auto_complete_bar(HUSH, words, match, highlight); + while (1) { + c = wgetch(bottomwin); + switch (c) { + case KEY_LEFT: + if (highlight == 0) + highlight = match - 1; + else + --highlight; + break; + case KEY_RIGHT: + if (highlight == match - 1) + highlight = 0; + else + ++highlight; + break; + case 13: + choice = highlight; + break; + default: + ca = c; + choice = -1; + break; + } + auto_complete_bar(HUSH, words, match, highlight); + if (choice == -1) { + blank_statusbar(); + do_output(&ca, 1, TRUE); + edit_refresh(); + bottombars(oldmenu); + return NULL; + } + else if (choice >= 0) { + char *to_be_replaced; + to_be_replaced = (char *)malloc(sizeof(words[highlight])); + strcpy(to_be_replaced, words[highlight]); + bottombars(oldmenu); + return to_be_replaced; + } + } +} + /* Display a message on the statusbar, and set suppress_cursorpos to - * TRUE, so that the message won't be immediately overwritten if + * TRUE, so that the message won't be immediately 0overwritten if * constant cursor position display is on. */ void statusline(message_type importance, const char *msg, ...) { -- 2.7.4