summaryrefslogtreecommitdiffstats
path: root/smenu.c
diff options
context:
space:
mode:
Diffstat (limited to 'smenu.c')
-rwxr-xr-x[-rw-r--r--]smenu.c768
1 files changed, 586 insertions, 182 deletions
diff --git a/smenu.c b/smenu.c
index cc867a6..dca2803 100644..100755
--- a/smenu.c
+++ b/smenu.c
@@ -95,9 +95,15 @@ char * vertical_bar = "\xe2\x94\x82"; /* │ box drawings light vertical. *
char * shift_left_sym = "\xe2\x97\x80"; /* ◀ black left-pointing triangle. */
char * shift_right_sym = "\xe2\x96\xb6"; /* ▶ black right-pointing triangle. */
char * sbar_line = "\xe2\x94\x82"; /* │ box drawings light vertical. */
+char * hbar_line = "\xe2\x94\x80"; /* ─ box drawings light horizontal. */
+char * hbar_left = "\xe2\x97\x80"; /* ◀ black left-pointing triangle. */
+char * hbar_right = "\xe2\x96\xb6"; /* ▶ black right-pointing triangle. */
char * sbar_top = "\xe2\x94\x90"; /* ┐ box drawings light down and l. */
char * sbar_down = "\xe2\x94\x98"; /* ┘ box drawings light up and l. */
-char * sbar_curs = "\xe2\x96\x88"; /* █ full Block. */
+char * hbar_begin = "\xe2\x94\x94"; /* └ box drawings light up and r. */
+char * hbar_end = "\xe2\x94\x98"; /* ┘ box drawings light up and l. */
+char * sbar_curs = "\xe2\x94\x83"; /* ┃ box drawings heavy vertical. */
+char * hbar_curs = "\xe2\x94\x81"; /* ━ box drawings heavy horizontal. */
char * sbar_arr_up = "\xe2\x96\xb2"; /* ▲ black up pointing triangle. */
char * sbar_arr_down = "\xe2\x96\xbc"; /* ▼ black down pointing triangle. */
char * msg_arr_down = "\xe2\x96\xbc"; /* ▼ black down pointing triangle. */
@@ -169,12 +175,12 @@ int quiet_timeout = 0; /* 1 when we want no message to be displayed. */
void
help(win_t *win, term_t *term, long last_line)
{
- 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. */
- long i;
+ 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;
struct entry_s
{
@@ -2791,6 +2797,8 @@ build_repl_string(char *orig,
/* character when protected. */
/* '''''''''''''''''''''''''''''''''''''''''''''' */
+ /* FALLTHROUGH */
+
default:
if (allocated == rsize)
str = xrealloc(str, allocated += 16);
@@ -3700,6 +3708,133 @@ right_margin_putp(char *s1,
(void)tputs(TPARM1(exit_attribute_mode), 1, outch);
}
+/* ==========================================================*/
+/* Displays an horizontal scroll bar below the window. */
+/* The bar if only displayed in line or column mode when the */
+/* line containing the cursor is truncated. */
+/* */
+/* mark is the offset of the cursor in the bar. */
+/* ==========================================================*/
+void
+disp_hbar(win_t *win, term_t *term, langinfo_t *langinfo, int pos1, int pos2)
+{
+ int i;
+
+ apply_attr(term, win->bar_attr);
+
+ (void)tputs(TPARM1(clr_eol), 1, outch);
+
+ /* Draw the left symbol arrow. */
+ /* """""""""""""""""""""""""""" */
+ if (langinfo->utf8)
+ {
+ if (pos1 == 0)
+ fputs_safe(hbar_begin, stdout);
+ else
+ fputs_safe(hbar_left, stdout);
+ }
+ else
+ {
+ if (pos1 == 0)
+ fputc_safe('<', stdout);
+ else
+ fputc_safe('\\', stdout);
+ }
+
+ /* Draw the line in the horizontal bar. */
+ /* """""""""""""""""""""""""""""""""""" */
+ if (term->has_rep && !langinfo->utf8)
+ (void)tputs(TPARM3(repeat_char, '-', term->ncolumns - 2), 1, outch);
+ else
+ {
+ char *s;
+
+ if (langinfo->utf8)
+ s = hbar_line;
+ else
+ s = "-";
+
+ for (i = 0; i < term->ncolumns - 3; i++)
+ fputs_safe(s, stdout);
+ }
+
+ /* Draw the cursor. */
+ /* """""""""""""""" */
+ if (term->has_hpa)
+ {
+ char *s;
+
+ if (langinfo->utf8)
+ s = hbar_curs;
+ else
+ s = "#";
+
+ (void)tputs(TPARM2(column_address, pos1 + 1), 1, outch);
+ for (i = pos1 + 1; i <= pos2 + 1; i++)
+ fputs_safe(s, stdout);
+
+ (void)tputs(TPARM2(column_address, term->ncolumns - 2), 1, outch);
+ }
+ else if (term->has_parm_right_cursor)
+ {
+ char *s;
+
+ if (langinfo->utf8)
+ s = hbar_curs;
+ else
+ s = "#";
+
+ fputs_safe("\r", stdout);
+ (void)tputs(TPARM2(parm_right_cursor, pos1 + 1), 1, outch);
+
+ for (i = pos1 + 2; i <= pos2 + 1; i++)
+ fputs_safe(s, stdout);
+
+ (void)tputs(TPARM2(parm_right_cursor, term->ncolumns - 3 - pos2 - 2),
+ 1,
+ outch);
+ }
+ else
+ {
+ char *s;
+
+ if (langinfo->utf8)
+ s = hbar_curs;
+ else
+ s = "#";
+
+ fputs_safe("\r", stdout);
+ (void)tputs(TPARM2(cursor_right, 1), 1, outch);
+ for (i = 0; i < pos1; i++)
+ (void)tputs(TPARM1(cursor_right), 1, outch);
+
+ for (i = pos1 + 2; i <= pos2 + 1; i++)
+ fputs_safe(s, stdout);
+
+ for (i = pos1; i < term->ncolumns - 3 - pos2 - 2; i++)
+ (void)tputs(TPARM1(cursor_right), 1, outch);
+ }
+
+ /* Draw the right symbol arrow. */
+ /* """""""""""""""""""""""""""" */
+ if (langinfo->utf8)
+ {
+ if (pos2 == term->ncolumns - 4)
+ fputs_safe(hbar_end, stdout);
+ else
+ fputs_safe(hbar_right, stdout);
+ }
+ else
+ {
+ if (pos2 == term->ncolumns - 4)
+ fputc_safe('>', stdout);
+ else
+ fputc_safe('/', stdout);
+ }
+
+ (void)tputs(TPARM1(exit_attribute_mode), 1, outch);
+}
+
/* *************** */
/* Core functions. */
/* *************** */
@@ -3839,7 +3974,10 @@ build_metadata(term_t *term, long count, win_t *win)
/* it to 0 and increment it later in the loop. */
/* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
if (!win->col_mode)
- win->max_width = 0;
+ {
+ win->max_width = 0;
+ win->real_max_width = 0;
+ }
tab_count = 0;
while (i < count)
@@ -3906,7 +4044,9 @@ build_metadata(term_t *term, long count, win_t *win)
/* Update the effective line width. */
/* '''''''''''''''''''''''''''''''' */
if (len > term->ncolumns)
+ {
win->max_width = term->ncolumns - 2;
+ }
else
win->max_width = len;
}
@@ -4513,10 +4653,20 @@ disp_lines(win_t *win,
{
long lines_disp;
long i;
- char scroll_symbol[5];
+ char left_margin_symbol[5]; /* Placeholder for the arrow symbols. */
long len;
- long display_bar;
+ long has_vbar; /* Flag to signal the presence of the vertical bar. */
long first_start;
+ int leftmost_start; /* Starting position of the leftmost selectable *
+ | word in the window lines. */
+ int rightmost_end; /* Ending position of the rightmost selectable *
+ | word in the window lines. */
+
+ long first_line; /* real line # on the first line of the window. */
+
+ int row1, row2, col; /* Only the rows are used to detect a *
+ | bottom-of-page scrolling, col is *
+ | necessary but not required here. */
sigset_t mask;
@@ -4528,16 +4678,21 @@ disp_lines(win_t *win,
sigaddset(&mask, SIGALRM);
sigprocmask(SIG_BLOCK, &mask, NULL);
- scroll_symbol[0] = ' ';
- scroll_symbol[1] = '\0';
+ left_margin_symbol[0] = ' ';
+ left_margin_symbol[1] = '\0';
- lines_disp = 1;
- first_start = -1;
+ lines_disp = 1;
+ first_start = -1;
+ leftmost_start = 0;
- /* Initialize the truncates lines flag. */
+ /* Initialize the truncated lines flag. */
/* """""""""""""""""""""""""""""""""""" */
win->has_truncated_lines = 0;
+ /* Initialize the necessity of displaying the horizontal scroll bar or not. */
+ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ win->has_hbar = 0;
+
/* Initialize the selectable column guard to its maximum position. */
/* for the first window line. */
/* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
@@ -4546,7 +4701,7 @@ disp_lines(win_t *win,
(void)tputs(TPARM1(save_cursor), 1, outch);
- i = win->start;
+ i = win->start; /* Index of the first word in the window. */
/* Modify the max number of displayed lines if we do not have */
/* enough place. */
@@ -4555,9 +4710,9 @@ disp_lines(win_t *win,
win->max_lines = term->nlines - win->message_lines;
if (last_line >= win->max_lines)
- display_bar = 1;
+ has_vbar = 1;
else
- display_bar = 0;
+ has_vbar = 0;
if (win->col_mode || win->line_mode)
len = term->ncolumns - 3;
@@ -4576,16 +4731,19 @@ disp_lines(win_t *win,
if (win->first_column > 0)
{
if (langinfo->utf8)
- strcpy(scroll_symbol, shift_left_sym);
+ strcpy(left_margin_symbol, shift_left_sym);
else
- strcpy(scroll_symbol, "<");
+ strcpy(left_margin_symbol, "<");
+
+ if (!toggles->no_hor_scrollbar)
+ win->has_hbar = 1;
}
if (!win->has_truncated_lines)
win->has_truncated_lines = 1;
}
else
- scroll_symbol[0] = '\0';
+ left_margin_symbol[0] = '\0';
/* Center the display ? */
/* """""""""""""""""""" */
@@ -4596,7 +4754,10 @@ disp_lines(win_t *win,
fputc_safe(' ', stdout);
}
- left_margin_putp(scroll_symbol, term, win);
+ left_margin_putp(left_margin_symbol, term, win);
+
+ first_line = line_nb_of_word_a[i];
+
while (len > 1 && i <= count - 1)
{
/* Display one word and the space or symbol following it. */
@@ -4609,14 +4770,48 @@ disp_lines(win_t *win,
disp_word(i, search_mode, search_data, term, win, toggles, tmp_word);
- /* If there are more element to be displayed after the right margin. */
- /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ /* Calculate the start offset of the last word of the line */
+ /* containing the cursor in column or line mode. */
+ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ if ((win->col_mode || win->line_mode)
+ && line_nb_of_word_a[current] - first_line + 1 == lines_disp)
+ {
+ long wi = count - 1;
+
+ wi = first_word_in_line_a[lines_disp + first_line - 1];
+ while (wi < current && !word_a[wi].is_selectable)
+ wi++;
+
+ leftmost_start = word_a[wi++].start;
+
+ if (lines_disp + first_line > last_line)
+ wi = count - 1;
+ else
+ wi = first_word_in_line_a[lines_disp + first_line] - 1;
+
+ while (!word_a[wi].is_selectable)
+ wi--;
+
+ rightmost_end = word_a[wi].end;
+ }
+
+ /* If there are more element to be displayed after the right margin */
+ /* in column or line mode. */
+ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
if ((win->col_mode || win->line_mode) && i < count - 1
&& word_a[i + 1].end >= len + win->first_column)
{
if (!win->has_truncated_lines)
win->has_truncated_lines = 1;
+ /* Toggle the presence of the horizontal bar if allowed and */
+ /* if this line contains the cursor in column or line mode. */
+ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ if (!toggles->no_hor_scrollbar
+ && line_nb_of_word_a[current] - first_line + 1 == lines_disp)
+ win->has_hbar = 1; /* the line containing the cursor is *
+ | truncated in the window. */
+
apply_attr(term, win->shift_attr);
if (langinfo->utf8)
@@ -4632,28 +4827,28 @@ disp_lines(win_t *win,
shift_right_sym_pos_a[line_nb_of_word_a[i]] = word_a[i].end + 1
- first_start + 2;
}
+ else
+ /* If we want to display the gutter. */
+ /* """"""""""""""""""""""""""""""""" */
+ if (!word_a[i].is_last && win->col_sep
+ && (win->tab_mode || win->col_mode))
+ {
+ long pos;
- /* If we want to display the gutter. */
- /* """"""""""""""""""""""""""""""""" */
- else if (!word_a[i].is_last && win->col_sep
- && (win->tab_mode || win->col_mode))
- {
- long pos;
-
- /* Make sure that we are using the right gutter character even */
- /* if the first displayed word is * not the first of its line. */
- /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
- pos = i - first_word_in_line_a[line_nb_of_word_a[i]];
+ /* Make sure that we are using the right gutter character even */
+ /* if the first displayed word is * not the first of its line. */
+ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ pos = i - first_word_in_line_a[line_nb_of_word_a[i]];
- if (pos >= win->gutter_nb) /* Use the last gutter character. */
- fputs_safe(win->gutter_a[win->gutter_nb - 1], stdout);
+ if (pos >= win->gutter_nb) /* Use the last gutter character. */
+ fputs_safe(win->gutter_a[win->gutter_nb - 1], stdout);
+ else
+ fputs_safe(win->gutter_a[pos], stdout);
+ }
else
- fputs_safe(win->gutter_a[pos], stdout);
- }
- else
- /* Else just display a space. */
- /* """""""""""""""""""""""""" */
- fputc_safe(' ', stdout);
+ /* Else just display a space. */
+ /* """""""""""""""""""""""""" */
+ fputc_safe(' ', stdout);
}
/* Mark the line as the current line, the line containing the cursor. */
@@ -4670,7 +4865,7 @@ disp_lines(win_t *win,
{
/* If we have more than one line to display. */
/* """"""""""""""""""""""""""""""""""""""""" */
- if (display_bar && !toggles->no_scrollbar
+ if (has_vbar && !toggles->no_scrollbar
&& (lines_disp > 1 || i < count - 1))
{
/* Store the scroll bar column position. */
@@ -4731,7 +4926,7 @@ disp_lines(win_t *win,
+ 2)
== lines_disp)
right_margin_putp(sbar_curs,
- "+",
+ "#",
langinfo,
term,
win,
@@ -4761,7 +4956,7 @@ disp_lines(win_t *win,
fputc_safe(' ', stdout);
}
- left_margin_putp(scroll_symbol, term, win);
+ left_margin_putp(left_margin_symbol, term, win);
}
/* We do not increment the number of lines seen after */
@@ -4786,7 +4981,7 @@ disp_lines(win_t *win,
{
/* The last line of the window has been displayed. */
/* """"""""""""""""""""""""""""""""""""""""""""""" */
- if (display_bar && line_nb_of_word_a[i] == last_line)
+ if (has_vbar && line_nb_of_word_a[i] == last_line)
{
if (!toggles->no_scrollbar)
{
@@ -4810,7 +5005,7 @@ disp_lines(win_t *win,
}
else
{
- if (display_bar && !toggles->no_scrollbar)
+ if (has_vbar && !toggles->no_scrollbar)
right_margin_putp(sbar_arr_down,
"v",
langinfo,
@@ -4832,6 +5027,56 @@ disp_lines(win_t *win,
i++;
}
+ /* Display the horizontal bar when needed. */
+ /* """"""""""""""""""""""""""""""""""""""" */
+ if (win->col_mode || win->line_mode)
+ {
+ /* Save again the cursor position before drawing the horizontal bar. */
+ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ get_cursor_position(&row1, &col); /* col is not needed here. */
+
+ if (win->has_hbar)
+ {
+ int pos1; /* Pos. of the cursor's start in the horizontal scroll bar. */
+ int pos2; /* Pos. of the cursor's end in the horizontal scroll bar. */
+
+ /* Note: in the following expression, rightmost_start is always */
+ /* greater then leftmost_start as a line containing a single word */
+ /* cannot be truncated and have an horizontal scroll bar hence */
+ /* win->has_hbar = 0. */
+ /* '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' */
+ pos1 = (int)(word_a[current].start - leftmost_start)
+ / (float)(rightmost_end - leftmost_start) * (term->ncolumns - 4);
+ pos2 = (int)(word_a[current].end - leftmost_start)
+ / (float)(rightmost_end - leftmost_start) * (term->ncolumns - 4);
+
+ if (pos2 > term->ncolumns - 4)
+ pos2 = term->ncolumns
+ - 4; /* just to make sure but should not happen. */
+
+ fputs_safe("\n", stdout);
+ disp_hbar(win, term, langinfo, pos1, pos2);
+
+ /* Mark the fact that an horizontal scroll bar has been displayed */
+ /* and its space allocated. */
+ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ if (win->hbar_displayed == 0)
+ win->hbar_displayed = 1;
+ }
+ else if (win->hbar_displayed) /* The horizontal scroll bar has already *
+ | been displayed, keep this space empty *
+ | to not disturb the display. */
+ {
+ fputs_safe("\n", stdout);
+ (void)tputs(TPARM1(clr_eol), 1, outch);
+ }
+
+ /* Save again the cursor position again (especially the row) to detect */
+ /* an automatic scroll up when the cursor is at the bottom of the window */
+ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ get_cursor_position(&row2, &col);
+ }
+
/* Update win->end, this is necessary because we only */
/* call build_metadata on start and on terminal resize. */
/* """""""""""""""""""""""""""""""""""""""""""""""""""" */
@@ -4839,15 +5084,28 @@ disp_lines(win_t *win,
win->end = i - 1;
else
win->end = i;
+
/* We restore the cursor position saved before the display of the window. */
/* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
(void)tputs(TPARM1(restore_cursor), 1, outch);
+ /* Make sure the cursor is correctly moved when the horizontal scroll */
+ /* bar is displayed and the window is at the bottom of the screen. */
+ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ if (win->col_mode || win->line_mode)
+ {
+ if (win->has_hbar && row1 == row2) /* Screen scrolled up. */
+ {
+ (void)tputs(TPARM1(cursor_up), 1, outch);
+ term->curs_line--;
+ }
+ }
+
/* Re-enable the periodic timer. */
/* """"""""""""""""""""""""""""" */
sigprocmask(SIG_UNBLOCK, &mask, NULL);
- return lines_disp;
+ return lines_disp + (win->hbar_displayed ? 1 : 0);
}
/* ======================================================= */
@@ -6104,6 +6362,7 @@ init_main_ds(attrib_t *init_attr,
win->first_column = 0;
win->real_max_width = 0;
win->sb_column = -1;
+ win->hbar_displayed = 0;
win->cursor_attr = *init_attr;
win->cursor_marked_attr = *init_attr;
@@ -6288,7 +6547,7 @@ lines_action(char *ctx_name,
/* No need to validate if values are numeric here, they have */
/* already been validated by the check_integer_constraint filter. */
/* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
- sscanf(values[0], "%ld", &(win->asked_max_lines));
+ sscanf(values[0], "%d", &(win->asked_max_lines));
else
win->asked_max_lines = 0;
}
@@ -6519,7 +6778,15 @@ toggle_action(char *ctx_name,
else if (strcmp(opt_name, "blank_nonprintable") == 0)
toggles->blank_nonprintable = 1;
else if (strcmp(opt_name, "no_scroll_bar") == 0)
- toggles->no_scrollbar = 1;
+ {
+ toggles->no_scrollbar = 1;
+ toggles->no_hor_scrollbar = 1;
+ }
+ else if (strcmp(opt_name, "no_hor_scroll_bar") == 0)
+ {
+ if (!toggles->no_scrollbar)
+ toggles->no_hor_scrollbar = 1;
+ }
else if (strcmp(opt_name, "auto_tag") == 0)
toggles->autotag = 1;
else if (strcmp(opt_name, "no_auto_tag") == 0)
@@ -8713,6 +8980,7 @@ main(int argc, char *argv[])
"[keep_spaces] "
"[word_separators #bytes] "
"[no_scroll_bar] "
+ "[no_hor_scroll_bar] "
"[early_subst_all... #/regex/repl/opts] "
"[post_subst_all... #/regex/repl/opts] "
"[post_subst_included... #/regex/repl/opts] "
@@ -8885,6 +9153,9 @@ main(int argc, char *argv[])
ctxopt_add_opt_settings(parameters,
"no_scroll_bar",
"-q -no_bar -no_scroll_bar");
+ ctxopt_add_opt_settings(parameters,
+ "no_hor_scroll_bar",
+ "-no_hbar -no_hor_scroll_bar");
ctxopt_add_opt_settings(parameters, "early_subst_all", "-ES -early_subst");
ctxopt_add_opt_settings(parameters, "post_subst_all", "-S -subst");
ctxopt_add_opt_settings(parameters,
@@ -9058,6 +9329,11 @@ main(int argc, char *argv[])
&toggles,
(char *)0);
ctxopt_add_opt_settings(actions,
+ "no_hor_scroll_bar",
+ toggle_action,
+ &toggles,
+ (char *)0);
+ ctxopt_add_opt_settings(actions,
"start_pattern",
set_pattern_action,
&pre_selection_index,
@@ -9468,6 +9744,8 @@ main(int argc, char *argv[])
term.has_blink = (str == (char *)-1 || str == NULL) ? 0 : 1;
str = tigetstr("kmous");
term.has_kmous = (str == (char *)-1 || str == NULL) ? 0 : 1;
+ str = tigetstr("rep");
+ term.has_rep = (str == (char *)-1 || str == NULL) ? 0 : 1;
}
if (!term.has_cursor_up || !term.has_cursor_down || !term.has_cursor_left
@@ -9922,11 +10200,11 @@ main(int argc, char *argv[])
else if (win.asked_max_lines >= 0)
{
if (win.asked_max_lines == 0)
- win.max_lines = term.nlines - win.message_lines;
+ win.max_lines = term.nlines - win.message_lines - 1;
else
{
if (win.asked_max_lines > term.nlines - win.message_lines)
- win.max_lines = term.nlines - win.message_lines;
+ win.max_lines = term.nlines - win.message_lines - 1;
else
win.max_lines = win.asked_max_lines;
}
@@ -12541,6 +12819,11 @@ main(int argc, char *argv[])
tmp_word,
&langinfo);
+ /* Assert the presence of an early display of the horizontal bar. */
+ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ if (win.has_hbar)
+ win.hbar_displayed = 1;
+
/* Determine the number of lines to move the cursor up if the window */
/* display needed a terminal scrolling. */
/* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
@@ -12829,6 +13112,26 @@ main(int argc, char *argv[])
win.first_column = word_a[pos].start;
}
+ /* Keep a line available for an eventual horizontal scroll bar. */
+ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ if (win.col_mode || win.line_mode)
+ {
+ if (win.asked_max_lines == 0
+ || win.max_lines > term.nlines - win.message_lines)
+ {
+ win.max_lines = term.nlines - win.message_lines - 1;
+ {
+ (void)tputs(TPARM3(cursor_address, win.max_lines, 0), 1, outch);
+ (void)tputs(TPARM1(clr_eol), 1, outch);
+ (void)tputs(TPARM3(cursor_address, 0, 0), 1, outch);
+ }
+ }
+ else if (win.asked_max_lines > term.nlines - win.message_lines)
+ win.max_lines = term.nlines - win.message_lines - 1;
+ else
+ win.max_lines = win.asked_max_lines;
+ }
+
disp_message(message_lines_list,
message_max_width,
message_max_len,
@@ -13567,9 +13870,6 @@ main(int argc, char *argv[])
break;
}
- /* Erase or jump after the window before printing the */
- /* selected string. */
- /* """""""""""""""""""""""""""""""""""""""""""""""""" */
if (toggles.del_line)
{
for (i = 0; i < win.message_lines; i++)
@@ -15314,7 +15614,8 @@ main(int argc, char *argv[])
/* Do not do anything if the user has above or below the window. */
/* """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
if (line_click < term.curs_line
- || line_click >= term.curs_line + win.max_lines)
+ || line_click
+ >= term.curs_line + win.max_lines + (win.has_hbar ? 1 : 0))
break;
/* Mouse wheel scroll down. */
@@ -15337,8 +15638,8 @@ main(int argc, char *argv[])
if (state == 80 && old_button == 0)
goto kpp; /* PgUp. */
- /* Manage the clicks at the ends of the scroll bar. */
- /* """""""""""""""""""""""""""""""""""""""""""""""" */
+ /* Manage the clicks at the ends of the vertical scroll bar. */
+ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""""" */
if (button == 0 && column_click == win.sb_column + 1)
{
if (line_click == term.curs_line + win.max_lines - 1)
@@ -15406,105 +15707,145 @@ main(int argc, char *argv[])
}
}
}
-
- /* Manage clicks on the horizontal arrows if any. */
- /* """""""""""""""""""""""""""""""""""""""""""""" */
- if (win.has_truncated_lines
- && shift_arrow_clicked(&win,
- &term,
- line_click,
- column_click,
- &clicked_line,
- &clicked_arrow))
- {
- if (button == 0)
- switch (clicked_arrow)
- {
- case 0: /* left */
- shift_left(&win,
- &term,
- &toggles,
- &search_data,
- &langinfo,
- &nl,
- last_line,
- tmp_word,
- clicked_line);
- break;
-
- case 1: /* right */
- shift_right(&win,
- &term,
- &toggles,
- &search_data,
- &langinfo,
- &nl,
- last_line,
- tmp_word,
- clicked_line);
- break;
- }
- nl = disp_lines(&win,
- &toggles,
- current,
- count,
- search_mode,
- &search_data,
- &term,
- last_line,
- tmp_word,
- &langinfo);
- }
else
- {
- /* Get the new current word on click. */
- /* """""""""""""""""""""""""""""""""" */
- error = 0;
- new_current = get_clicked_index(&win,
- &term,
- line_click,
- column_click,
- &error);
-
- /* Update the selection index and refresh if needed. */
- /* """"""""""""""""""""""""""""""""""""""""""""""""" */
- if ((toggles.taggable || toggles.pinable || new_current != current)
- && error == 0)
+ /* Manage the clicks in the horizontal scroll bar. */
+ /* """"""""""""""""""""""""""""""""""""""""""""""" */
+ if (win.has_hbar && button == 0
+ && line_click == term.curs_line + win.max_lines)
{
- current = new_current;
+ long wi; /* Word index. */
+ long line = line_nb_of_word_a[current];
+ long leftmost;
+ long rightmost;
+ int leftmost_start;
+ int rightmost_end;
+
+ /* Find the first selectable word in the line */
+ /* containing the cursor. */
+ /* """""""""""""""""""""""""""""""""""""""""" */
+ wi = first_word_in_line_a[line];
- /* Manage the marking of a word. */
- /* (button 0 + CTRL or button 2 pressed). */
- /* """""""""""""""""""""""""""""""""""""" */
- if ((button == 0 && state == 16)
- && (toggles.taggable || toggles.pinable))
+ while (!word_a[wi].is_selectable)
+ wi++;
+
+ leftmost = wi;
+ leftmost_start = word_a[leftmost].start;
+
+ if (column_click == 1)
{
- if (marked == -1)
- goto mark_word;
- else
- goto unmark_word;
+ /* First, manage the case where the user clicked at the */
+ /* beginning of the scroll bar. */
+ /* """""""""""""""""""""""""""""""""""""""""""""""""""" */
+ if (current > leftmost && word_a[current].start > 0)
+ goto kl;
}
- /* Manage the tagging of a word. */
- /* (button 2 + CTRL or button 2 pressed). */
- /* """""""""""""""""""""""""""""""""""""" */
- if ((button == 2 && state == 0)
- && (toggles.taggable || toggles.pinable))
+ /* Else we need to calculate the rightmost selectable word */
+ /* in the line containing the cursor. */
+ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ else if (line == last_line)
+ wi = count - 1;
+ else
+ wi = first_word_in_line_a[line + 1] - 1;
+
+ while (!word_a[wi].is_selectable)
+ wi--;
+
+ rightmost = wi;
+
+ /* Manage the case where the users clicked at the end */
+ /* of the scroll bar. */
+ /* """""""""""""""""""""""""""""""""""""""""""""""""" */
+ if (column_click == term.ncolumns - 1)
+ if (current < rightmost && current < count - 1
+ && word_a[current + 1].start > 0)
+ goto kr;
+
+ /* Finally manage the core where the users clicked in */
+ /* the crossbar. */
+ /* """""""""""""""""""""""""""""""""""""""""""""""""" */
+ rightmost_end = word_a[rightmost].end;
+
{
- if (word_a[current].tag_id > 0)
- goto kdel;
- else
- goto kins;
+ long index;
+ int target;
+ double ratio;
+
+ if (column_click >= 2 && column_click - 2 <= term.ncolumns - 4)
+ {
+ ratio = (1.0 * column_click - 2) / (term.ncolumns - 4);
+ target = (int)((rightmost_end - leftmost_start + 1) * ratio)
+ + leftmost_start;
+
+ if (target > 0) /* General case. */
+ {
+ if (word_a[current].start <= target)
+ index = current;
+ else
+ index = leftmost;
+
+ while (index <= rightmost && word_a[index].start <= target)
+ current = index++;
+ }
+ else /* Trivial case. */
+ current = leftmost;
+
+ set_new_first_column(&win, &term);
+
+ nl = disp_lines(&win,
+ &toggles,
+ current,
+ count,
+ search_mode,
+ &search_data,
+ &term,
+ last_line,
+ tmp_word,
+ &langinfo);
+ }
}
- if ((button == 2 && state == 16)
- && (toggles.taggable || toggles.pinable))
- goto adaptative_tag_to_mark; /* Like 'Z' keyboard command. */
+ break;
+ }
+ else
- /* Redisplay the new window if the first button was pressed */
- /* otherwise reset the cursor position to its previous value. */
- /* """""""""""""""""""""""""""""""""""""""""""""""""""""""""" */
- if (button == 0 || button == 2)
+ /* Manage clicks on the horizontal arrows in lines if any. */
+ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ if (win.has_truncated_lines
+ && shift_arrow_clicked(&win,
+ &term,
+ line_click,
+ column_click,
+ &clicked_line,
+ &clicked_arrow))
+ {
+ if (button == 0)
+ switch (clicked_arrow)
+ {
+ case 0: /* left */
+ shift_left(&win,
+ &term,
+ &toggles,
+ &search_data,
+ &langinfo,
+ &nl,
+ last_line,
+ tmp_word,
+ clicked_line);
+ break;
+
+ case 1: /* right */
+ shift_right(&win,
+ &term,
+ &toggles,
+ &search_data,
+ &langinfo,
+ &nl,
+ last_line,
+ tmp_word,
+ clicked_line);
+ break;
+ }
nl = disp_lines(&win,
&toggles,
current,
@@ -15515,49 +15856,112 @@ main(int argc, char *argv[])
last_line,
tmp_word,
&langinfo);
- else
- current = old_current;
- }
-
- /* Manage double clicks if the clicked word is selectable. */
- /* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */
- if (!disable_double_click && button == 0)
- {
- /* More than one clicks on the same word? */
- /* """""""""""""""""""""""""""""""""""""" */
- if (click_nr > 0 && old_current == current)
- {
- double delay;
-
- /* Get the delay between the actual click and */
- /* the previous one. */
- /* """""""""""""""""""""""""""""""""""""""""" */
- clock_gettime(CLOCK_MONOTONIC, &actual_click_ts);
- delay = (1000.0 * actual_click_ts.tv_sec
- + 1e-6 * actual_click_ts.tv_nsec)
- - (1000.0 * last_click_ts.tv_sec
- + 1e-6 * last_click_ts.tv_nsec);
-
- if (!error && delay > 0 && delay <= mouse.double_click_delay)
- goto enter; /* Press Enter. */
- else
- clock_gettime(CLOCK_MONOTONIC, &last_click_ts);
}
else
{
- /* The first click on a selectable was not make yet. */
+ /* Get the new current word on click. */
+ /* """""""""""""""""""""""""""""""""" */
+ error = 0;
+ new_current = get_clicked_index(&win,
+ &term,
+