summaryrefslogtreecommitdiffstats
path: root/smenu.c
diff options
context:
space:
mode:
Diffstat (limited to 'smenu.c')
-rwxr-xr-xsmenu.c2667
1 files changed, 1626 insertions, 1041 deletions
diff --git a/smenu.c b/smenu.c
index 9c1414a..a5651be 100755
--- a/smenu.c
+++ b/smenu.c
@@ -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;
+