diff options
Diffstat (limited to 'smenu.c')
-rwxr-xr-x | smenu.c | 2667 |
1 files changed, 1626 insertions, 1041 deletions
@@ -41,6 +41,9 @@ #include "ctxopt.h" #include "usage.h" #include "safe.h" +#define BUF_MALLOC xmalloc +#define BUF_REALLOC xrealloc +#include "tinybuf.h" #include "smenu.h" /* ***************** */ @@ -64,8 +67,8 @@ long *line_nb_of_word_a; /* array containing the line number (from 0) * long *first_word_in_line_a; /* array containing the index of the first * | word of each lines. */ long *shift_right_sym_pos_a; /* screen column number of the right * - scrolling symbol if any when in line or * - column mode. */ + | scrolling symbol if any when in line or * + | column mode. */ int forgotten_timer = -1; int help_timer = -1; @@ -123,26 +126,18 @@ int daccess_stack_head; /* Variables used for fuzzy and substring searching. */ /* """"""""""""""""""""""""""""""""""""""""""""""""" */ -long matches_count; /* Number of all matching words. */ +long *matching_words_da = NULL; /* Array containing the index of all * + | matching words. */ -long *matching_words_a; /* Array containing the index of all matching * - | words. */ +long *best_matching_words_da = NULL; /* Array containing the index of * + | matching words containing a * + | consecutive suite of matching * + | glyphs. */ -long matching_words_a_size; /* Allocated size for the previous array. */ - -long best_matches_count; /* Number of matching words whose matching * - | part form a consecutive suite of matching * - | glyphs. */ - -long *best_matching_words_a; /* Array containing the index of matching * - | words containing a consecutive suite of * - | matching glyphs. */ - -long best_matching_words_a_size; /* Allocated size for the previous array. */ - -long *alt_matching_words_a = NULL; /* Alternate array to contain only the * - | matching candidates having potentially * - | a starting/ending pattern. */ +long *alt_matching_words_da = NULL; /* Alternate array to contain only * + | the matching candidates having * + | potentially a starting/ending * + | pattern. */ /* Variables used in signal handlers. */ /* """""""""""""""""""""""""""""""""" */ @@ -170,142 +165,474 @@ int quiet_timeout = 0; /* 1 when we want no message to be displayed. */ /* Help functions. */ /* *************** */ -/* ===================== */ -/* Help message display. */ -/* ===================== */ -void -help(win_t *win, term_t *term, long last_line) +/* ============================================================ */ +/* Parse, create and add an help entry. */ +/* - attributes are preprocessed for a future quicker display. */ +/* - special entries t,m and c allow to ignore entries when not */ +/* in tag mode, when the mouse is not usable or when not in */ +/* column mode. */ +/* */ +/* entries IN array of help data. */ +/* help_items_da OUT dynamic array to be updated. */ +/* */ +/* Return the number of help entries added in help_items_da. */ +/* ============================================================ */ +int +help_add_entries(win_t *win, + term_t *term, + toggle_t *toggles, + help_attr_entry_t ***help_items_da, + help_entry_t *entries, + int entries_nb) { - int index; /* used to identify the objects long the help line. */ - int line = 0; /* number of windows lines used by the help line. */ - int len = 0; /* length of the help line. */ - int max_col; /* when to split the help line. */ - int entries_nb; /* number of help entries to display. */ - int i; + int index; + int nb = 0; + + help_attr_entry_t *attr_entry; - struct entry_s + for (index = 0; index < entries_nb; index++) { - char *str; /* string to be displayed for an object in the help line. */ - int len; /* screen space taken by of one of these objects. */ - char attr; /* r=reverse, n=normal, b=bold, uu=underlined. */ - }; + /* Do not create a tag/pin related entry if tagging/pinning is not */ + /* enabled. */ + /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ + if (strchr(entries[index].flags, 't') && !toggles->taggable + && !toggles->pinable) + continue; - char *arrows = concat(left_arrow, - up_arrow, - right_arrow, - down_arrow, - (char *)0); - - struct entry_s entries[] = { - { "Move:", 5, 'r' }, { "Mouse:", 6, 'u' }, { "B1", 2, 'b' }, - { ",", 1, 'n' }, { "B3", 2, 'b' }, { ",", 1, 'n' }, - { "Wheel", 5, 'b' }, { " ", 1, 'n' }, { "Keyb:", 5, 'u' }, - { "hjkl", 4, 'b' }, { ",", 1, 'n' }, { arrows, 4, 'b' }, - { ",", 1, 'n' }, { "PgUp", 4, 'b' }, { "/", 1, 'n' }, - { "Dn", 2, 'b' }, { "... ", 4, 'n' }, { "Abort:", 6, 'r' }, - { "q", 1, 'b' }, { ",", 1, 'n' }, { "^C", 2, 'b' }, - { " ", 1, 'n' }, { "Find:", 5, 'r' }, { "/", 1, 'b' }, - { "\"\'", 2, 'b' }, { "~*", 2, 'b' }, { "=^", 2, 'b' }, - { ",", 1, 'n' }, { "SP", 2, 'b' }, { ",", 1, 'n' }, - { "nN", 2, 'b' }, { " ", 1, 'n' }, { "Select:", 7, 'r' }, - { "CR", 2, 'b' }, { ",", 1, 'n' }, { "D-click", 7, 'b' }, - { " ", 1, 'n' }, { " ", 1, 'n' }, { "Mark:", 5, 'r' }, - { "mM", 2, 'b' }, { " ", 1, 'n' }, { "Tag:", 4, 'r' }, - { "t", 1, 'b' }, { ",", 1, 'n' }, { "r", 1, 'b' }, - { ",", 1, 'n' }, { "c", 1, 'b' }, { " ", 1, 'n' }, - { "T", 1, 'b' }, { "...", 3, 'n' }, { "T", 1, 'b' }, - { ",", 1, 'n' }, { "Z", 1, 'b' }, { "...", 3, 'n' }, - { "Z", 1, 'b' }, { ",", 1, 'n' }, { "R", 1, 'b' }, - { "...", 3, 'n' }, { "R", 1, 'b' }, { ",", 1, 'n' }, - { "C", 1, 'b' }, { "...", 3, 'n' }, { "C", 1, 'b' }, - { " ", 1, 'n' }, { "U", 1, 'b' }, { ",", 1, 'n' }, - { "^T", 2, 'b' }, { " ", 1, 'n' }, { "Cancel:", 7, 'r' }, - { "ESC", 3, 'b' }, - }; + /* Do not create a mouse related entry if -no_mouse is activated. */ + /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ + if (strchr(entries[index].flags, 'm') && toggles->no_mouse) + continue; - entries_nb = sizeof(entries) / sizeof(struct entry_s); + /* Do not create a column/row related entry if the column or line_mode */ + /* is not activated. */ + /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ + if (strchr(entries[index].flags, 'c') && !win->line_mode && !win->col_mode) + continue; - /* Save the position of the terminal cursor so that it can be */ - /* put back there after printing of the help line. */ - /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ - (void)tputs(TPARM1(save_cursor), 1, outch); + /* Allocate and initialize a new attribute. */ + /* """""""""""""""""""""""""""""""""""""""" */ + attr_entry = xmalloc(sizeof(help_attr_entry_t)); - /* Determine when to split the help line if necessary. */ + attr_entry->str = xstrdup(entries[index].str); + attr_entry->len = entries[index].len; + attr_entry->attr = attr_new(); + + if (term->colors > 0) + parse_attr(entries[index].main_attr_str, attr_entry->attr, term->colors); + else + parse_attr(entries[index].alt_attr_str, attr_entry->attr, term->colors); + + /* Add it into a dynamic array. */ + /* """""""""""""""""""""""""""" */ + BUF_PUSH(*help_items_da, attr_entry); + + nb++; + } + + return nb; +} + +/* ======================================================== */ +/* Create an array of lines to be displayed by disp_help. */ +/* Created lines will have a dynamic length with leading */ +/* spaces removed. */ +/* */ +/* last_line IN last logical line number (from 0). */ +/* help_items_da OUT dynamic array to be updated. */ +/* */ +/* Return the dynamic array containing help data with */ +/* attributes processed. */ +/* ======================================================== */ +help_attr_entry_t *** +init_help(win_t *win, + term_t *term, + toggle_t *toggles, + long last_line, + help_attr_entry_t ***help_items_da) +{ + int index; /* used to identify the objects long the help line. */ + int entries_nb; /* number of all potentially displayable help * + | entries. */ + int entries_total_nb; /* number of help entries to display. */ + int line = 0; /* number of windows lines used by the help line. */ + int len = 0; /* length of the help line. */ + int max_col; /* when to split the help line. */ + int forced_nl; + int first_in_line; + + /* array of arrays containing help items. */ + /* the content of this darray will be returned by this function. */ + /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ + help_attr_entry_t ***help_lines_da = NULL; + + /* array of help items, element of help_lines_da. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ - if (win->sb_column > 0) - max_col = term->ncolumns > win->sb_column ? win->sb_column - 1 - : term->ncolumns - 1; + help_attr_entry_t **items_da = NULL; + + entries_nb = BUF_LEN(*help_items_da); + + if (entries_nb == 0) + { + char *Cleft_arrow = concat("^", left_arrow, (char *)0); + char *Cright_arrow = concat("^", right_arrow, (char *)0); + char *du_arrows = concat(down_arrow, up_arrow, (char *)0); + char *arrows = concat(left_arrow, + down_arrow, + up_arrow, + right_arrow, + (char *)0); + + help_entry_t header_entries[] = { + { "Start", 5, "u", "u", "" }, { " ", 1, "u", "u", "" }, + { "of", 2, "u", "u", "" }, { " ", 1, "u", "u", "" }, + { "quick", 5, "u", "u", "" }, { " ", 1, "u", "u", "" }, + { "help.", 5, "u", "u", "" }, { " ", 1, "u", "u", "" }, + { "jk", 2, "bu", "bu", "" }, { "/", 1, "u", "u", "" }, + { du_arrows, 2, "bu", "bu", "" }, { " ", 1, "u", "u", "" }, + { "to", 2, "u", "u", "" }, { " ", 1, "u", "u", "" }, + { "scroll.", 7, "u", "u", "" }, { " ", 1, "u", "u", "" }, + { "\"", 1, "u", "u", "" }, { "man", 3, "bu", "bu", "" }, + { " ", 1, "u", "u", "" }, { "smenu", 5, "bu", "bu", "" }, + { "\"", 1, "u", "u", "" }, { " ", 1, "u", "u", "" }, + { "for", 3, "u", "u", "" }, { " ", 1, "u", "u", "" }, + { "more", 4, "u", "u", "" }, { " ", 1, "u", "u", "" }, + { "help.", 5, "u", "u", "" }, + }; + help_entry_t generic_entries[] = { + { "\n", 0, "", "", "" }, + { "Move:", 5, "5+b", "r", "" }, + { "Mouse:", 6, "2", "u", "m" }, + { "B1", 2, "b", "b", "m" }, + { ",", 1, "", "", "m" }, + { "B3", 2, "b", "b", "m" }, + { ",", 1, "", "", "m" }, + { "Wheel", 5, "b", "b", "m" }, + { " ", 1, "", "", "m" }, + { "Keyb:", 5, "2", "u", "m" }, + { "hjkl", 4, "b", "b", "" }, + { ",", 1, "", "", "" }, + { arrows, 4, "b", "b", "" }, + { ",", 1, "", "", "" }, + { "PgUp", 4, "b", "b", "" }, + { "/", 1, "", "", "" }, + { "Dn", 2, "b", "b", "" }, + { ",", 1, "", "", "c" }, + { "S-HOME", 6, "b", "b", "c" }, + { "/", 1, "", "", "c" }, + { Cleft_arrow, 2, "b", "b", "c" }, + { "/", 1, "", "", "c" }, + { "H", 1, "b", "b", "c" }, + { ",", 1, "", "", "c" }, + { "S-END", 5, "b", "b", "c" }, + { "/", 1, "", "", "c" }, + { Cright_arrow, 2, "b", "b", "c" }, + { "/", 1, "", "", "c" }, + { "L", 1, "b", "b", "c" }, + { "\n", 0, "", "", "c" }, + { "Shift:", 6, "5+b", "r", "c" }, + { "<", 1, "b", "b", "c" }, + { ",", 1, "", "", "c" }, + { ">", 1, "b", "b", "c" }, + { "\n", 0, "", "", "" }, + { "Abort:", 6, "5+b", "r", "" }, + { "q", 1, "b", "b", "" }, + { ",", 1, "", "", "" }, + { "^C", 2, "b", "b", "" }, + { " ", 1, "", "", "" }, + { "Cancel:", 7, "5+b", "r", "" }, + { "ESC", 3, "b", "b", "" }, + { " ", 1, "", "", "" }, + { "Select:", 7, "5+b", "r", "" }, + { "Mouse:", 6, "2", "u", "m" }, + { "Double-B1", 9, "b", "b", "m" }, + { " ", 1, "", "", "m" }, + { "Keyb:", 5, "2", "u", "m" }, + { "CR", 2, "b", "b", "" }, + { "\n", 0, "", "", "" }, + { "Search:", 7, "5+b", "r", "" }, + { "Def.", 4, "3", "i", "" }, + { " ", 1, "", "", "" }, + { "(fuzzy):", 8, "3", "i", "" }, + { "/", 1, "b", "b", "" }, + { " ", 1, "", "", "" }, + { "Substr:", 7, "3", "i", "" }, + { "\"", 2, "b", "b", "" }, + { ",", 1, "", "", "" }, + { "\'", 1, "b", "b", "" }, + { " ", 1, "", "", "" }, + { "Fuzzy:", 6, "3", "i", "" }, + { "~", 1, "b", "b", "" }, + { ",", 1, "", "", "" }, + { "*", 1, "b", "b", "" }, + { " ", 1, "", "", "" }, + { "HOME", 4, "b", "b", "" }, + { ",", 1, "", "", "" }, + { "^A", 2, "b", "b", "" }, + { ",", 1, "", "", "" }, + { " ", 1, "", "", "" }, + { "END", 3, "b", "b", "" }, + { ",", 1, "", "", "" }, + { "^Z", 2, "b", "b", "" }, + { " ", 1, "", "", "" }, + { "Prefix:", 7, "3", "i", "" }, + { "=", 1, "b", "b", "" }, + { ",", 1, "", "", "" }, + { "^", 1, "b", "b", "" }, + { " ", 1, "", "", "" }, + { "Validate:", 9, "3", "i", "" }, + { "CR", 2, "b", "b", "" }, + { " ", 1, "", "", "" }, + { "Next:", 5, "3", "i", "" }, + { "SP", 2, "b", "b", "" }, + { ",", 1, "", "", "" }, + { "n", 1, "b", "b", "" }, + { " ", 1, "", "", "" }, + { "Prev:", 5, "3", "i", "" }, + { "N", 1, "b", "b", "" }, + { "\n", 0, "", "", "t" }, + { "Mark:", 5, "5+b", "r", "t" }, + { "Mouse:", 6, "2", "u", "tm" }, + { "^B1", 3, "b", "b", "tm" }, + { "/", 1, "b", "b", "tm" }, + { "B3", 2, "b", "b", "tm" }, + { " ", 1, "", "", "tm" }, + { "Keyb:", 5, "2", "u", "tm" }, + { "mM", 2, "b", "b", "t" }, + { "\n", 0, "", "", "t" }, + { "Tag:", 4, "5+b", "r", "t" }, + { "Mouse:", 6, "2", "u", "tm" }, + { "B3", 2, "B", "B", "tm" }, + { " ", 1, "", "", "tm" }, + { "Zone:", 5, "3", "i", "ctm" }, + { "/", 1, "b", "b", "ctm" }, + { "Row:", 4, "3", "i", "ctm" }, + { "/", 1, "b", "b", "ctm" }, + { "Col:", 4, "3", "i", "ctm" }, + { "^B3", 3, "B", "B", "ctm" }, + { " ", 1, "b", "b", "ct" }, + { "Keyb:", 5, "2", "u", "tm" }, + { "t", 1, "b", "b", "t" }, + { ",", 1, "", "", "t" }, + { "u", 1, "b", "b", "ct" }, + { " ", 1, "", "", "ct" }, + { "r", 1, "b", "b", "ct" }, + { ",", 1, "", "", "ct" }, + { "c", 1, "b", "b", "ct" }, + { " ", 1, "", "", "ct" }, + { "Cont:", 5, "3", "i", "t" }, + { "T", 1, "b", "b", "t" }, + { "...", 3, "", "", "t" }, + { "T", 1, "b", "b", "t" }, + { ",", 1, "", "", "t" }, + { "Zone:", 5, "3", "i", "t" }, + { "Z", 1, "b", "b", "t" }, + { "...", 3, "", "", "t" }, + { "Z", 1, "b", "b", "t" }, + { ",", 1, "", "", "ct" }, + { "Row:", 4, "3", "i", "ct" }, + { "R", 1, "b", "b", "ct" }, + { "...", 3, "", "", "ct" }, + { "R", 1, "b", "b", "ct" }, + { ",", 1, "", "", "ct" }, + { "Col:", 4, "3", "i", "ct" }, + { "C", 1, "b", "b", "ct" }, + { "...", 3, "", "", "ct" }, + { "C", 1, "b", "b", "ct" }, + { " ", 1, "", "", "t" }, + { "Undo:", 5, "3", "i", "t" }, + { "U", 1, "b", "b", "t" }, + { ",", 1, "", "", "t" }, + { "^T", 2, "b", "b", "t" }, + { " ", 1, "", "", "t" }, + }; + + help_entry_t trailer_entries[] = { + { "\n", 0, "", "", "" }, { "End", 3, "u", "u", "" }, + { " ", 1, "u", "u", "" }, { "of", 2, "u", "u", "" }, + { " ", 1, "u", "u", "" }, { "quick", 5, "u", "u", "" }, + { " ", 1, "u", "u", "" }, { "help.", 5, "u", "u", "" }, + }; + + entries_total_nb = 0; + + entries_nb = sizeof(header_entries) / sizeof(help_entry_t); + entries_total_nb += help_add_entries(win, + term, + toggles, + help_items_da, + header_entries, + entries_nb); + + entries_nb = sizeof(generic_entries) / sizeof(help_entry_t); + entries_total_nb += help_add_entries(win, + term, + toggles, + help_items_da, + generic_entries, + entries_nb); + + entries_nb = sizeof(trailer_entries) / sizeof(help_entry_t); + entries_total_nb += help_add_entries(win, + term, + toggles, + help_items_da, + trailer_entries, + entries_nb); + } else - max_col = term->ncolumns - 1; + entries_total_nb = entries_nb; - /* Print the different objects forming the help line. */ - /* A new line is added each time the next entry does not fit in the */ - /* width of the window. This is done as long as there is space left in */ - /* the window. */ - /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ - for (index = 0; index < entries_nb; index++) + /* Determine when to split the help line if necessary. */ + /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ + max_col = term->ncolumns - 1; + + help_lines_da = NULL; + items_da = NULL; + + first_in_line = 0; + + /* Fill the darray of darrays, each line is a darray of help_attr_entry_t */ + /* A new line is added each time the next entry does not fit in the */ + /* width of the window. This is done as long as there is space left in */ + /* the window. */ + /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ + for (index = 0; index < entries_total_nb; index++) { - if (entries[index].len >= max_col) + /* Ignore item if its length cannot be fully displayed. */ + /* '''''''''''''''''''''''''''''''''''''''''''''''''''' */ + if ((*help_items_da)[index]->len >= max_col) continue; - len += entries[index].len; - if (len >= max_col) + /* increase the total length of displayed items in the line. */ + /* ''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */ + len += (*help_items_da)[index]->len; + + /* Set a flag if we need to start a new line. */ + /* '''''''''''''''''''''''''''''''''''''''''' */ + if (strcmp((*help_items_da)[index]->str, "\n") == 0) + forced_nl = 1; + else + forced_nl = 0; + + if (len >= max_col || forced_nl) { line++; + first_in_line = 1; /* Exit early if we do not have enough space. */ /* '''''''''''''''''''''''''''''''''''''''''' */ - if (line > last_line || line == win->max_lines) + if (line > last_line) break; - len -= entries[index].len; + len = 0; - /* Fill the rest on the line with space, preserving the scroll bar. */ - /* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */ - for (i = len; i < max_col; i++) - fputc_safe(' ', stdout); + /* Dynamically push the current items_da in help_lines_da */ + /* And initialize a new items_da. */ + /* '''''''''''''''''''''''''''''''''''''''''''''''''''''' */ + BUF_PUSH(help_lines_da, items_da); + items_da = NULL; - len = entries[index].len; - fputc_safe('\n', stdout); + /* Do not put the '\n' in the current items_da. */ + /* '''''''''''''''''''''''''''''''''''''''''''' */ + if (forced_nl) + continue; } + /* Skip ' ' and ',' when they appear first in a line. */ + /* '''''''''''''''''''''''''''''''''''''''''''''''''' */ + if (first_in_line) + if (strcmp((*help_items_da)[index]->str, " ") == 0 + || strcmp((*help_items_da)[index]->str, ",") == 0) + continue; + + first_in_line = 0; + BUF_PUSH(items_da, (*help_items_da)[index]); + } + + if (items_da != NULL) + BUF_PUSH(help_lines_da, items_da); + + return help_lines_da; +} + +/* ================================================= */ +/* Display the quick help content. */ +/* */ +/* help_lines_da IN array of help lines. */ +/* fst_disp_help_line IN first help line to display. */ +/* ================================================= */ +void +disp_help(win_t *win, + term_t *term, + help_attr_entry_t ***help_lines_da, + int fst_disp_help_line) +{ + int index; /* used to identify the objects long the help line. */ + int max_col; /* when to split the help line. */ + int len; + int displayed_lines; + int total_lines; + + help_attr_entry_t **items_da; + + /* Determine when to split the help line if necessary. */ + /* """"""""""""""""""""""""""""""""""""""""""""""""""" */ + max_col = term->ncolumns - 1; + + /* Save the position of the terminal cursor so that it can be */ + /* put back there after printing of the help line. */ + /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ + (void)tputs(TPARM1(save_cursor), 1, outch); + + displayed_lines = 0; + total_lines = BUF_LEN(help_lines_da); + + /* Print the different objects forming the help lines. */ + /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ + for (index = fst_disp_help_line; index < total_lines; index++) + { + int i; + int item; + int nb_items; + + if (displayed_lines == win->max_lines) + break; + + displayed_lines++; + + len = 0; + + items_da = help_lines_da[index]; + nb_items = BUF_LEN(items_da); + (void)tputs(TPARM1(exit_attribute_mode), 1, outch); - switch (entries[index].attr) + for (item = 0; item < nb_items; item++) { - case 'b': /* bold. */ - if (term->has_bold) - (void)tputs(TPARM1(enter_bold_mode), 1, outch); - break; - case 'u': /* underline. */ - if (term->has_underline) - (void)tputs(TPARM1(enter_underline_mode), 1, outch); - break; - case 'r': /* reverse. */ - if (term->has_reverse) - (void)tputs(TPARM1(enter_reverse_mode), 1, outch); - else if (term->has_standout) - (void)tputs(TPARM1(enter_standout_mode), 1, outch); - break; - case 'n': /* no attributes. */ - (void)tputs(TPARM1(exit_attribute_mode), 1, outch); - break; + help_attr_entry_t *entry; + + entry = items_da[item]; + len += entry->len; + + (void)tputs(TPARM1(exit_attribute_mode), 1, outch); + apply_attr(term, *(entry->attr)); + + fputs_safe(entry->str, stdout); + (void)tputs(TPARM1(exit_attribute_mode), 1, outch); } - fputs_safe(entries[index].str, stdout); - (void)tputs(TPARM1(exit_attribute_mode), 1, outch); - } - /* Fill the remaining space with spaces. */ - /* """"""""""""""""""""""""""""""""""""" */ - (void)tputs(TPARM1(exit_attribute_mode), 1, outch); - for (i = len; i < max_col; i++) - fputc_safe(' ', stdout); + /* Fill the remaining space with spaces. */ + /* """"""""""""""""""""""""""""""""""""" */ + for (i = len; i < max_col; i++) + fputc_safe(' ', stdout); + if (displayed_lines < win->max_lines) + fputc_safe('\n', stdout); + } /* Put back the cursor to its saved position. */ /* """""""""""""""""""""""""""""""""""""""""" */ (void)tputs(TPARM1(restore_cursor), 1, outch); - - free(arrows); } /* *********************************** */ @@ -314,6 +641,8 @@ help(win_t *win, term_t *term, long last_line) /* =========================================================== */ /* Allocation and initialization of a new attribute structure. */ +/* */ +/* Return the newly created attribute. */ /* =========================================================== */ attrib_t * attr_new(void) @@ -337,20 +666,20 @@ attr_new(void) return attr; } -/* ================================= */ -/* Decode attributes toggles if any. */ -/* b -> bold */ -/* d -> dim */ -/* r -> reverse */ -/* s -> standout */ -/* u -> underline */ -/* i -> italic */ -/* x -> invis */ -/* l -> blink */ -/* */ -/* Returns 0 if some unexpected. */ -/* toggle is found else 0. */ -/* ================================= */ +/* ============================================ */ +/* Decode attributes toggles if any. */ +/* b -> bold */ +/* d -> dim */ +/* r -> reverse */ +/* s -> standout */ +/* u -> underline */ +/* i -> italic */ +/* x -> invis */ +/* l -> blink */ +/* */ +/* Return 0 if some unexpected toggle is found, */ +/* 1 otherwise. */ +/* ============================================ */ int decode_attr_toggles(char *s, attrib_t *attr) { @@ -913,11 +1242,13 @@ out: return error; } -/* ======================================================= */ -/* Return the full path on the configuration file supposed */ -/* to be in the home directory of the user. */ -/* NULL is returned if the built path is too large. */ -/* ======================================================= */ +/* ====================================================================== */ +/* Returns the full path of the configuration file supposed to be in the */ +/* user's home directory if base is NULL or in the content of the */ +/* environment variable base. */ +/* */ +/* Returns NULL if the built path is too large or if base does not exist. */ +/* ====================================================================== */ char * make_ini_path(char *name, char *base) { @@ -1108,7 +1439,7 @@ update_bitmaps(search_mode_t mode, long last = data->utf8_len - 1; /* offset of the last glyph in the * | search buffer. */ - best_matches_count = 0; + BUF_CLEAR(best_matching_words_da); if (mode == FUZZY || mode == SUBSTRING) { @@ -1126,12 +1457,12 @@ update_bitmaps(search_mode_t mode, else sb = sb_orig; - for (i = 0; i < matches_count; i++) + for (i = 0; i < BUF_LEN(matching_words_da); i++) { long lmg; /* position of the last matching glyph of the search buffer * | in a word. */ - n = matching_words_a[i]; + n = matching_words_da[i]; str_orig = xstrdup(word_a[n].str + daccess.flength); @@ -1322,19 +1653,7 @@ update_bitmaps(search_mode_t mode, /* cursor among this category of words. */ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */ if (badness == 0) - { - if (best_matches_count == best_matching_words_a_size) - { - best_matching_words_a = xrealloc(best_matching_words_a, - (best_matching_words_a_size + 16) - * sizeof(long)); - best_matching_words_a_size += 16; - } - - best_matching_words_a[best_matches_count] = n; - - best_matches_count++; - } + BUF_PUSH(best_matching_words_da, n); } } @@ -1345,9 +1664,9 @@ update_bitmaps(search_mode_t mode, } else if (mode == PREFIX) { - for (i = 0; i < matches_count; i++) + for (i = 0; i < BUF_LEN(matching_words_da); i++) { - n = matching_words_a[i]; + n = matching_words_da[i]; bm = word_a[n].bitmap; bm_len = (word_a[n].mb - daccess.flength) / CHAR_BIT + 1; @@ -1509,9 +1828,9 @@ clean_matches(search_data_t *search_data, long size) /* Clean the match flags and bitmaps. */ /* """""""""""""""""""""""""""""""""" */ - for (i = 0; i < matches_count; i++) + for (i = 0; i < BUF_LEN(matching_words_da); i++) { - long n = matching_words_a[i]; + long n = matching_words_da[i]; word_a[n].is_matching = 0; @@ -1520,7 +1839,7 @@ clean_matches(search_data_t *search_data, long size) (word_a[n].mb - daccess.flength) / CHAR_BIT + 1); } - matches_count = 0; + BUF_CLEAR(matching_words_da); } /* *************************** */ @@ -1538,7 +1857,7 @@ outch(char c) outch(int c) #endif { - putchar(c); + fputc_safe(c, stdout); return 1; } @@ -2826,17 +3145,18 @@ build_repl_string(char *orig, long match, int *error) { - size_t allocated = 16; - size_t rsize = 0; - char *str = xmalloc(allocated); - int special = 0; - long offset = match * subs_nb; /* offset of the 1st sub * - | corresponding to the match. */ + char *str; /*string to return */ + int special; /* 1 if the next character is protected. */ + long offset; /* offset of the 1st sub corresponding to the match. */ - *error = 0; + str = (char *)0; + special = 0; + *error = 0; + + offset = match * subs_nb; if (*repl == '\0') - str = xstrdup(""); + BUF_FIT(str, 1); else while (!*error && *repl) { @@ -2845,12 +3165,8 @@ build_repl_string(char *orig, case '\\': if (special) { - if (allocated == rsize) - str = xrealloc(str, allocated += 16); - str[rsize] = '\\'; - rsize++; - str[rsize] = '\0'; - special = 0; + BUF_PUSH(str, '\\'); + special = 0; } else special = 1; @@ -2872,13 +3188,11 @@ build_repl_string(char *orig, long index = (*repl) - '0' - 1 + offset; long delta = subs_a[index].end - subs_a[index].start; - if (allocated <= rsize + delta) - str = xrealloc(str, allocated += (delta + 16)); - - memcpy(str + rsize, orig + subs_a[index].start, delta); - - rsize += delta; - str[rsize] = '\0'; + if (delta > 0) + { + char *ptr = BUF_ADD(str, delta); + memcpy(ptr, orig + subs_a[index].start, delta); + } } else { @@ -2889,11 +3203,7 @@ build_repl_string(char *orig, } else { - if (allocated == rsize) - str = xrealloc(str, allocated += 16); - str[rsize] = *repl; - rsize++; - str[rsize] = '\0'; + BUF_PUSH(str, *repl); } break; @@ -2902,24 +3212,18 @@ build_repl_string(char *orig, { long delta = match_end - match_start; - if (allocated <= rsize + delta) - str = xrealloc(str, allocated += (delta + 16)); - - memcpy(str + rsize, orig + match_start, delta); - - rsize += delta; - str[rsize] = '\0'; + if (delta > 0) + { + char *ptr = BUF_ADD(str, delta); + memcpy(ptr, orig + match_start, delta); + } special = 0; } else { - if (allocated == rsize) - str = xrealloc(str, allocated += 16); - str[rsize] = *repl; - rsize++; - str[rsize] = '\0'; - special = 0; + BUF_PUSH(str, *repl); + special = 0; } break; @@ -2928,33 +3232,28 @@ build_repl_string(char *orig, { long delta = match_end - match_start; - if (allocated <= rsize + delta) - str = xrealloc(str, allocated += (delta + 16)); - - memcpy(str + rsize, orig + match_start, delta); - - rsize += delta; - str[rsize] = '\0'; - break; + if (delta > 0) + { + char *ptr = BUF_ADD(str, delta); + memcpy(ptr, orig + match_start, delta); + } } - - /* No break here, '&' must be treated as a normal */ - /* character when protected. */ - /* '''''''''''''''''''''''''''''''''''''''''''''' */ - - /* FALLTHROUGH */ + else + { + BUF_PUSH(str, '&'); + special = 0; + } + break; default: - if (allocated == rsize) - str = xrealloc(str, allocated += 16); - str[rsize] = *repl; - rsize++; - str[rsize] = '\0'; - special = 0; + BUF_PUSH(str, *repl); + special = 0; } repl++; } + BUF_PUSH(str, '\0'); + if (special > 0) *error = 1; @@ -2981,7 +3280,7 @@ replace(char *orig, sed_t *sed) { size_t match_nb = 0; /* number of matches in the original string. */ int sub_nb = 0; /* number of remembered matches in the * - | original sting. */ + | original string. */ size_t target_len = 0; /* length of the resulting string. */ size_t subs_max = 0; @@ -3043,7 +3342,8 @@ replace(char *orig, sed_t *sed) my_strcpy(word_buffer + target_len, exp_repl); target_len += len; - free(exp_repl); + + BUF_FREE(exp_repl); index += matches_a[match].end - matches_a[match].start; @@ -3164,6 +3464,7 @@ set_matching_flag(void *elem) ll_t *list = (ll_t *)elem; ll_node_t *node = list->head; + long target; while (node) { @@ -3173,10 +3474,11 @@ set_matching_flag(void *elem) if (word_a[pos].is_selectable) word_a[pos].is_matching = 1; - insert_sorted_index(&matching_words_a, - &matching_words_a_size, - &matches_count, - pos); + target = get_sorted_array_target_pos(matching_words_da, + BUF_LEN(matching_words_da), + pos); + if (target >= 0) + BUF_INSERT(matching_words_da, target, pos); node = node->next; } @@ -3191,7 +3493,7 @@ set_matching_flag(void *elem) /* the words in the input flow. */ /* Each position in this list is used to: */ /* - mark the word at that position as matching, */ -/* - add this position in the sorted array matching_words_a. */ +/* - add this position in the sorted array matching_words_da. */ /* Always succeeds and returns 1. */ /* ======================================================================= */ int @@ -3204,18 +3506,21 @@ tst_cb(void *elem) ll_t *list = (ll_t *)elem; ll_node_t *node = list->head; + long target; while (node) { - size_t pos; + |