summaryrefslogtreecommitdiff
path: root/src/ui.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-06-14 23:41:55 +0200
committerBram Moolenaar <Bram@vim.org>2019-06-14 23:41:55 +0200
commitbd75b5333d10e63f7a667d4b65e80d309435629e (patch)
tree0eb77d04d98823e3b5e17a2f0ab3320ab750d73b /src/ui.c
parent2fc39aeeb5ff5101530a89838049e09e2959ad0e (diff)
downloadvim-git-bd75b5333d10e63f7a667d4b65e80d309435629e.tar.gz
patch 8.1.1534: modeless selection in popup window selects too muchv8.1.1534
Problem: Modeless selection in popup window selects too much. Solution: Restrict the selection to insde of the popup window.
Diffstat (limited to 'src/ui.c')
-rw-r--r--src/ui.c158
1 files changed, 123 insertions, 35 deletions
diff --git a/src/ui.c b/src/ui.c
index 2748da403..9e387b4ce 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -988,13 +988,13 @@ clip_isautosel_plus(void)
* Stuff for general mouse selection, without using Visual mode.
*/
-static void clip_invert_area(int, int, int, int, int how);
-static void clip_invert_rectangle(int row, int col, int height, int width, int invert);
+static void clip_invert_area(Clipboard_T *, int, int, int, int, int how);
+static void clip_invert_rectangle(Clipboard_T *, int row, int col, int height, int width, int invert);
static void clip_get_word_boundaries(Clipboard_T *, int, int);
-static int clip_get_line_end(int);
+static int clip_get_line_end(Clipboard_T *, int);
static void clip_update_modeless_selection(Clipboard_T *, int, int, int, int);
-/* flags for clip_invert_area() */
+// "how" flags for clip_invert_area()
#define CLIP_CLEAR 1
#define CLIP_SET 2
#define CLIP_TOGGLE 3
@@ -1071,6 +1071,33 @@ clip_start_selection(int col, int row, int repeated_click)
cb->end = cb->start;
cb->origin_row = (short_u)cb->start.lnum;
cb->state = SELECT_IN_PROGRESS;
+#ifdef FEAT_TEXT_PROP
+ {
+ win_T *wp;
+ int row_cp = row;
+ int col_cp = col;
+
+ wp = mouse_find_win(&row_cp, &col_cp, FIND_POPUP);
+ if (wp != NULL && bt_popup(wp->w_buffer))
+ {
+ // Click in a popup window restricts selection to that window,
+ // excluding the border.
+ cb->min_col = wp->w_wincol + wp->w_popup_border[3];
+ cb->max_col = wp->w_wincol + popup_width(wp) - 1
+ - wp->w_popup_border[1];
+ cb->min_row = wp->w_winrow + wp->w_popup_border[0];
+ cb->max_row = wp->w_winrow + popup_height(wp) - 1
+ - wp->w_popup_border[2];
+ }
+ else
+ {
+ cb->min_col = 0;
+ cb->max_col = screen_Columns;
+ cb->min_row = 0;
+ cb->max_row = screen_Rows;
+ }
+ }
+#endif
if (repeated_click)
{
@@ -1090,7 +1117,7 @@ clip_start_selection(int col, int row, int repeated_click)
{
case SELECT_MODE_CHAR:
cb->origin_start_col = cb->start.col;
- cb->word_end_col = clip_get_line_end((int)cb->start.lnum);
+ cb->word_end_col = clip_get_line_end(cb, (int)cb->start.lnum);
break;
case SELECT_MODE_WORD:
@@ -1098,14 +1125,14 @@ clip_start_selection(int col, int row, int repeated_click)
cb->origin_start_col = cb->word_start_col;
cb->origin_end_col = cb->word_end_col;
- clip_invert_area((int)cb->start.lnum, cb->word_start_col,
+ clip_invert_area(cb, (int)cb->start.lnum, cb->word_start_col,
(int)cb->end.lnum, cb->word_end_col, CLIP_SET);
cb->start.col = cb->word_start_col;
cb->end.col = cb->word_end_col;
break;
case SELECT_MODE_LINE:
- clip_invert_area((int)cb->start.lnum, 0, (int)cb->start.lnum,
+ clip_invert_area(cb, (int)cb->start.lnum, 0, (int)cb->start.lnum,
(int)Columns, CLIP_SET);
cb->start.col = 0;
cb->end.col = Columns;
@@ -1223,7 +1250,7 @@ clip_process_selection(
case SELECT_MODE_CHAR:
/* If we're on a different line, find where the line ends */
if (row != cb->prev.lnum)
- cb->word_end_col = clip_get_line_end(row);
+ cb->word_end_col = clip_get_line_end(cb, row);
/* See if we are before or after the origin of the selection */
if (clip_compare_pos(row, col, cb->origin_row,
@@ -1316,7 +1343,7 @@ clip_may_redraw_selection(int row, int col, int len)
if (row == clip_star.end.lnum && end > (int)clip_star.end.col)
end = clip_star.end.col;
if (end > start)
- clip_invert_area(row, start, row, end, 0);
+ clip_invert_area(&clip_star, row, start, row, end, 0);
}
}
# endif
@@ -1331,8 +1358,8 @@ clip_clear_selection(Clipboard_T *cbd)
if (cbd->state == SELECT_CLEARED)
return;
- clip_invert_area((int)cbd->start.lnum, cbd->start.col, (int)cbd->end.lnum,
- cbd->end.col, CLIP_CLEAR);
+ clip_invert_area(cbd, (int)cbd->start.lnum, cbd->start.col,
+ (int)cbd->end.lnum, cbd->end.col, CLIP_CLEAR);
cbd->state = SELECT_CLEARED;
}
@@ -1388,13 +1415,21 @@ clip_scroll_selection(
*/
static void
clip_invert_area(
- int row1,
- int col1,
- int row2,
- int col2,
- int how)
+ Clipboard_T *cbd,
+ int row1,
+ int col1,
+ int row2,
+ int col2,
+ int how)
{
int invert = FALSE;
+ int max_col;
+
+#ifdef FEAT_TEXT_PROP
+ max_col = cbd->max_col;
+#else
+ max_col = Columns - 1;
+#endif
if (how == CLIP_SET)
invert = TRUE;
@@ -1417,28 +1452,29 @@ clip_invert_area(
/* If all on the same line, do it the easy way */
if (row1 == row2)
{
- clip_invert_rectangle(row1, col1, 1, col2 - col1, invert);
+ clip_invert_rectangle(cbd, row1, col1, 1, col2 - col1, invert);
}
else
{
/* Handle a piece of the first line */
if (col1 > 0)
{
- clip_invert_rectangle(row1, col1, 1, (int)Columns - col1, invert);
+ clip_invert_rectangle(cbd, row1, col1, 1,
+ (int)Columns - col1, invert);
row1++;
}
/* Handle a piece of the last line */
- if (col2 < Columns - 1)
+ if (col2 < max_col)
{
- clip_invert_rectangle(row2, 0, 1, col2, invert);
+ clip_invert_rectangle(cbd, row2, 0, 1, col2, invert);
row2--;
}
/* Handle the rectangle thats left */
if (row2 >= row1)
- clip_invert_rectangle(row1, 0, row2 - row1 + 1, (int)Columns,
- invert);
+ clip_invert_rectangle(cbd, row1, 0, row2 - row1 + 1,
+ (int)Columns, invert);
}
}
@@ -1448,15 +1484,36 @@ clip_invert_area(
*/
static void
clip_invert_rectangle(
- int row,
- int col,
- int height,
- int width,
- int invert)
-{
+ Clipboard_T *cbd,
+ int row_arg,
+ int col_arg,
+ int height_arg,
+ int width_arg,
+ int invert)
+{
+ int row = row_arg;
+ int col = col_arg;
+ int height = height_arg;
+ int width = width_arg;
+
#ifdef FEAT_TEXT_PROP
// this goes on top of all popup windows
screen_zindex = 32000;
+
+ if (col < cbd->min_col)
+ {
+ width -= cbd->min_col - col;
+ col = cbd->min_col;
+ }
+ if (width > cbd->max_col - col + 1)
+ width = cbd->max_col - col + 1;
+ if (row < cbd->min_row)
+ {
+ height -= cbd->min_row - row;
+ row = cbd->min_row;
+ }
+ if (height > cbd->max_row - row + 1)
+ height = cbd->max_row - row + 1;
#endif
#ifdef FEAT_GUI
if (gui.in_use)
@@ -1507,6 +1564,16 @@ clip_copy_modeless_selection(int both UNUSED)
{
row = col1; col1 = col2; col2 = row;
}
+#ifdef FEAT_TEXT_PROP
+ if (col1 < clip_star.min_col)
+ col1 = clip_star.min_col;
+ if (col2 > clip_star.max_col + 1)
+ col2 = clip_star.max_col + 1;
+ if (row1 < clip_star.min_row)
+ row1 = clip_star.min_row;
+ if (row2 > clip_star.max_row)
+ row2 = clip_star.max_row;
+#endif
/* correct starting point for being on right halve of double-wide char */
p = ScreenLines + LineOffset[row1];
if (enc_dbcs != 0)
@@ -1530,17 +1597,31 @@ clip_copy_modeless_selection(int both UNUSED)
if (row == row1)
start_col = col1;
else
+#ifdef FEAT_TEXT_PROP
+ start_col = clip_star.min_col;
+#else
start_col = 0;
+#endif
if (row == row2)
end_col = col2;
else
+#ifdef FEAT_TEXT_PROP
+ end_col = clip_star.max_col + 1;
+#else
end_col = Columns;
+#endif
- line_end_col = clip_get_line_end(row);
+ line_end_col = clip_get_line_end(&clip_star, row);
/* See if we need to nuke some trailing whitespace */
- if (end_col >= Columns && (row < row2 || end_col > line_end_col))
+ if (end_col >=
+#ifdef FEAT_TEXT_PROP
+ clip_star.max_col + 1
+#else
+ Columns
+#endif
+ && (row < row2 || end_col > line_end_col))
{
/* Get rid of trailing whitespace */
end_col = line_end_col;
@@ -1556,6 +1637,7 @@ clip_copy_modeless_selection(int both UNUSED)
if (row > row1 && !LineWraps[row - 1])
*bufp++ = NL;
+ // Safetey check for in case resizing went wrong
if (row < screen_Rows && end_col <= screen_Columns)
{
if (enc_dbcs != 0)
@@ -1690,16 +1772,22 @@ clip_get_word_boundaries(Clipboard_T *cb, int row, int col)
/*
* Find the column position for the last non-whitespace character on the given
- * line.
+ * line at or before start_col.
*/
static int
-clip_get_line_end(int row)
+clip_get_line_end(Clipboard_T *cbd UNUSED, int row)
{
int i;
if (row >= screen_Rows || ScreenLines == NULL)
return 0;
- for (i = screen_Columns; i > 0; i--)
+ for (i =
+#ifdef FEAT_TEXT_PROP
+ cbd->max_col + 1;
+#else
+ screen_Columns;
+#endif
+ i > 0; i--)
if (ScreenLines[LineOffset[row] + i - 1] != ' ')
break;
return i;
@@ -1720,7 +1808,7 @@ clip_update_modeless_selection(
/* See if we changed at the beginning of the selection */
if (row1 != cb->start.lnum || col1 != (int)cb->start.col)
{
- clip_invert_area(row1, col1, (int)cb->start.lnum, cb->start.col,
+ clip_invert_area(cb, row1, col1, (int)cb->start.lnum, cb->start.col,
CLIP_TOGGLE);
cb->start.lnum = row1;
cb->start.col = col1;
@@ -1729,7 +1817,7 @@ clip_update_modeless_selection(
/* See if we changed at the end of the selection */
if (row2 != cb->end.lnum || col2 != (int)cb->end.col)
{
- clip_invert_area((int)cb->end.lnum, cb->end.col, row2, col2,
+ clip_invert_area(cb, (int)cb->end.lnum, cb->end.col, row2, col2,
CLIP_TOGGLE);
cb->end.lnum = row2;
cb->end.col = col2;