diff options
Diffstat (limited to 'smenu.c')
-rw-r--r-- | smenu.c | 3761 |
1 files changed, 2523 insertions, 1238 deletions
@@ -25,6 +25,8 @@ #if defined(__sun) && defined(__SVR4) #include <stdbool.h> #endif +#include <limits.h> +#include <stdarg.h> #include <signal.h> #include <ctype.h> #include <string.h> @@ -59,174 +61,249 @@ typedef struct txt_attr_s txt_attr_t; typedef struct limits_s limits_t; typedef struct sed_s sed_t; typedef struct interval_s interval_t; +typedef struct timeout_s timeout_t; /* ********** */ /* Prototypes */ /* ********** */ -static void help(win_t * win, term_t * term, int last_line, toggle_t * toggle); -static void short_usage(void); -static void usage(void); +static void +help(win_t * win, term_t * term, int last_line, toggle_t * toggle); + +static void +short_usage(void); + +static void +usage(void); -static void * xmalloc(size_t size); -static void * xcalloc(size_t num, size_t size); -static void * xrealloc(void * ptr, size_t size); +static void * +xmalloc(size_t size); -static interval_t * interval_new(void); -static int interval_comp(void * a, void * b); -static void interval_swap(void * a, void * b); +static void * +xcalloc(size_t num, size_t size); + +static void * +xrealloc(void * ptr, size_t size); + +static interval_t * +interval_new(void); + +static int +interval_comp(void * a, void * b); + +static void +interval_swap(void * a, void * b); + +static int +ll_append(ll_t * const list, void * const data); -static int ll_append(ll_t * const list, void * const data); #if 0 /* here for coherency but not used. */ static int ll_prepend(ll_t * const list, void *const data); -static void ll_insert_before(ll_t * const list, ll_node_t * node, - void *const data); -static void ll_insert_after(ll_t * const list, ll_node_t * node, - void *const data); + +static void +ll_insert_before(ll_t * const list, ll_node_t * node, void *const data); + +static void +ll_insert_after(ll_t * const list, ll_node_t * node, void *const data); #endif -static ll_node_t * ll_partition(ll_node_t * l, ll_node_t * h, - int (*comp)(void *, void *), - void (*swap)(void *, void *)); -static void ll_quicksort(ll_node_t * l, ll_node_t * h, - int (*comp)(void *, void *), - void (*swap)(void * a, void *)); -static void ll_sort(ll_t * list, int (*comp)(void *, void *), - void (*swap)(void * a, void *)); -static int ll_delete(ll_t * const list, ll_node_t * node); -static ll_node_t * ll_find(ll_t * const, void * const, - int (*)(const void *, const void *)); -static void ll_init(ll_t * list); -static ll_node_t * ll_new_node(void); -static ll_t * ll_new(void); - -static void ltrim(char * str, const char * trim); -static void rtrim(char * str, const char * trim, size_t min_len); -static int my_stricmp(const char * str1, const char * str2); - -static int isprint7(int i); -static int isprint8(int i); - -static int count_leading_set_bits(unsigned char c); -static int get_cursor_position(int * const r, int * const c); -static void get_terminal_size(int * const r, int * const c); -static char * mb_strprefix(char * d, char * s, int n, int * pos); -static int mb_strlen(char * str); -static wchar_t * mb_strtowcs(char * s); -static int validate_mb(const char * str, int length); -static int outch(int c); -static void restore_term(int const fd); -static void setup_term(int const fd); -static void strip_ansi_color(char * s, toggle_t * toggle); -static int strprefix(char * str1, char * str2); - -static int tst_cb(void * elem); -static int tst_cb_cli(void * elem); + +static ll_node_t * +ll_partition(ll_node_t * l, ll_node_t * h, int (*comp)(void *, void *), + void (*swap)(void *, void *)); + +static void +ll_quicksort(ll_node_t * l, ll_node_t * h, int (*comp)(void *, void *), + void (*swap)(void * a, void *)); + +static void +ll_sort(ll_t * list, int (*comp)(void *, void *), + void (*swap)(void * a, void *)); + +static int +ll_delete(ll_t * const list, ll_node_t * node); + +static ll_node_t * +ll_find(ll_t * const, void * const, int (*)(const void *, const void *)); + +static void +ll_init(ll_t * list); + +static ll_node_t * +ll_new_node(void); + +static ll_t * +ll_new(void); + +static void +ltrim(char * str, const char * trim); + +static void +rtrim(char * str, const char * trim, size_t min_len); + +static int +isempty(const char * str); + +static int +my_stricmp(const char * str1, const char * str2); + +static int +isprint7(int i); + +static int +isprint8(int i); + +static int +count_leading_set_bits(unsigned char c); + +static int +get_cursor_position(int * const r, int * const c); + +static void +get_terminal_size(int * const r, int * const c); + +static char * +mb_strprefix(char * d, char * s, int n, int * pos); + +static int +mb_strlen(char * str); + +static wchar_t * +mb_strtowcs(char * s); + +static int +validate_mb(const char * str, int length); + +static int +outch(int c); + +static void +restore_term(int const fd); + +static void +setup_term(int const fd); + +static void +strip_ansi_color(char * s, toggle_t * toggle); + +static int +strprefix(char * str1, char * str2); + +static int +tst_cb(void * elem); + +static int +tst_cb_cli(void * elem); + #if 0 /* here for coherency but not used. */ static void tst_cleanup(tst_node_t * p); #endif -static tst_node_t * tst_insert(tst_node_t * p, wchar_t * w, void * data); -static void * tst_prefix_search(tst_node_t * root, wchar_t * w, - int (*callback)(void *)); -static void * tst_search(tst_node_t * root, wchar_t * w); -static int tst_traverse(tst_node_t * p, int (*callback)(void *), - int first_call); - -static int ini_load(const char * filename, win_t * win, term_t * term, - limits_t * limits, - int (*report)(win_t * win, term_t * term, limits_t * limits, - const char * section, const char * name, - char * value)); -static int ini_cb(win_t * win, term_t * term, limits_t * limits, - const char * section, const char * name, char * value); -static char * make_ini_path(char * name, char * base); - -static void set_foreground_color(term_t * term, int color); -static void set_background_color(term_t * term, int color); - -static void set_win_start_end(win_t * win, int current, int last); -static int build_metadata(word_t * word_a, term_t * term, int count, - win_t * win); -static int disp_lines(word_t * word_a, win_t * win, toggle_t * toggle, - int current, int count, int search_mode, - char * search_buf, term_t * term, int last_line, - char * tmp_max_word, langinfo_t * langinfo); -static void get_message_lines(char * message, ll_t * message_lines_list, - int * message_max_width, int * message_max_len); -static int disp_message(ll_t * message_lines_list, int width, int max_len, - term_t * term, win_t * win); -static void disp_word(word_t * word_a, int pos, int search_mode, char * buffer, - term_t * term, win_t * win, char * tmp_max_word); -static int egetopt(int nargc, char ** nargv, char * ostr); -static int expand(char * src, char * dest, langinfo_t * langinfo); -static int get_bytes(FILE * input, char * mb_buffer, ll_t * word_delims_list, - toggle_t * toggle, langinfo_t * langinfo); -static int get_scancode(unsigned char * s, int max); -static char * get_word(FILE * input, ll_t * word_delims_list, - ll_t * record_delims_list, char * mb_buffer, - unsigned char * is_last, toggle_t * toggle, - langinfo_t * langinfo, win_t * win, limits_t * limits); - -static void left_margin_putp(char * s, term_t * term, win_t * win); -static void right_margin_putp(char * s1, char * s2, langinfo_t * langinfo, - term_t * term, win_t * win, int line, int offset); - -static int search_next(tst_node_t * tst, word_t * word_a, char * search_buf, - int after_only); -static void sig_handler(int s); - -static void set_new_first_column(win_t * win, term_t * term, word_t * word_a); - -static int parse_sed_like_string(sed_t * sed); -static int replace(char * orig, sed_t * sed, char * buf, size_t bufsiz); - -static int decode_txt_attr_toggles(char * s, txt_attr_t * attr); -static int parse_txt_attr(char * str, txt_attr_t * attr, short max_color); -static void apply_txt_attr(term_t * term, txt_attr_t attr); -static int (*my_isprint)(int); +static tst_node_t * +tst_insert(tst_node_t * p, wchar_t * w, void * data); -static int delims_cmp(const void * a, const void * b); +static void * +tst_prefix_search(tst_node_t * root, wchar_t * w, int (*callback)(void *)); -/* **************** */ -/* Global variables */ -/* **************** */ +static void * +tst_search(tst_node_t * root, wchar_t * w); -int dummy_rc; /* temporary variable to silence * - * the compiler */ +static int +tst_traverse(tst_node_t * p, int (*callback)(void *), int first_call); -int count = 0; /* number of words read from stdin */ -int current; /* index the current selection * - * (under the cursor) */ -int new_current; /* final current position, (used in * - * search function) */ -int * line_nb_of_word_a; /* array containing the line number * - * (from 0) of each word read */ -int * first_word_in_line_a; /* array containing the index of * - * the first word of each lines */ -int search_mode = 0; /* 1 if in search mode else 0 */ -int help_mode = 0; /* 1 if help is display else 0 */ +static int +ini_load(const char * filename, win_t * win, term_t * term, limits_t * limits, + int (*report)(win_t * win, term_t * term, limits_t * limits, + const char * section, const char * name, char * value)); -/* UTF-8 useful symbols */ -/* """"""""""""""""""""" */ -char * broken_line_sym = "\xc2\xa6"; /* broken_bar */ -char * shift_left_sym = "\xe2\x86\x90"; /* leftwards_arrow */ -char * shift_right_sym = "\xe2\x86\x92"; /* rightwards_arrow */ +static int +ini_cb(win_t * win, term_t * term, limits_t * limits, const char * section, + const char * name, char * value); -char * sbar_line = "\xe2\x94\x82"; /* box_drawings_light_vertical */ -char * sbar_top = "\xe2\x94\x90"; /* box_drawings_light_down_and_left */ -char * sbar_down = "\xe2\x94\x98"; /* box_drawings_light_up_and_left */ -char * sbar_curs = "\xe2\x95\x91"; /* box_drawings_double_vertical */ -char * sbar_arr_up = "\xe2\x96\xb2"; /* black_up_pointing_triangle */ -char * sbar_arr_down = "\xe2\x96\xbc"; /* black_down_pointing_triangle */ +static char * +make_ini_path(char * name, char * base); -tst_node_t * root; +static void +set_foreground_color(term_t * term, int color); -/* Variables used in signal handlers */ -/* """"""""""""""""""""""""""""""""" */ -volatile sig_atomic_t got_winch = 0; -volatile sig_atomic_t got_winch_alrm = 0; -volatile sig_atomic_t got_search_alrm = 0; -volatile sig_atomic_t got_help_alrm = 0; +static void +set_background_color(term_t * term, int color); + +static void +set_win_start_end(win_t * win, int current, int last); + +static int +build_metadata(word_t * word_a, term_t * term, int count, win_t * win); + +static int +disp_lines(word_t * word_a, win_t * win, toggle_t * toggle, int current, + int count, int search_mode, char * search_buf, term_t * term, + int last_line, char * tmp_word, langinfo_t * langinfo); + +static void +get_message_lines(char * message, ll_t * message_lines_list, + int * message_max_width, int * message_max_len); + +static int +disp_message(ll_t * message_lines_list, int width, int max_len, term_t * term, + win_t * win); + +static void +disp_word(word_t * word_a, int pos, int search_mode, char * buffer, + term_t * term, win_t * win, char * tmp_word); + +static int +egetopt(int nargc, char ** nargv, char * ostr); + +static int +expand(char * src, char * dest, langinfo_t * langinfo); + +static int +get_bytes(FILE * input, char * mb_buffer, ll_t * word_delims_list, + toggle_t * toggle, langinfo_t * langinfo); +static int +get_scancode(unsigned char * s, int max); + +static char * +get_word(FILE * input, ll_t * word_delims_list, ll_t * record_delims_list, + char * mb_buffer, unsigned char * is_last, toggle_t * toggle, + langinfo_t * langinfo, win_t * win, limits_t * limits); + +static void +left_margin_putp(char * s, term_t * term, win_t * win); + +static void +right_margin_putp(char * s1, char * s2, langinfo_t * langinfo, term_t * term, + win_t * win, int line, int offset); + +static int +search_nex(tst_node_t * tst, word_t * word_a, char * search_buf, + int after_only); + +static void +sig_handler(int s); + +static void +set_new_first_column(win_t * win, term_t * term, word_t * word_a); + +static int +parse_sed_like_string(sed_t * sed); + +static int +replace(char * orig, sed_t * sed); + +static int +decode_txt_attr_toggles(char * s, txt_attr_t * attr); + +static int +parse_txt_attr(char * str, txt_attr_t * attr, short max_color); + +static void +apply_txt_attr(term_t * term, txt_attr_t attr); + +static int (*my_isprint)(int); + +static int +delims_cmp(const void * a, const void * b); /* ***************** */ /* emums and structs */ @@ -241,10 +318,40 @@ enum filter_types EXCLUDE_FILTER }; +/* Used when managing the -R option */ +/* """""""""""""""""""""""""""""""" */ +enum row_regex_types +{ + ROW_REGEX_EXCLUDE = 0, + ROW_REGEX_INCLUDE = 1 +}; + +/* Used when managing the -C option */ +/* """""""""""""""""""""""""""""""" */ enum filter_infos { - INCLUDE_MARK = '1', - EXCLUDE_MARK = '0' + EXCLUDE_MARK = 0, /* must be 0 because used in various tests * + * these words cannot be re-included */ + INCLUDE_MARK = 1, /* to forcibly include a word, these words can * + * be excluded later */ + SOFT_EXCLUDE_MARK = 2, /* word with this mark are excluded by default * + * but can be included later */ + SOFT_INCLUDE_MARK = 3 /* word with this mark are included by default * + * but can be excluded later */ +}; + +enum timeout_types +{ + CURRENT, /* on timeout, outputs the selected word */ + QUIT, /* on timeout, quit without selecting anything */ + WORD /* on timeout , outputs the specified word */ +}; + +enum attribute_settings +{ + UNSET = 0, /* must be 0 for future testings */ + SET, + FORCED /* an attribute setting has been given in the command line */ }; /* Locale informations */ @@ -291,10 +398,11 @@ struct termios old_in_attrs; /* Interval timers used */ /* """""""""""""""""""" */ -struct itimerval search_itv; /* used when searching */ -struct itimerval hlp_itv; /* used to remove the help line */ -struct itimerval winch_itv; /* used to delay the redisplay when * - * the terminal is resized */ +struct itimerval periodic_itv; /* refresh rate for the timeout counter */ + +int search_timer = -1; +int help_timer = -1; +int winch_timer = -1; /* Structure containing the attributes components */ /* """""""""""""""""""""""""""""""""""""""""""""" */ @@ -322,21 +430,22 @@ struct term_s short colors; /* number of available colors */ short color_method; /* color method (0=classic (0-7), 1=ANSI) */ - char has_cursor_up; /* has cuu1 terminfo capability */ - char has_cursor_down; /* has cud1 terminfo capability */ - char has_cursor_left; /* has cub1 terminfo capability */ - char has_cursor_right; /* has cuf1 terminfo capability */ - char has_save_cursor; /* has sc terminfo capability */ - char has_restore_cursor; /* has rc terminfo capability */ - char has_setf; /* has set_foreground terminfo capability */ - char has_setb; /* has set_background terminfo capability */ - char has_setaf; /* idem for set_a_foreground (ANSI) */ - char has_setab; /* idem for set_a_background (ANSI) */ - char has_hpa; /* has column_address terminfo capability */ - char has_bold; /* has bold mode */ - char has_reverse; /* has reverse mode */ - char has_underline; /* has underline mode */ - char has_standout; /* has standout mode */ + char has_cursor_up; /* has cuu1 terminfo capability */ + char has_cursor_down; /* has cud1 terminfo capability */ + char has_cursor_left; /* has cub1 terminfo capability */ + char has_cursor_right; /* has cuf1 terminfo capability */ + char has_parm_right_cursor; /* has cuf terminfo capability */ + char has_save_cursor; /* has sc terminfo capability */ + char has_restore_cursor; /* has rc terminfo capability */ + char has_setf; /* has set_foreground terminfo capability */ + char has_setb; /* has set_background terminfo capability */ + char has_setaf; /* idem for set_a_foreground (ANSI) */ + char has_setab; /* idem for set_a_background (ANSI) */ + char has_hpa; /* has column_address terminfo capability */ + char has_bold; /* has bold mode */ + char has_reverse; /* has reverse mode */ + char has_underline; /* has underline mode */ + char has_standout; /* has standout mode */ }; /* Structure describing a word */ @@ -354,7 +463,7 @@ struct word_s * by is expansion. */ unsigned char is_tagged; /* 1 if the word is tagged, 0 if not */ unsigned char is_last; /* 1 if the word is the last of a line */ - unsigned char is_selectable; /* word is is_selectable */ + unsigned char is_selectable; /* word is selectable */ }; /* Structure describing the window in which the user */ @@ -367,7 +476,7 @@ struct win_s int cur_line; /* relative number of the cursor line (1+) */ int asked_max_lines; /* requested number of lines in the window */ int max_lines; /* effective number of lines in the window */ - int max_cols; /* max number of words in a sigle line */ + int max_cols; /* max number of words in a single line */ int max_width; /* max line length. In column, tab or line * * mode it can be greater than the * * terminal width */ @@ -387,6 +496,7 @@ struct win_s txt_attr_t shift_attr; /* shift indicator attributes */ txt_attr_t search_field_attr; /* search mode field attributes */ txt_attr_t search_text_attr; /* search mode text attributes */ + txt_attr_t include_attr; /* selectable words attributes */ txt_attr_t exclude_attr; /* non-selectable words attributes */ txt_attr_t tag_attr; /* non-selectable words attributes */ txt_attr_t special_attr[5]; /* special (-1,...) words attributes */ @@ -415,6 +525,74 @@ struct interval_s int high; }; +/* Structure used by the replace function to delimit matches */ +/* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */ +struct range_s +{ + size_t start; + size_t end; +}; + +struct timeout_s +{ + unsigned type; /* timeout type: current/quit/word */ + unsigned initial_value; /* 0: no timeout else value in sec */ + unsigned remain; /* remaining seconds */ + unsigned reached; /* 1: timeout has expired, else 0 */ +}; + +/* **************** */ +/* Global variables */ +/* **************** */ + +int dummy_rc; /* temporary variable to silence * + * the compiler */ + +int count = 0; /* number of words read from stdin */ +int current; /* index the current selection * + * (under the cursor) */ +int new_current; /* final current position, (used in * + * search function) */ +int * line_nb_of_word_a; /* array containing the line number * + * (from 0) of each word read */ +int * first_word_in_line_a; /* array containing the index of * + * the first word of each lines */ +int search_mode = 0; /* 1 if in search mode else 0 */ +int help_mode = 0; /* 1 if help is display else 0 */ + +char * word_buffer; + +/* UTF-8 useful symbols */ +/* """"""""""""""""""""" */ +char * broken_line_sym = "\xc2\xa6"; /* broken_bar */ +char * shift_left_sym = "\xe2\x86\x90"; /* leftwards_arrow */ +char * shift_right_sym = "\xe2\x86\x92"; /* rightwards_arrow */ + +char * sbar_line = "\xe2\x94\x82"; /* box_drawings_light_vertical */ +char * sbar_top = "\xe2\x94\x90"; /* box_drawings_light_down_and_left */ +char * sbar_down = "\xe2\x94\x98"; /* box_drawings_light_up_and_left */ +char * sbar_curs = "\xe2\x95\x91"; /* box_drawings_double_vertical */ +char * sbar_arr_up = "\xe2\x96\xb2"; /* black_up_pointing_triangle */ +char * sbar_arr_down = "\xe2\x96\xbc"; /* black_down_pointing_triangle */ + +tst_node_t * root; + +/* Variables used in signal handlers */ +/* """"""""""""""""""""""""""""""""" */ +volatile sig_atomic_t got_winch = 0; +volatile sig_atomic_t got_winch_alrm = 0; +volatile sig_atomic_t got_search_alrm = 0; +volatile sig_atomic_t got_help_alrm = 0; +volatile sig_atomic_t got_timeout_tick = 0; + +/* Variables used when a timeout is set (option -x) */ +/* """""""""""""""""""""""""""""""""""""""""""""""" */ +timeout_t timeout; +char * timeout_word; /* printed word when the timeout type is WORD. */ +char * timeout_seconds; /* string containing the number of remaining * + * seconds. */ +int quiet_timeout = 0; /* 1 when we want no message to be displayed. */ + /* ************************************************************************ */ /* custom fgetc/ungetc implementation able to unget more than one character */ /* ************************************************************************ */ @@ -431,7 +609,7 @@ static size_t next_buffer_pos = 0; /* next free position in the getc buffer */ /* ====================================== */ /* get a (possibly pushed-back) character */ /* ====================================== */ -int +static int my_fgetc(FILE * input) { return (next_buffer_pos > 0) ? getc_buffer[--next_buffer_pos] : fgetc(input); @@ -440,7 +618,7 @@ my_fgetc(FILE * input) /* ============================ */ /* push character back on input */ /* ============================ */ -void +static void my_ungetc(int c) { if (next_buffer_pos >= GETC_BUFF_SIZE) @@ -493,41 +671,57 @@ struct ll_s /* =================== */ /* Short usage display */ /* =================== */ -void +static void short_usage(void) { - fprintf(stderr, "Usage: smenu [-h|-?] [-n lines] [-c] [-l] [-s pattern] "); - fprintf(stderr, "[-m message] [-w] \\\n"); - fprintf(stderr, " [-d] [-M] [-t [cols]] [-k] [-r] [-b] [-i regex] "); - fprintf(stderr, "[-e regex] \\\n"); - fprintf(stderr, " [-C [a|A|s|S|r|R|d|D]col1[-col2],[col1[-col2]]...]"); - fprintf(stderr, " \\\n"); - fprintf(stderr, " [-R [a|A|s|S|r|R|d|D]row1[-row2],[row1[-row2]]...] "); - fprintf(stderr, " \\\n"); + fprintf(stderr, "Usage: smenu [-h|-?] [-f config_file] [-n lines] "); + fprintf(stderr, "[-t [cols]] [-k] \\\n"); + fprintf(stderr, " [-s pattern] [-m message] [-w] [-d] [-M] [-c] [-l] "); + fprintf(stderr, "[-r] [-b] \\\n"); + fprintf(stderr, " [-a prefix:attr [prefix:attr]...] "); + fprintf(stderr, "[-i regex] [-e regex] \\\n"); + fprintf(stderr, " [-C [a|s|i|r|d|e]<col selectors>] "); + fprintf(stderr, "[-R [a|s|i|r|d|e]<row selectors>] \\\n"); fprintf(stderr, " [-S /regex/repl/[g][v][s][i]] "); - fprintf(stderr, "[-I /regex/repl/[g][v][s][i]] \\\n"); + fprintf(stderr, "[-I /regex/repl/[g][v][s][i]] \\\n"); fprintf(stderr, " [-E /regex/repl/[g][v][s][i]] "); - fprintf(stderr, "[-A regex] [-Z regex] \\\n"); - fprintf(stderr, " [-1 regex [attr]] [-2 regex [attr]] ... "); - fprintf(stderr, "[-5 regex [attr]] [-g] \\\n"); - fprintf(stderr, " [-W bytes] [-L bytes] [-T [separator]] [-V]\n"); + fprintf(stderr, "[-A regex] [-Z regex] \\\n"); + fprintf(stderr, " [-1 regex [attr]] [-2 regex [attr]]... "); + fprintf(stderr, "[-5 regex [attr]] \\\n"); + fprintf(stderr, " [-g] [-q] [-W bytes] [-L bytes] [-T [separator]]"); + fprintf(stderr, " \\\n"); + fprintf(stderr, " [-V] [-x|-X current|quit|word [<word>] <seconds>] "); + fprintf(stderr, "[input_file]\n\n"); + fprintf(stderr, " <col selectors> ::= col1[-col2]...|<RE>...\n"); + fprintf(stderr, " <row selectors> ::= row1[-row2]...|<RE>...\n"); + fprintf(stderr, " <prefix> ::= e|i|c|b|s|t|sf|st\n"); + fprintf(stderr, " <attr> ::= [fg][/bg][,style] \n"); + fprintf(stderr, " (ex: 7/4,bu)\n"); + fprintf(stderr, " <RE> ::= <char>regex<char> \n"); + fprintf(stderr, " (ex: /regex/ or :regex:)\n\n"); + fprintf(stderr, " <col/row selectors> and <RE> can be freely mixed "); + fprintf(stderr, "when used\n"); + fprintf(stderr, " with -C and -R (ex: 2,/x/,4-5).\n"); } /* ====================== */ /* Usage display and exit */ /* ====================== */ -void +static void usage(void) { short_usage(); fprintf(stderr, "\nThis is a filter that gets words from stdin "); - fprintf(stderr, "and outputs the\n"); - fprintf(stderr, "selected word (or nothing) on stdout.\n\n"); + fprintf(stderr, "and outputs the selected\n"); + fprintf(stderr, "words (or nothing) on stdout in a nice selection "); + fprintf(stderr, "window\n\n"); fprintf(stderr, "The selection window appears on /dev/tty "); - fprintf(stderr, "immediately after the current line.\n\n"); + fprintf(stderr, "immediately after the current line\n"); + fprintf(stderr, "(no clear screen!).\n\n"); fprintf(stderr, "The following options are available:\n\n"); fprintf(stderr, "-h displays this help.\n"); + fprintf(stderr, "-f selects an alternative configuration file.\n"); fprintf(stderr, "-n sets the number of lines in the selection window.\n"); fprintf(stderr, "-t tabulates the items. The number of columns can be limited " @@ -551,12 +745,14 @@ usage(void) "-r enables ENTER to validate the selection even in " "search mode.\n"); fprintf(stderr, "-b displays the non printable characters as space.\n"); + fprintf(stderr, "-a sets the attributes for the various displayed "); + fprintf(stderr, "elements.\n"); fprintf(stderr, "-i sets the regex input filter to match the selectable words.\n"); fprintf(stderr, "-e sets the regex input filter to match the non-selectable " "words.\n"); - fprintf(stderr, "-C sets column restrictions for selections.\n"); + fprintf(stderr, "-C sets columns restrictions for selections.\n"); fprintf(stderr, "-R sets rows restrictions for selections.\n"); fprintf(stderr, "-S sets the post-processing action to apply to all words.\n"); @@ -585,6 +781,8 @@ usage(void) fprintf(stderr, "on the output.\n"); fprintf(stderr, " A single space is the default separator.\n"); fprintf(stderr, "-V displays the current version and quits.\n"); + fprintf(stderr, + "-x|-X sets a timeout and specifies what to do when it expires.\n"); fprintf(stderr, "\nNavigation keys are:\n"); fprintf(stderr, " - Left/Down/Up/Right arrows or h/j/k/l.\n"); fprintf(stderr, " - Home/End.\n"); @@ -626,7 +824,7 @@ usage(void) /* ==================== */ /* Help message display */ /* ==================== */ -void +static void help(win_t * win, term_t * term, int last_line, toggle_t * toggle) { int index; /* used to identify the objects int the help line */ @@ -640,24 +838,23 @@ help(win_t * win, term_t * term, int last_line, toggle_t * toggle) struct entry_s { char attr; /* r=reverse, n=normal, b=bold */ - char * str; /* string to be displayed for un object in the help line */ + char * str; /* string to be displayed for an object in the help line */ int len; /* length of one of these objects */ }; - struct entry_s entries[] = { - { 'r', "HLP", 3 }, { 'n', " ", 1 }, { 'n', "Move:", 5 }, - { 'b', "Arrows", 6 }, { 'n', "|", 1 }, { 'b', "h", 1 }, - { 'b', "j", 1 }, { 'b', "k", 1 }, { 'b', "l", 1 }, - { 'n', ",", 1 }, { 'b', "PgUp", 4 }, { 'n', "/", 1 }, - { 'b', "PgDn", 4 }, { 'n', "/", 1 }, { 'b', "Home", 4 }, - { 'n', "/", 1 }, { 'b', "End", 3 }, { 'n', " ", 1 }, - { 'n', "Abort:", 6 }, { 'b', "q", 1 }, { 'n', " ", 1 }, - { 'n', "Select:", 7 }, { 'b', "CR", 2 }, { 'n', " ", 1 }, - { 'n', "Find:", 5 }, { 'b', "/", 1 }, { 'n', "|", 1 }, - { 'b', "^F", 2 }, { 'n', "|", 1 }, { 'b', "SP", 2 }, - { 'n', "|", 1 }, { 'b', "n", 1 }, { 'n', " ", 1 }, - { 'n', "Tag:", 4 }, { 'b', "t", 1 } - }; + struct entry_s entries[] = + { { 'r', "HLP", 3 }, { 'n', " ", 1 }, { 'n', "Move:", 5 }, + { 'b', "Arrows", 6 }, { 'n', "|", 1 }, { 'b', "h", 1 }, + { 'b', "j", 1 }, { 'b', "k", 1 }, { 'b', "l", 1 }, + { 'n', ",", 1 }, { 'b', "PgUp", 4 }, { 'n', "/", 1 }, + { 'b', "PgDn", 4 }, { 'n', "/", 1 }, { 'b', "Home", 4 }, + { 'n', "/", 1 }, { 'b', "End", 3 }, { 'n', " ", 1 }, + { 'n', "Abort:", 6 }, { 'b', "q", 1 }, { 'n', " ", 1 }, + { 'n', "Select:", 7 }, { 'b', "CR", 2 }, { 'n', " ", 1 }, + { 'n', "Find:", 5 }, { 'b', "/", 1 }, { 'n', "|", 1 }, + { 'b', "^F", 2 }, { 'n', "|", 1 }, { 'b', "SP", 2 }, + { 'n', "|", 1 }, { 'b', "n", 1 }, { 'n', " ", 1 }, + { 'n', "Tag:", 4 }, { 'b', "t", 1 } }; entries_nb = sizeof(entries) / sizeof(struct entry_s); @@ -739,7 +936,7 @@ help(win_t * win, term_t * term, int last_line, toggle_t * toggle) /* ================= */ /* Customized malloc */ /* ================= */ -void * +static void * xmalloc(size_t size) { void * allocated; @@ -762,7 +959,7 @@ xmalloc(size_t size) /* ================= */ /* Customized calloc */ /* ================= */ -void * +static void * xcalloc(size_t n, size_t size) { void * allocated; @@ -785,7 +982,7 @@ xcalloc(size_t n, size_t size) /* ================== */ /* Customized realloc */ /* ================== */ -void * +static void * xrealloc(void * p, size_t size) { void * allocated; @@ -806,7 +1003,7 @@ xrealloc(void * p, size_t size) /* =================================== */ /* strdup implementation using xmalloc */ /* =================================== */ -char * +static char * xstrdup(const char * p) { char * allocated; @@ -833,7 +1030,7 @@ xstrdup(const char * p) /* Returns 0 if some unexpected */ /* toggle is found else 0 */ /* ================================ */ -int +static int decode_txt_attr_toggles(char * s, txt_attr_t * attr) { int rc = 1; @@ -847,27 +1044,27 @@ decode_txt_attr_toggles(char * s, txt_attr_t * attr) { case 'b': attr->bold = 1; - attr->is_set = 1; + attr->is_set = SET; break; case 'd': attr->dim = 1; - attr->is_set = 1; + attr->is_set = SET; break; case 'r': attr->reverse = 1; - attr->is_set = 1; + attr->is_set = SET; break; case 's': attr->standout = 1; - attr->is_set = 1; + attr->is_set = SET; break; case 'u': attr->underline = 1; - attr->is_set = 1; + attr->is_set = SET; break; case 'i': attr->italic = 1; - attr->is_set = 1; + attr->is_set = SET; break; default: rc = 0; @@ -886,7 +1083,7 @@ decode_txt_attr_toggles(char * s, txt_attr_t * attr) /* Returns 1 on success else 0 */ /* attr will be filled by the function */ /* ============================================================ */ -int +static int parse_txt_attr(char * str, txt_attr_t * attr, short max_color) { int n; @@ -940,16 +1137,13 @@ parse_txt_attr(char * str, txt_attr_t * attr, short max_color) if (n == 2) rc = decode_txt_attr_toggles(s2, attr); - if (!attr->is_set) - attr->is_set = (d1 >= 0 || d2 >= 0); - return rc; } /* ============================================= */ /* Set the terminal attributes according to attr */ /* ============================================= */ -void +static void apply_txt_attr(term_t * term, txt_attr_t attr) { if (attr.fg >= 0) @@ -986,7 +1180,7 @@ apply_txt_attr(term_t * term, txt_attr_t attr) /* line of the ini file. */ /* Returns 0 if OK, 1 if not. */ /* ===================================================== */ -int +static int ini_cb(win_t * win, term_t * term, limits_t * limits, const char * section, const char * name, char * value) { @@ -995,7 +1189,7 @@ ini_cb(win_t * win, term_t * term, limits_t * limits, const char * section, if (strcmp(section, "colors") == 0) { - txt_attr_t v = { 0, -1, -1, -1, -1, -1, -1, -1, -1 }; + txt_attr_t v = { UNSET, -1, -1, -1, -1, -1, -1, -1, -1 }; #define CHECK_ATTR(x) \ else if (strcmp(name, #x) == 0) \ @@ -1005,51 +1199,58 @@ ini_cb(win_t * win, term_t * term, limits_t * limits, const char * section, goto out; \ else \ { \ - win->x##_attr.is_set = v.is_set; \ - if (win->x##_attr.fg < 0) \ - win->x##_attr.fg = v.fg; \ - if (win->x##_attr.bg < 0) \ - win->x##_attr.bg = v.bg; \ - if (win->x##_attr.bold < 0) \ - win->x##_attr.bold = v.bold; \ - if (win->x##_attr.dim < 0) \ - win->x##_attr.dim = v.dim; \ - if (win->x##_attr.reverse < 0) \ - win->x##_attr.reverse = v.reverse; \ - if (win->x##_attr.standout < 0) \ - win->x##_attr.standout = v.standout; \ - if (win->x##_attr.underline < 0) \ - win->x##_attr.underline = v.underline; \ - if (win->x##_attr.italic < 0) \ - win->x##_attr.italic = v.italic; \ + if (win->x##_attr.is_set != FORCED) \ + { \ + win->x##_attr.is_set = SET; \ + if (v.fg >= 0) \ + win->x##_attr.fg = v.fg; \ + if (v.bg >= 0) \ + win->x##_attr.bg = v.bg; \ + if (v.bold >= 0) \ + win->x##_attr.bold = v.bold; \ + if (v.dim >= 0) \ + win->x##_attr.dim = v.dim; \ + if (v.reverse >= 0) \ + win->x##_attr.reverse = v.reverse; \ + if (v.standout >= 0) \ + win->x##_attr.standout = v.standout; \ + if (v.underline >= 0) \ + win->x##_attr.underline = v.underline; \ + if (v.italic >= 0) \ + win->x##_attr.italic = v.italic; \ + } \ } \ } -#define CHECK_ATT_ATTR(x, y) \ - else if (strcmp(name, #x #y) == 0) \ - { \ - if ((error = !parse_txt_attr(value, &v, term->colors))) \ - goto out; \ - else \ - { \ - win->x##_attr[y - 1].is_set = v.is_set; \ - if (win->x##_attr[y - 1].fg < 0) \ - win->x##_attr[y - 1].fg = v.fg; \ - if (win->x##_attr[y - 1].bg < 0) \ - win->x##_attr[y - 1].bg = v.bg; \ - if (win->x##_attr[y - 1].bold < 0) \ - win->x##_attr[y - 1].bold = v.bold; \ - if (win->x##_attr[y - 1].dim < 0) \ - win->x##_attr[y - 1].dim = v.dim; \ - if (win->x##_attr[y - 1].reverse < 0) \ - win->x##_attr[y - 1].reverse = v.reverse; \ - if (win->x##_attr[y - 1].standout < 0) \ - win->x##_attr[y - 1].standout = v.standout; \ - if (win->x##_attr[y - 1].underline < 0) \ - win->x##_attr[y - 1].underline = v.underline; \ - if (win->x##_attr[y - 1].ital |