trailcol = (colnr_T)STRLEN(ptr);
while (trailcol > (colnr_T)0 && VIM_ISWHITE(ptr[trailcol - 1]))
--trailcol;
- trailcol += (colnr_T) (ptr - line);
+ trailcol += (colnr_T)(ptr - line);
}
// find end of leading whitespace
if (wp->w_lcs_chars.lead || wp->w_lcs_chars.leadmultispace != NULL)
leadcol = (colnr_T)0;
else
// keep track of the first column not filled with spaces
- leadcol += (colnr_T) (ptr - line) + 1;
+ leadcol += (colnr_T)(ptr - line) + 1;
}
}
// Repeat for the whole displayed line.
for (;;)
{
+ char_u *prev_ptr = ptr;
#if defined(FEAT_CONCEAL) || defined(FEAT_SEARCH_EXTRA)
- int has_match_conc = 0; // match wants to conceal
+ int has_match_conc = 0; // match wants to conceal
#endif
#ifdef FEAT_CONCEAL
- int did_decrement_ptr = FALSE;
+ int did_decrement_ptr = FALSE;
#endif
+
// Skip this quickly when working on the text.
if (draw_state != WL_LINE)
{
&match_conc, did_line_attr, lcs_eol_one,
&on_last_col);
ptr = line + v; // "line" may have been changed
+ prev_ptr = ptr;
// Do not allow a conceal over EOL otherwise EOL will be missed
// and bad things happen.
// have made it invalid.
line = ml_get_buf(wp->w_buffer, lnum, FALSE);
ptr = line + v;
+ prev_ptr = ptr;
# ifdef FEAT_CONCEAL
// no concealing past the end of the line, it interferes
// with line highlighting
else
{
#ifdef FEAT_LINEBREAK
- int c0;
+ int c0;
#endif
VIM_CLEAR(p_extra_free);
+ prev_ptr = ptr;
// Get a character from the line itself.
c = *ptr;
# endif
can_spell))
{
- char_u *prev_ptr, *p;
+ char_u *p;
int len;
hlf_T spell_hlf = HLF_COUNT;
if (has_mbyte)
- {
- prev_ptr = ptr - mb_l;
v -= mb_l - 1;
- }
- else
- prev_ptr = ptr - 1;
// Use nextline[] if possible, it has the start of the
// next line concatenated.
}
#endif
ScreenAttrs[off] = char_attr;
+ ScreenCols[off] = MAXCOL;
#ifdef FEAT_RIGHTLEFT
if (wp->w_p_rl)
{
ScreenLines[off] = ' ';
if (enc_utf8)
ScreenLinesUC[off] = 0;
+ ScreenCols[off] = MAXCOL;
++col;
if (draw_color_col)
draw_color_col = advance_color_col(VCOL_HLC,
else
ScreenAttrs[off] = char_attr;
+ ScreenCols[off] = (colnr_T)(prev_ptr - line);
+
if (has_mbyte && (*mb_char2cells)(mb_c) > 1)
{
// Need to fill two screen columns.
// the character, otherwise highlighting won't stop.
if (tocol == vcol)
++tocol;
+
+ ScreenCols[off] = (colnr_T)(prev_ptr - line);
+
#ifdef FEAT_RIGHTLEFT
if (wp->w_p_rl)
{
int first;
int row = mouse_row;
int col = mouse_col;
+ colnr_T col_from_screen = -1;
#ifdef FEAT_FOLDING
- int mouse_char;
+ int mouse_char = ' ';
#endif
mouse_past_bottom = FALSE;
if (flags & MOUSE_SETPOS)
goto retnomove; // ugly goto...
-#ifdef FEAT_FOLDING
- // Remember the character under the mouse, it might be a '-' or '+' in the
- // fold column.
- if (row >= 0 && row < Rows && col >= 0 && col <= Columns
- && ScreenLines != NULL)
- mouse_char = ScreenLines[LineOffset[row] + col];
- else
- mouse_char = ' ';
-#endif
-
old_curwin = curwin;
old_cursor = curwin->w_cursor;
}
}
+ if (prev_row >= 0 && prev_row < Rows && prev_col >= 0 && prev_col <= Columns
+ && ScreenLines != NULL)
+ {
+ int off = LineOffset[prev_row] + prev_col;
+
+ // Only use ScreenCols[] after the window was redrawn. Mainly matters
+ // for tests, a user would not click before redrawing.
+ if (curwin->w_redr_type <= VALID_NO_UPDATE)
+ col_from_screen = ScreenCols[off];
+#ifdef FEAT_FOLDING
+ // Remember the character under the mouse, it might be a '-' or '+' in
+ // the fold column.
+ mouse_char = ScreenLines[off];
+#endif
+ }
+
#ifdef FEAT_FOLDING
// Check for position outside of the fold column.
if (
redraw_cmdline = TRUE; // show visual mode later
}
- curwin->w_curswant = col;
- curwin->w_set_curswant = FALSE; // May still have been TRUE
- if (coladvance(col) == FAIL) // Mouse click beyond end of line
+ if (col_from_screen >= 0)
+ {
+ // Use the column from ScreenCols[], it is accurate also after
+ // concealed characters.
+ curwin->w_cursor.col = col_from_screen;
+ if (col_from_screen == MAXCOL)
+ {
+ curwin->w_curswant = col_from_screen;
+ curwin->w_set_curswant = FALSE; // May still have been TRUE
+ mouse_past_eol = TRUE;
+ if (inclusive != NULL)
+ *inclusive = TRUE;
+ }
+ else
+ {
+ curwin->w_set_curswant = TRUE;
+ if (inclusive != NULL)
+ *inclusive = FALSE;
+ }
+ check_cursor_col();
+ }
+ else
{
- if (inclusive != NULL)
- *inclusive = TRUE;
- mouse_past_eol = TRUE;
+ curwin->w_curswant = col;
+ curwin->w_set_curswant = FALSE; // May still have been TRUE
+ if (coladvance(col) == FAIL) // Mouse click beyond end of line
+ {
+ if (inclusive != NULL)
+ *inclusive = TRUE;
+ mouse_past_eol = TRUE;
+ }
+ else if (inclusive != NULL)
+ *inclusive = FALSE;
}
- else if (inclusive != NULL)
- *inclusive = FALSE;
count = IN_BUFFER;
if (curwin != old_curwin || curwin->w_cursor.lnum != old_cursor.lnum
* ScreenLines[off] Contains a copy of the whole screen, as it is currently
* displayed (excluding text written by external commands).
* ScreenAttrs[off] Contains the associated attributes.
- * LineOffset[row] Contains the offset into ScreenLines*[] and ScreenAttrs[]
- * for each line.
+ * ScreenCols[off] Contains the byte offset in the line. -1 means not
+ * available (below last line), MAXCOL means after the end
+ * of the line.
+ *
+ * LineOffset[row] Contains the offset into ScreenLines*[], ScreenAttrs[]
+ * and ScreenCols[] for each line.
* LineWraps[row] Flag for each line whether it wraps to the next line.
*
* For double-byte characters, two consecutive bytes in ScreenLines[] can form
int clear_next = FALSE;
int char_cells; // 1: normal char
// 2: occupies two display cells
-# define CHAR_CELLS char_cells
// Check for illegal row and col, just in case.
if (row >= Rows)
char_cells = 1;
redraw_this = redraw_next;
- redraw_next = force || char_needs_redraw(off_from + CHAR_CELLS,
- off_to + CHAR_CELLS, endcol - col - CHAR_CELLS);
+ redraw_next = force || char_needs_redraw(off_from + char_cells,
+ off_to + char_cells, endcol - col - char_cells);
#ifdef FEAT_GUI
// If the next character was bold, then redraw the current character to
// happens in the GUI.
if (redraw_next && gui.in_use)
{
- hl = ScreenAttrs[off_to + CHAR_CELLS];
+ hl = ScreenAttrs[off_to + char_cells];
if (hl > HL_ALL)
hl = syn_attr2attr(hl);
if (hl & HL_BOLD)
}
#endif
ScreenAttrs[off_to] = ScreenAttrs[off_from];
+ ScreenCols[off_to] = ScreenCols[off_from];
// For simplicity set the attributes of second half of a
// double-wide character equal to the first half.
if (char_cells == 2)
+ {
ScreenAttrs[off_to + 1] = ScreenAttrs[off_from];
+ ScreenCols[off_to + 1] = ScreenCols[off_from + 1];
+ }
if (enc_dbcs != 0 && char_cells == 2)
screen_char_2(off_to, row, col + coloff);
screen_stop_highlight();
}
- off_to += CHAR_CELLS;
- off_from += CHAR_CELLS;
- col += CHAR_CELLS;
+ ScreenCols[off_to] = ScreenCols[off_from];
+ if (char_cells == 2)
+ ScreenCols[off_to + 1] = ScreenCols[off_from];
+
+ off_to += char_cells;
+ off_from += char_cells;
+ col += char_cells;
}
if (clear_next)
&& ScreenAttrs[off_to] == 0
&& (!enc_utf8 || ScreenLinesUC[off_to] == 0))
{
+ ScreenCols[off_to] = MAXCOL;
++off_to;
++col;
}
#endif
screen_fill(row, row + 1, col + coloff, clear_width + coloff,
' ', ' ', 0);
- off_to += clear_width - col;
- col = clear_width;
+ while (col < clear_width)
+ {
+ ScreenCols[off_to++] = MAXCOL;
+ ++col;
+ }
}
}
ScreenLines[off + mbyte_blen] = 0;
ScreenLines[off] = c;
ScreenAttrs[off] = attr;
+ ScreenCols[off] = -1;
if (enc_utf8)
{
if (c < 0x80 && u8cc[0] == 0)
{
ScreenLines[off + 1] = 0;
ScreenAttrs[off + 1] = attr;
+ ScreenCols[off + 1] = -1;
}
screen_char(off, row, col);
}
{
ScreenLines[off + 1] = ptr[1];
ScreenAttrs[off + 1] = attr;
+ ScreenCols[off + 1] = -1;
screen_char_2(off, row, col);
}
else if (enc_dbcs == DBCS_JPNU && c == 0x8e)
)
{
ScreenAttrs[off] = (sattr_T)-1;
+ ScreenCols[off] = -1;
return;
}
if (row == screen_Rows - 1 && col >= screen_Columns - 2)
{
ScreenAttrs[off] = (sattr_T)-1;
+ ScreenCols[off] = -1;
return;
}
{
ScreenLines[off] = ' ';
ScreenAttrs[off] = attr;
+ ScreenCols[off] = -1;
if (enc_utf8)
ScreenLinesUC[off] = 0;
}
if (!did_delete || c != ' ')
screen_char(off, row, col);
}
+ ScreenCols[off] = -1;
++off;
if (col == start_col)
{
schar_T *new_ScreenLines2 = NULL;
int i;
sattr_T *new_ScreenAttrs;
+ colnr_T *new_ScreenCols;
unsigned *new_LineOffset;
char_u *new_LineWraps;
short *new_TabPageIdxs;
if (enc_dbcs == DBCS_JPNU)
new_ScreenLines2 = LALLOC_MULT(schar_T, (Rows + 1) * Columns);
new_ScreenAttrs = LALLOC_MULT(sattr_T, (Rows + 1) * Columns);
+ new_ScreenCols = LALLOC_MULT(colnr_T, (Rows + 1) * Columns);
new_LineOffset = LALLOC_MULT(unsigned, Rows);
new_LineWraps = LALLOC_MULT(char_u, Rows);
new_TabPageIdxs = LALLOC_MULT(short, Columns);
|| (enc_utf8 && (new_ScreenLinesUC == NULL || i != p_mco))
|| (enc_dbcs == DBCS_JPNU && new_ScreenLines2 == NULL)
|| new_ScreenAttrs == NULL
+ || new_ScreenCols == NULL
|| new_LineOffset == NULL
|| new_LineWraps == NULL
|| new_TabPageIdxs == NULL
VIM_CLEAR(new_ScreenLinesC[i]);
VIM_CLEAR(new_ScreenLines2);
VIM_CLEAR(new_ScreenAttrs);
+ VIM_CLEAR(new_ScreenCols);
VIM_CLEAR(new_LineOffset);
VIM_CLEAR(new_LineWraps);
VIM_CLEAR(new_TabPageIdxs);
0, (size_t)Columns * sizeof(schar_T));
(void)vim_memset(new_ScreenAttrs + new_row * Columns,
0, (size_t)Columns * sizeof(sattr_T));
+ (void)vim_memset(new_ScreenCols + new_row * Columns,
+ 0, (size_t)Columns * sizeof(colnr_T));
old_row = new_row + (screen_Rows - Rows);
if (old_row >= 0 && ScreenLines != NULL)
{
mch_memmove(new_ScreenAttrs + new_LineOffset[new_row],
ScreenAttrs + LineOffset[old_row],
(size_t)len * sizeof(sattr_T));
+ mch_memmove(new_ScreenCols + new_LineOffset[new_row],
+ ScreenAttrs + LineOffset[old_row],
+ (size_t)len * sizeof(colnr_T));
}
}
}
Screen_mco = p_mco;
ScreenLines2 = new_ScreenLines2;
ScreenAttrs = new_ScreenAttrs;
+ ScreenCols = new_ScreenCols;
LineOffset = new_LineOffset;
LineWraps = new_LineWraps;
TabPageIdxs = new_TabPageIdxs;
VIM_CLEAR(ScreenLines2);
VIM_CLEAR(ScreenLines);
VIM_CLEAR(ScreenAttrs);
+ VIM_CLEAR(ScreenCols);
VIM_CLEAR(LineOffset);
VIM_CLEAR(LineWraps);
VIM_CLEAR(TabPageIdxs);
(void)vim_memset(ScreenLinesUC + off, 0,
(size_t)width * sizeof(u8char_T));
(void)vim_memset(ScreenAttrs + off, attr, (size_t)width * sizeof(sattr_T));
+ (void)vim_memset(ScreenCols + off, -1, (size_t)width * sizeof(colnr_T));
}
/*
lineinvalid(unsigned off, int width)
{
(void)vim_memset(ScreenAttrs + off, -1, (size_t)width * sizeof(sattr_T));
+ (void)vim_memset(ScreenCols + off, -1, (size_t)width * sizeof(colnr_T));
}
/*
wp->w_width * sizeof(schar_T));
mch_memmove(ScreenAttrs + off_to, ScreenAttrs + off_from,
wp->w_width * sizeof(sattr_T));
+ mch_memmove(ScreenCols + off_to, ScreenCols + off_from,
+ wp->w_width * sizeof(colnr_T));
}
/*