summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpgen <p.gen.progs@gmail.com>2022-11-12 22:30:29 +0100
committerpgen <p.gen.progs@gmail.com>2022-11-12 23:02:21 +0100
commit8046035843fabcfb8cff084e4282819445603db6 (patch)
treed8af1d23aaba538c8400b8eb216761fb52f0f008
parentcad6ed5a6281941ebafe9d776f9b71947a04e620 (diff)
Fix the tagging code and update the manual
-rw-r--r--smenu.143
-rw-r--r--smenu.c264
-rw-r--r--smenu.h114
3 files changed, 231 insertions, 190 deletions
diff --git a/smenu.1 b/smenu.1
index 2ecf6a5..f0c0d72 100644
--- a/smenu.1
+++ b/smenu.1
@@ -269,13 +269,6 @@ The keyboard commands \fB<\fP and \fB>\fP can be used in such a case
because the cursor is already on the current line.
.RE
.P
-\fBPaste (second and usually middle) mouse button\fP:
-.RS 2
-.IP \(bu 2
-When tagging or pinning is enabled, a click undoes the latest taggging
-operation.
-.RE
-.P
\fBThird (usually right) mouse button\fP:
.RS 2
.IP \(bu 2
@@ -330,8 +323,9 @@ such a terminal emulator is screen < 4.7.0.
tmux as well as screen >= 4.7.0 are fine.
Keyboard and mouse can be used at the same time.
-
-\fBRemark 1\fP, some X-Window terminal emulators may not support the
+.TP 2
+\fBRemark 1.\fP
+Some X-Window terminal emulators may not support the
enable/disable bracketed pastes escape sequence, in such a case if
may be necessary to explicitly clear the content of the paste buffer
before running smenu so that the mouse buttons (especially for pasting)
@@ -339,18 +333,19 @@ do their job correctly.
.br
This action can easily be performed using the command \f(CRxsel -c\fP
for example.
-
-\fBRemark 2\fP, some X-Windows terminal emulators intercept mouse input
+.TP 2
+\fBRemark 2.\fP
+Some X-Windows terminal emulators intercept mouse input
when some modifiers are used, a typical example is xterm which displays
popup menus in these cases.
.br
-For xterm a working workaround is to use the X resource
-\f(CRXTerm*omitTranslation:popup-menu\fP either by adding it in
-your \f(CR.Xresources\fP file and register it with \f(CRxrdb\fP or by
-launching xterm using the \f(CR-xrm 'XTerm*omitTranslation:popup-menu'\fP
-command line option.
+For xterm (Patch #361 - 2020/10/14 or later) a working workaround
+is to use the X resource \f(CRXTerm*omitTranslation:popup-menu\fP
+either by adding it in your \f(CR.Xresources\fP file and register
+it with \f(CRxrdb\fP or by launching xterm using the
+\f(CR-xrm 'XTerm*omitTranslation:popup-menu'\fP command line option.
.TP 2
-\fBImportant note for BSD systems:\fP
+\fBRemark 3 for BSD systems.\fP
In order for the mouse to work properly under (virtualised?) FreeBSD
and perhaps other BSD variants, it may be necessary add the following
two lines to the file \fB~/.Xmodmap\fP:
@@ -602,13 +597,17 @@ Tags or pins all the selectable words in the current \fBrow/line\fP.
Marks the current word, the cursor aspect will change until the word
is unmarked.
.TP
-\fBM\fP
-Unmarks the current word, other actions will automatically unmark the
-word, see below.
+\fBM\fP or \fBESC\fP
+Unmarks the current word, other actions will also automatically unmark
+the word, see below.
.TP
\fBT\fP
-If no word are marked then tags the current one, else tags all word
-between the marked one and the current one.
+If no word are marked and the result of a search is still displayed then
+tags all words found in this search.
+
+If no word has been searched and no word is marked, then the current
+word is marked, otherwise all words between the marked word and the
+current word are tagged.
.br
If the marked word and the current word are on the same line/column
then only the words in this line/column will be tagged/pinned.
diff --git a/smenu.c b/smenu.c
index 1660173..322c1f3 100644
--- a/smenu.c
+++ b/smenu.c
@@ -10574,20 +10574,32 @@ main(int argc, char * argv[])
/* """"""""""""""""""""""""""""""""""""""""""""""""""""" */
if (memcmp("\x1b[200~", buffer, 6) == 0)
{
- int c, eb[6];
+ int c;
+ char eb[6] = { 0 };
/* Consume stdin until a closing bracket is found. */
/* ''''''''''''''''''''''''''''''''''''''''''''''' */
while (1)
{
+ /* Fast reading until an ESC or the end of input is found. */
+ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */
while ((c = my_fgetc(stdin)) != EOF && c != 0x1b)
; /* Null action. */
- if (c == EOF || scanf("[201~", eb))
+ /* Exits the loop early if the first ESC character starting */
+ /* the ending bracket has already be consumed while reading */
+ /* the content of buffer. */
+ /* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ if (c == EOF)
break;
- }
- goto untag_last_tagged;
+ /* Read the 5 next characters to look for the */
+ /* ending bracket "[201~". */
+ /* """""""""""""""""""""""""""""""""""""""""" */
+ scanf("%5c", eb);
+ if (memcmp("[201~", eb, 5) == 0)
+ break;
+ }
}
/* An escape sequence or a UTF-8 sequence has been pressed. */
@@ -10791,6 +10803,12 @@ main(int argc, char * argv[])
reset_search_buffer(&win, &search_data, &timers, &toggles, &term,
&daccess, &langinfo, last_line, tmp_word,
word_real_max_size);
+
+ /* Unmark the marked word. */
+ /* """"""""""""""""""""""" */
+ if (toggles.taggable && marked >= 0)
+ goto unmark_word;
+
break;
}
@@ -11768,86 +11786,89 @@ main(int argc, char * argv[])
/* """""""""""""""""""""""""""""""""""""""""""""" */
if (search_mode == NONE)
{
- long col, cur_col, marked_col;
- long first, last;
- int tagged;
-
- if (!win.col_mode)
- break;
+ if (toggles.taggable || toggles.pinable)
+ {
+ long col, cur_col, marked_col;
+ long first, last;
+ int tagged;
- /* Get the current column number. */
- /* """""""""""""""""""""""""""""" */
- cur_col = current - first_word_in_line_a[line_nb_of_word_a[current]]
- + 1;
+ if (!win.col_mode)
+ break;
- /* Determine the loop values according to the existence of */
- /* a marked word and is value. */
- /* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */
- if (marked == -1)
- {
- first = 0;
- last = count - 1;
- }
- else
- {
- marked_col = marked
- - first_word_in_line_a[line_nb_of_word_a[marked]]
- + 1;
+ /* Get the current column number. */
+ /* """""""""""""""""""""""""""""" */
+ cur_col = current
+ - first_word_in_line_a[line_nb_of_word_a[current]] + 1;
- /* Ignore the marked word is its is not on the same column */
- /* as the current word. */
+ /* Determine the loop values according to the existence of */
+ /* a marked word and is value. */
/* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */
- if (cur_col == marked_col)
+ if (marked == -1)
{
- if (marked <= current)
+ first = 0;
+ last = count - 1;
+ }
+ else
+ {
+ marked_col = marked
+ - first_word_in_line_a[line_nb_of_word_a[marked]]
+ + 1;
+
+ /* Ignore the marked word is its is not on the same column */
+ /* as the current word. */
+ /* """"""""""""""""""""""""""""""""""""""""""""""""""""""" */
+ if (cur_col == marked_col)
{
- first = first_word_in_line_a[line_nb_of_word_a[marked]];
- last = current;
+ if (marked <= current)
+ {
+ first = first_word_in_line_a[line_nb_of_word_a[marked]];
+ last = current;
+ }
+ else
+ {
+ first = first_word_in_line_a[line_nb_of_word_a[current]];
+ last = marked;
+ }
}
else
- {
- first = first_word_in_line_a[line_nb_of_word_a[current]];
- last = marked;
- }
+ break;
}
- else
- break;
- }
- /* Tag from first to last. */
- /* """"""""""""""""""""""" */
- col = 0;
- tagged = 0;
+ /* Tag from first to last. */
+ /* """"""""""""""""""""""" */
+ col = 0;
+ tagged = 0;
- for (wi = first; wi <= last; wi++)
- {
- col++;
- if (col == cur_col && word_a[wi].is_selectable
- && word_a[wi].tag_id == 0)
+ for (wi = first; wi <= last; wi++)
{
- word_a[wi].tag_id = win.next_tag_id;
- tagged_words++;
+ col++;
+ if (col == cur_col && word_a[wi].is_selectable
+ && word_a[wi].tag_id == 0)
+ {
+ word_a[wi].tag_id = win.next_tag_id;
+ tagged_words++;
- if (toggles.pinable)
- word_a[wi].tag_order = tag_nb++;
+ if (toggles.pinable)
+ word_a[wi].tag_order = tag_nb++;
- tagged = 1;
- }
+ tagged = 1;
+ }
- /* Time to go back to column 1? */
- /* """""""""""""""""""""""""""" */
- if (word_a[wi].is_last)
- col = 0;
- }
+ /* Time to go back to column 1? */
+ /* """""""""""""""""""""""""""" */
+ if (word_a[wi].is_last)
+ col = 0;
+ }
- if (tagged)
- win.next_tag_id++;
+ if (tagged)
+ win.next_tag_id++;
- marked = -1;
+ marked = -1;
- nl = disp_lines(&win, &toggles, current, count, search_mode,
- &search_data, &term, last_line, tmp_word,
- &langinfo);
+ nl = disp_lines(&win, &toggles, current, count, search_mode,
+ &search_data, &term, last_line, tmp_word,
+ &langinfo);
+ }
}
else
goto special_cmds_when_searching;
@@ -11864,6 +11885,9 @@ main(int argc, char * argv[])
if (!win.col_mode)
break;
+ if (!toggles.taggable && !toggles.pinable)
+ break;
+
if (marked == -1)
goto mark_word;
@@ -11879,72 +11903,76 @@ main(int argc, char * argv[])
/* """""""""""""""""""""""""""""""""""""""""""" */
if (search_mode == NONE)
{
- long first, last;
- long marked_line;
- int tagged;
+ if (toggles.taggable || toggles.pinable)
+ {
+ long first, last;
+ long marked_line;
+ int tagged;
- if (!win.col_mode && !win.line_mode)
- break;
+ if (!win.col_mode && !win.line_mode)
+ break;
- if (marked >= 0)
- {
- marked_line = line_nb_of_word_a[marked];
- if (marked_line == line_nb_of_word_a[current])
+ if (marked >= 0)
{
- if (marked <= current)
+ marked_line = line_nb_of_word_a[marked];
+ if (marked_line == line_nb_of_word_a[current])
{
- first = marked;
- last = current;
+ if (marked <= current)
+ {
+ first = marked;
+ last = current;
+ }
+ else
+ {
+ first = current;
+ last = marked;
+ }
}
else
- {
- first = current;
- last = marked;
- }
+ break;
}
else
- break;
- }
- else
- {
- first = first_word_in_line_a[line_nb_of_word_a[current]];
- if (line_nb_of_word_a[current] == line_nb_of_word_a[count - 1])
- last = count - 1;
- else
- last = first_word_in_line_a[line_nb_of_word_a[current] + 1] - 1;
- }
+ {
+ first = first_word_in_line_a[line_nb_of_word_a[current]];
+ if (line_nb_of_word_a[current] == line_nb_of_word_a[count - 1])
+ last = count - 1;
+ else
+ last = first_word_in_line_a[line_nb_of_word_a[current] + 1]
+ - 1;
+ }
- /* Tag from first to last. */
- /* """"""""""""""""""""""" */
- wi = first;
- tagged = 0;
+ /* Tag from first to last. */
+ /* """"""""""""""""""""""" */
+ wi = first;
+ tagged = 0;
- do
- {
- if (word_a[wi].is_selectable)
+ do
{
- if (word_a[wi].tag_id == 0)
+ if (word_a[wi].is_selectable)
{
- word_a[wi].tag_id = win.next_tag_id;
- tagged_words++;
+ if (word_a[wi].tag_id == 0)
+ {
+ word_a[wi].tag_id = win.next_tag_id;
+ tagged_words++;
- if (toggles.pinable)
- word_a[wi].tag_order = tag_nb++;
+ if (toggles.pinable)
+ word_a[wi].tag_order = tag_nb++;
- tagged = 1;
+ tagged = 1;
+ }
}
- }
- wi++;
- } while (wi <= last);
+ wi++;
+ } while (wi <= last);
- if (tagged)
- win.next_tag_id++;
+ if (tagged)
+ win.next_tag_id++;
- marked = -1;
+ marked = -1;
- nl = disp_lines(&win, &toggles, current, count, search_mode,
- &search_data, &term, last_line, tmp_word,
- &langinfo);
+ nl = disp_lines(&win, &toggles, current, count, search_mode,
+ &search_data, &term, last_line, tmp_word,
+ &langinfo);
+ }
}
else
goto special_cmds_when_searching;
@@ -11959,6 +11987,9 @@ main(int argc, char * argv[])
if (!win.col_mode && !win.line_mode)
break;
+ if (!toggles.taggable && !toggles.pinable)
+ break;
+
if (marked == -1)
goto mark_word;
@@ -12019,7 +12050,7 @@ main(int argc, char * argv[])
/* Is words have been matched by a recent search, tag them. */
/* """""""""""""""""""""""""""""""""""""""""""""""""""""""" */
- if (matches_count > 0)
+ if (matches_count > 0 && marked == -1)
{
int tagged = 0;
@@ -12547,7 +12578,8 @@ main(int argc, char * argv[])
goto kins;
}
- if (button == 2 && state == 16)
+ if ((button == 2 && state == 16)
+ && (toggles.taggable || toggles.pinable))
{
if (marked == -1)
marked = current;
diff --git a/smenu.h b/smenu.h
index 4382ba9..d0357ee 100644
--- a/smenu.h
+++ b/smenu.h
@@ -180,6 +180,8 @@ struct toggle_s
| 0 keeps it forgetful. */
int no_mouse; /* 1 to disable the possibly auto-detected *
| mouse, 0 to let smenu auto-detect it. */
+ int tagged_to_mark; /* 1 of tag_to_mark has tagged untagged words *
+ | else 0. */
};
/* Structure to store the default or imposed smenu limits. */
@@ -275,25 +277,25 @@ struct term_s
/* """""""""""""""""""""""""""" */
struct word_s
{
- long start, end; /* start/end absolute horiz. word positions *
- | on the screen. */
- size_t mb; /* number of UTF-8 glyphs to display. */
- long tag_order; /* each time a word is tagged, this value. *
- | is increased. */
- size_t special_level; /* can vary from 0 to 9; 0 meaning normal. */
- char * str; /* display string associated with this word */
- size_t len; /* number of bytes of str (for trimming). */
- char * orig; /* NULL or original string if is had been. *
- | shortened for being displayed or altered *
- | by is expansion. */
- char * bitmap; /* used to store the position of the. *
- | currently searched chars in a word. The *
- | objective is to speed their display. */
- unsigned char is_matching; /* word is matching a search ERE. */
- 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 selectable. */
- unsigned char is_numbered; /* word has a direct access index. */
+ long start, end; /* start/end absolute horiz. word positions *
+ | on the screen. */
+ size_t mb; /* number of UTF-8 glyphs to display. */
+ long tag_order; /* each time a word is tagged, this value. *
+ | is increased. */
+ unsigned short tag_id; /* tag id. 0 means no tag. */
+ size_t special_level; /* can vary from 0 to 9; 0 meaning normal. */
+ char * str; /* display string associated with this word */
+ size_t len; /* number of bytes of str (for trimming). */
+ char * orig; /* NULL or original string if is had been. *
+ | shortened for being displayed or altered *
+ | by is expansion. */
+ char * bitmap; /* used to store the position of the. *
+ | currently searched chars in a word. The *
+ | objective is to speed their display. */
+ unsigned char is_matching; /* word is matching a search ERE. */
+ unsigned char is_last; /* 1 if the word is the last of a line. */
+ unsigned char is_selectable; /* word is selectable. */
+ unsigned char is_numbered; /* word has a direct access index. */
};
/* Structure describing the window in which the user */
@@ -301,23 +303,25 @@ struct word_s
/* """""""""""""""""""""""""""""""""""""""""""""""""" */
struct win_s
{
- long start, end; /* index of the first and last word. */
- long first_column; /* number of the first character displayed. */
- long cur_line; /* relative number of the cursor line (1+). */
- long asked_max_lines; /* requested number of lines in the window. */
- long max_lines; /* effective number of lines in the window. */
- long max_cols; /* max number of words in a single line. */
- long real_max_width; /* max line length. In column, tab or line *
+ long start, end; /* index of the first and last word. */
+ long first_column; /* number of the first character displayed. */
+ long cur_line; /* relative number of the cursor line (1+). */
+ long asked_max_lines; /* requested number of lines in the window. */
+ long max_lines; /* effective number of lines in the window. */
+ long max_cols; /* max number of words in a single line. */
+ long real_max_width; /* max line length. In column, tab or line *
| mode it can be greater than the *
| terminal width. */
- long message_lines; /* number of lines taken by the messages *
+ long message_lines; /* number of lines taken by the messages *
| (updated by disp_message. */
- long max_width; /* max usable line width or the terminal. */
- long offset; /* Left margin, used in centered mode. */
- char * sel_sep; /* output separator when tags are enabled. */
- char ** gutter_a; /* array of UTF-8 gutter glyphs. */
- long gutter_nb; /* number of UTF-8 gutter glyphs. */
- long sb_column; /* scroll bar column (-1) if no scroll bar. */
+ long max_width; /* max usable line width or the terminal. */
+ long offset; /* Left margin, used in centered mode. */
+ char * sel_sep; /* output separator when tags are enabled. */
+ char ** gutter_a; /* array of UTF-8 gutter glyphs. */
+ long gutter_nb; /* number of UTF-8 gutter glyphs. */
+ long sb_column; /* scroll bar column (-1) if no scroll bar. */
+ unsigned next_tag_id; /* Next tag ID, increased on each tagging *
+ | operation. */
unsigned char tab_mode; /* -t */
unsigned char col_mode; /* -c */
@@ -328,24 +332,30 @@ struct win_s
unsigned char has_truncated_lines; /* 1 if win has tr. lines else 0. */
- attrib_t cursor_attr; /* current cursor attributes. */
- attrib_t cursor_on_tag_attr; /* current cursor on tag attributes. */
- attrib_t bar_attr; /* scrollbar attributes. */
- attrib_t shift_attr; /* shift indicator attributes. */
- attrib_t message_attr; /* message (title) attributes. */
- attrib_t search_field_attr; /* search mode field attributes. */
- attrib_t search_text_attr; /* search mode text attributes. */
- attrib_t search_err_field_attr; /* bad search mode field attributes. */
- attrib_t search_err_text_attr; /* bad search mode text attributes. */
- attrib_t match_field_attr; /* matching word field attributes. */
- attrib_t match_text_attr; /* matching word text attributes. */
- attrib_t match_err_field_attr; /* bad matching word field attributes. */
- attrib_t match_err_text_attr; /* bad matching word text attributes. */
- attrib_t include_attr; /* selectable words attributes. */
- attrib_t exclude_attr; /* non-selectable words attributes. */
- attrib_t tag_attr; /* non-selectable words attributes. */
- attrib_t daccess_attr; /* direct access tag attributes. */
- attrib_t special_attr[9]; /* special (-1,...) words attributes. */
+ attrib_t cursor_attr; /* current cursor attributes. */
+ attrib_t cursor_marked_attr; /* current cursor when a mark is set. */
+ attrib_t cursor_on_marked_attr; /* current cursor on marked word *
+ | attributes. */
+ attrib_t cursor_on_tag_attr; /* current cursor on tag attributes. */
+ attrib_t cursor_on_tag_marked_attr; /* current cursor on tag attributes *
+ | if current word is marked. */
+ attrib_t marked_attr; /* marked word. */
+ attrib_t bar_attr; /* scrollbar attributes. */
+ attrib_t shift_attr; /* shift indicator attributes. */
+ attrib_t message_attr; /* message (title) attributes. */
+ attrib_t search_field_attr; /* search mode field attributes. */
+ attrib_t search_text_attr; /* search mode text attributes. */
+ attrib_t search_err_field_attr; /* bad search mode field attributes. */
+ attrib_t search_err_text_attr; /* bad search mode text attributes. */
+ attrib_t match_field_attr; /* matching word field attributes. */
+ attrib_t match_text_attr; /* matching word text attributes. */
+ attrib_t match_err_field_attr; /* bad matching word field attributes. */
+ attrib_t match_err_text_attr; /* bad matching word text attributes. */
+ attrib_t include_attr; /* selectable words attributes. */
+ attrib_t exclude_attr; /* non-selectable words attributes. */
+ attrib_t tag_attr; /* non-selectable words attributes. */
+ attrib_t daccess_attr; /* direct access tag attributes. */
+ attrib_t special_attr[9]; /* special (-1,...) words attributes. */
};
/* Sed like node structure. */
@@ -547,7 +557,7 @@ disp_matching_word(long pos, win_t * win, term_t * term, int is_cursor,
void
disp_word(long pos, search_mode_t search_mode, search_data_t * search_data,
- term_t * term, win_t * win, char * tmp_word);
+ term_t * term, win_t * win, toggle_t * toggles, char * tmp_word);
size_t
expand(char * src, char * dest, langinfo_t * langinfo, toggle_t * toggles,