Mercurial > vim
comparison src/drawline.c @ 18124:2a806e3c39f6 v8.1.2057
patch 8.1.2057: the screen.c file is much too big
Commit: https://github.com/vim/vim/commit/7528d1f6b5422750eb778dfb550cfd0b0e540964
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Sep 19 23:06:20 2019 +0200
patch 8.1.2057: the screen.c file is much too big
Problem: The screen.c file is much too big.
Solution: Split it in three parts. (Yegappan Lakshmanan, closes https://github.com/vim/vim/issues/4943)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Thu, 19 Sep 2019 23:15:05 +0200 |
parents | |
children | 851a014dfd8b |
comparison
equal
deleted
inserted
replaced
18123:ceb4be0b23c7 | 18124:2a806e3c39f6 |
---|---|
1 /* vi:set ts=8 sts=4 sw=4 noet: | |
2 * | |
3 * VIM - Vi IMproved by Bram Moolenaar | |
4 * | |
5 * Do ":help uganda" in Vim to read copying and usage conditions. | |
6 * Do ":help credits" in Vim to see a list of people who contributed. | |
7 * See README.txt for an overview of the Vim source code. | |
8 */ | |
9 | |
10 /* | |
11 * drawline.c: Functions for drawing window lines on the screen. | |
12 * This is the middle level, drawscreen. is the higher level and screen.c the | |
13 * lower level. | |
14 */ | |
15 | |
16 #include "vim.h" | |
17 | |
18 #ifdef FEAT_SYN_HL | |
19 /* | |
20 * Advance **color_cols and return TRUE when there are columns to draw. | |
21 */ | |
22 static int | |
23 advance_color_col(int vcol, int **color_cols) | |
24 { | |
25 while (**color_cols >= 0 && vcol > **color_cols) | |
26 ++*color_cols; | |
27 return (**color_cols >= 0); | |
28 } | |
29 #endif | |
30 | |
31 #ifdef FEAT_SYN_HL | |
32 /* | |
33 * Used when 'cursorlineopt' contains "screenline": compute the margins between | |
34 * which the highlighting is used. | |
35 */ | |
36 static void | |
37 margin_columns_win(win_T *wp, int *left_col, int *right_col) | |
38 { | |
39 // cache previous calculations depending on w_virtcol | |
40 static int saved_w_virtcol; | |
41 static win_T *prev_wp; | |
42 static int prev_left_col; | |
43 static int prev_right_col; | |
44 static int prev_col_off; | |
45 | |
46 int cur_col_off = win_col_off(wp); | |
47 int width1; | |
48 int width2; | |
49 | |
50 if (saved_w_virtcol == wp->w_virtcol | |
51 && prev_wp == wp && prev_col_off == cur_col_off) | |
52 { | |
53 *right_col = prev_right_col; | |
54 *left_col = prev_left_col; | |
55 return; | |
56 } | |
57 | |
58 width1 = wp->w_width - cur_col_off; | |
59 width2 = width1 + win_col_off2(wp); | |
60 | |
61 *left_col = 0; | |
62 *right_col = width1; | |
63 | |
64 if (wp->w_virtcol >= (colnr_T)width1) | |
65 *right_col = width1 + ((wp->w_virtcol - width1) / width2 + 1) * width2; | |
66 if (wp->w_virtcol >= (colnr_T)width1 && width2 > 0) | |
67 *left_col = (wp->w_virtcol - width1) / width2 * width2 + width1; | |
68 | |
69 // cache values | |
70 prev_left_col = *left_col; | |
71 prev_right_col = *right_col; | |
72 prev_wp = wp; | |
73 saved_w_virtcol = wp->w_virtcol; | |
74 prev_col_off = cur_col_off; | |
75 } | |
76 #endif | |
77 | |
78 #ifdef FEAT_SIGNS | |
79 /* | |
80 * Get information needed to display the sign in line 'lnum' in window 'wp'. | |
81 * If 'nrcol' is TRUE, the sign is going to be displayed in the number column. | |
82 * Otherwise the sign is going to be displayed in the sign column. | |
83 */ | |
84 static void | |
85 get_sign_display_info( | |
86 int nrcol, | |
87 win_T *wp, | |
88 linenr_T lnum UNUSED, | |
89 sign_attrs_T *sattr, | |
90 int wcr_attr, | |
91 int row, | |
92 int startrow, | |
93 int filler_lines UNUSED, | |
94 int filler_todo UNUSED, | |
95 int *c_extrap, | |
96 int *c_finalp, | |
97 char_u *extra, | |
98 char_u **pp_extra, | |
99 int *n_extrap, | |
100 int *char_attrp) | |
101 { | |
102 int text_sign; | |
103 # ifdef FEAT_SIGN_ICONS | |
104 int icon_sign; | |
105 # endif | |
106 | |
107 // Draw two cells with the sign value or blank. | |
108 *c_extrap = ' '; | |
109 *c_finalp = NUL; | |
110 if (nrcol) | |
111 *n_extrap = number_width(wp) + 1; | |
112 else | |
113 { | |
114 *char_attrp = hl_combine_attr(wcr_attr, HL_ATTR(HLF_SC)); | |
115 *n_extrap = 2; | |
116 } | |
117 | |
118 if (row == startrow | |
119 #ifdef FEAT_DIFF | |
120 + filler_lines && filler_todo <= 0 | |
121 #endif | |
122 ) | |
123 { | |
124 text_sign = (sattr->text != NULL) ? sattr->typenr : 0; | |
125 # ifdef FEAT_SIGN_ICONS | |
126 icon_sign = (sattr->icon != NULL) ? sattr->typenr : 0; | |
127 if (gui.in_use && icon_sign != 0) | |
128 { | |
129 // Use the image in this position. | |
130 if (nrcol) | |
131 { | |
132 *c_extrap = NUL; | |
133 sprintf((char *)extra, "%-*c ", number_width(wp), SIGN_BYTE); | |
134 *pp_extra = extra; | |
135 *n_extrap = (int)STRLEN(*pp_extra); | |
136 } | |
137 else | |
138 *c_extrap = SIGN_BYTE; | |
139 # ifdef FEAT_NETBEANS_INTG | |
140 if (netbeans_active() && (buf_signcount(wp->w_buffer, lnum) > 1)) | |
141 { | |
142 if (nrcol) | |
143 { | |
144 *c_extrap = NUL; | |
145 sprintf((char *)extra, "%-*c ", number_width(wp), | |
146 MULTISIGN_BYTE); | |
147 *pp_extra = extra; | |
148 *n_extrap = (int)STRLEN(*pp_extra); | |
149 } | |
150 else | |
151 *c_extrap = MULTISIGN_BYTE; | |
152 } | |
153 # endif | |
154 *c_finalp = NUL; | |
155 *char_attrp = icon_sign; | |
156 } | |
157 else | |
158 # endif | |
159 if (text_sign != 0) | |
160 { | |
161 *pp_extra = sattr->text; | |
162 if (*pp_extra != NULL) | |
163 { | |
164 if (nrcol) | |
165 { | |
166 int n, width = number_width(wp) - 2; | |
167 | |
168 for (n = 0; n < width; n++) | |
169 extra[n] = ' '; | |
170 extra[n] = 0; | |
171 STRCAT(extra, *pp_extra); | |
172 STRCAT(extra, " "); | |
173 *pp_extra = extra; | |
174 } | |
175 *c_extrap = NUL; | |
176 *c_finalp = NUL; | |
177 *n_extrap = (int)STRLEN(*pp_extra); | |
178 } | |
179 *char_attrp = sattr->texthl; | |
180 } | |
181 } | |
182 } | |
183 #endif | |
184 | |
185 #ifdef FEAT_TEXT_PROP | |
186 static textprop_T *current_text_props = NULL; | |
187 static buf_T *current_buf = NULL; | |
188 | |
189 static int | |
190 text_prop_compare(const void *s1, const void *s2) | |
191 { | |
192 int idx1, idx2; | |
193 proptype_T *pt1, *pt2; | |
194 colnr_T col1, col2; | |
195 | |
196 idx1 = *(int *)s1; | |
197 idx2 = *(int *)s2; | |
198 pt1 = text_prop_type_by_id(current_buf, current_text_props[idx1].tp_type); | |
199 pt2 = text_prop_type_by_id(current_buf, current_text_props[idx2].tp_type); | |
200 if (pt1 == pt2) | |
201 return 0; | |
202 if (pt1 == NULL) | |
203 return -1; | |
204 if (pt2 == NULL) | |
205 return 1; | |
206 if (pt1->pt_priority != pt2->pt_priority) | |
207 return pt1->pt_priority > pt2->pt_priority ? 1 : -1; | |
208 col1 = current_text_props[idx1].tp_col; | |
209 col2 = current_text_props[idx2].tp_col; | |
210 return col1 == col2 ? 0 : col1 > col2 ? 1 : -1; | |
211 } | |
212 #endif | |
213 | |
214 /* | |
215 * Display line "lnum" of window 'wp' on the screen. | |
216 * Start at row "startrow", stop when "endrow" is reached. | |
217 * wp->w_virtcol needs to be valid. | |
218 * | |
219 * Return the number of last row the line occupies. | |
220 */ | |
221 int | |
222 win_line( | |
223 win_T *wp, | |
224 linenr_T lnum, | |
225 int startrow, | |
226 int endrow, | |
227 int nochange UNUSED, // not updating for changed text | |
228 int number_only) // only update the number column | |
229 { | |
230 int col = 0; // visual column on screen | |
231 unsigned off; // offset in ScreenLines/ScreenAttrs | |
232 int c = 0; // init for GCC | |
233 long vcol = 0; // virtual column (for tabs) | |
234 #ifdef FEAT_LINEBREAK | |
235 long vcol_sbr = -1; // virtual column after showbreak | |
236 #endif | |
237 long vcol_prev = -1; // "vcol" of previous character | |
238 char_u *line; // current line | |
239 char_u *ptr; // current position in "line" | |
240 int row; // row in the window, excl w_winrow | |
241 int screen_row; // row on the screen, incl w_winrow | |
242 | |
243 char_u extra[21]; // "%ld " and 'fdc' must fit in here | |
244 int n_extra = 0; // number of extra chars | |
245 char_u *p_extra = NULL; // string of extra chars, plus NUL | |
246 char_u *p_extra_free = NULL; // p_extra needs to be freed | |
247 int c_extra = NUL; // extra chars, all the same | |
248 int c_final = NUL; // final char, mandatory if set | |
249 int extra_attr = 0; // attributes when n_extra != 0 | |
250 static char_u *at_end_str = (char_u *)""; // used for p_extra when | |
251 // displaying lcs_eol at end-of-line | |
252 int lcs_eol_one = lcs_eol; // lcs_eol until it's been used | |
253 int lcs_prec_todo = lcs_prec; // lcs_prec until it's been used | |
254 | |
255 // saved "extra" items for when draw_state becomes WL_LINE (again) | |
256 int saved_n_extra = 0; | |
257 char_u *saved_p_extra = NULL; | |
258 int saved_c_extra = 0; | |
259 int saved_c_final = 0; | |
260 int saved_char_attr = 0; | |
261 | |
262 int n_attr = 0; // chars with special attr | |
263 int saved_attr2 = 0; // char_attr saved for n_attr | |
264 int n_attr3 = 0; // chars with overruling special attr | |
265 int saved_attr3 = 0; // char_attr saved for n_attr3 | |
266 | |
267 int n_skip = 0; // nr of chars to skip for 'nowrap' | |
268 | |
269 int fromcol = -10; // start of inverting | |
270 int tocol = MAXCOL; // end of inverting | |
271 int fromcol_prev = -2; // start of inverting after cursor | |
272 int noinvcur = FALSE; // don't invert the cursor | |
273 pos_T *top, *bot; | |
274 int lnum_in_visual_area = FALSE; | |
275 pos_T pos; | |
276 long v; | |
277 | |
278 int char_attr = 0; // attributes for next character | |
279 int attr_pri = FALSE; // char_attr has priority | |
280 int area_highlighting = FALSE; // Visual or incsearch highlighting | |
281 // in this line | |
282 int vi_attr = 0; // attributes for Visual and incsearch | |
283 // highlighting | |
284 int wcr_attr = 0; // attributes from 'wincolor' | |
285 int win_attr = 0; // background for whole window, except | |
286 // margins and "~" lines. | |
287 int area_attr = 0; // attributes desired by highlighting | |
288 int search_attr = 0; // attributes desired by 'hlsearch' | |
289 #ifdef FEAT_SYN_HL | |
290 int vcol_save_attr = 0; // saved attr for 'cursorcolumn' | |
291 int syntax_attr = 0; // attributes desired by syntax | |
292 int has_syntax = FALSE; // this buffer has syntax highl. | |
293 int save_did_emsg; | |
294 int draw_color_col = FALSE; // highlight colorcolumn | |
295 int *color_cols = NULL; // pointer to according columns array | |
296 #endif | |
297 int eol_hl_off = 0; // 1 if highlighted char after EOL | |
298 #ifdef FEAT_TEXT_PROP | |
299 int text_prop_count; | |
300 int text_prop_next = 0; // next text property to use | |
301 textprop_T *text_props = NULL; | |
302 int *text_prop_idxs = NULL; | |
303 int text_props_active = 0; | |
304 proptype_T *text_prop_type = NULL; | |
305 int text_prop_attr = 0; | |
306 int text_prop_combine = FALSE; | |
307 #endif | |
308 #ifdef FEAT_SPELL | |
309 int has_spell = FALSE; // this buffer has spell checking | |
310 # define SPWORDLEN 150 | |
311 char_u nextline[SPWORDLEN * 2];// text with start of the next line | |
312 int nextlinecol = 0; // column where nextline[] starts | |
313 int nextline_idx = 0; // index in nextline[] where next line | |
314 // starts | |
315 int spell_attr = 0; // attributes desired by spelling | |
316 int word_end = 0; // last byte with same spell_attr | |
317 static linenr_T checked_lnum = 0; // line number for "checked_col" | |
318 static int checked_col = 0; // column in "checked_lnum" up to which | |
319 // there are no spell errors | |
320 static int cap_col = -1; // column to check for Cap word | |
321 static linenr_T capcol_lnum = 0; // line number where "cap_col" used | |
322 int cur_checked_col = 0; // checked column for current line | |
323 #endif | |
324 int extra_check = 0; // has extra highlighting | |
325 int multi_attr = 0; // attributes desired by multibyte | |
326 int mb_l = 1; // multi-byte byte length | |
327 int mb_c = 0; // decoded multi-byte character | |
328 int mb_utf8 = FALSE; // screen char is UTF-8 char | |
329 int u8cc[MAX_MCO]; // composing UTF-8 chars | |
330 #if defined(FEAT_DIFF) || defined(FEAT_SIGNS) | |
331 int filler_lines = 0; // nr of filler lines to be drawn | |
332 int filler_todo = 0; // nr of filler lines still to do + 1 | |
333 #endif | |
334 #ifdef FEAT_DIFF | |
335 hlf_T diff_hlf = (hlf_T)0; // type of diff highlighting | |
336 int change_start = MAXCOL; // first col of changed area | |
337 int change_end = -1; // last col of changed area | |
338 #endif | |
339 colnr_T trailcol = MAXCOL; // start of trailing spaces | |
340 #ifdef FEAT_LINEBREAK | |
341 int need_showbreak = FALSE; // overlong line, skipping first x | |
342 // chars | |
343 #endif | |
344 #if defined(FEAT_SIGNS) || defined(FEAT_QUICKFIX) \ | |
345 || defined(FEAT_SYN_HL) || defined(FEAT_DIFF) | |
346 # define LINE_ATTR | |
347 int line_attr = 0; // attribute for the whole line | |
348 int line_attr_save; | |
349 #endif | |
350 #ifdef FEAT_SIGNS | |
351 int sign_present = FALSE; | |
352 sign_attrs_T sattr; | |
353 #endif | |
354 #ifdef FEAT_ARABIC | |
355 int prev_c = 0; // previous Arabic character | |
356 int prev_c1 = 0; // first composing char for prev_c | |
357 #endif | |
358 #if defined(LINE_ATTR) | |
359 int did_line_attr = 0; | |
360 #endif | |
361 #ifdef FEAT_TERMINAL | |
362 int get_term_attr = FALSE; | |
363 #endif | |
364 #ifdef FEAT_SYN_HL | |
365 int cul_attr = 0; // set when 'cursorline' active | |
366 | |
367 // 'cursorlineopt' has "screenline" and cursor is in this line | |
368 int cul_screenline = FALSE; | |
369 | |
370 // margin columns for the screen line, needed for when 'cursorlineopt' | |
371 // contains "screenline" | |
372 int left_curline_col = 0; | |
373 int right_curline_col = 0; | |
374 #endif | |
375 | |
376 // draw_state: items that are drawn in sequence: | |
377 #define WL_START 0 // nothing done yet | |
378 #ifdef FEAT_CMDWIN | |
379 # define WL_CMDLINE WL_START + 1 // cmdline window column | |
380 #else | |
381 # define WL_CMDLINE WL_START | |
382 #endif | |
383 #ifdef FEAT_FOLDING | |
384 # define WL_FOLD WL_CMDLINE + 1 // 'foldcolumn' | |
385 #else | |
386 # define WL_FOLD WL_CMDLINE | |
387 #endif | |
388 #ifdef FEAT_SIGNS | |
389 # define WL_SIGN WL_FOLD + 1 // column for signs | |
390 #else | |
391 # define WL_SIGN WL_FOLD // column for signs | |
392 #endif | |
393 #define WL_NR WL_SIGN + 1 // line number | |
394 #ifdef FEAT_LINEBREAK | |
395 # define WL_BRI WL_NR + 1 // 'breakindent' | |
396 #else | |
397 # define WL_BRI WL_NR | |
398 #endif | |
399 #if defined(FEAT_LINEBREAK) || defined(FEAT_DIFF) | |
400 # define WL_SBR WL_BRI + 1 // 'showbreak' or 'diff' | |
401 #else | |
402 # define WL_SBR WL_BRI | |
403 #endif | |
404 #define WL_LINE WL_SBR + 1 // text in the line | |
405 int draw_state = WL_START; // what to draw next | |
406 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) | |
407 int feedback_col = 0; | |
408 int feedback_old_attr = -1; | |
409 #endif | |
410 int screen_line_flags = 0; | |
411 | |
412 #if defined(FEAT_CONCEAL) || defined(FEAT_SEARCH_EXTRA) | |
413 int match_conc = 0; // cchar for match functions | |
414 #endif | |
415 #ifdef FEAT_CONCEAL | |
416 int syntax_flags = 0; | |
417 int syntax_seqnr = 0; | |
418 int prev_syntax_id = 0; | |
419 int conceal_attr = HL_ATTR(HLF_CONCEAL); | |
420 int is_concealing = FALSE; | |
421 int boguscols = 0; // nonexistent columns added to force | |
422 // wrapping | |
423 int vcol_off = 0; // offset for concealed characters | |
424 int did_wcol = FALSE; | |
425 int old_boguscols = 0; | |
426 # define VCOL_HLC (vcol - vcol_off) | |
427 # define FIX_FOR_BOGUSCOLS \ | |
428 { \ | |
429 n_extra += vcol_off; \ | |
430 vcol -= vcol_off; \ | |
431 vcol_off = 0; \ | |
432 col -= boguscols; \ | |
433 old_boguscols = boguscols; \ | |
434 boguscols = 0; \ | |
435 } | |
436 #else | |
437 # define VCOL_HLC (vcol) | |
438 #endif | |
439 | |
440 if (startrow > endrow) // past the end already! | |
441 return startrow; | |
442 | |
443 row = startrow; | |
444 screen_row = row + W_WINROW(wp); | |
445 | |
446 if (!number_only) | |
447 { | |
448 // To speed up the loop below, set extra_check when there is linebreak, | |
449 // trailing white space and/or syntax processing to be done. | |
450 #ifdef FEAT_LINEBREAK | |
451 extra_check = wp->w_p_lbr; | |
452 #endif | |
453 #ifdef FEAT_SYN_HL | |
454 if (syntax_present(wp) && !wp->w_s->b_syn_error | |
455 # ifdef SYN_TIME_LIMIT | |
456 && !wp->w_s->b_syn_slow | |
457 # endif | |
458 ) | |
459 { | |
460 // Prepare for syntax highlighting in this line. When there is an | |
461 // error, stop syntax highlighting. | |
462 save_did_emsg = did_emsg; | |
463 did_emsg = FALSE; | |
464 syntax_start(wp, lnum); | |
465 if (did_emsg) | |
466 wp->w_s->b_syn_error = TRUE; | |
467 else | |
468 { | |
469 did_emsg = save_did_emsg; | |
470 #ifdef SYN_TIME_LIMIT | |
471 if (!wp->w_s->b_syn_slow) | |
472 #endif | |
473 { | |
474 has_syntax = TRUE; | |
475 extra_check = TRUE; | |
476 } | |
477 } | |
478 } | |
479 | |
480 // Check for columns to display for 'colorcolumn'. | |
481 color_cols = wp->w_p_cc_cols; | |
482 if (color_cols != NULL) | |
483 draw_color_col = advance_color_col(VCOL_HLC, &color_cols); | |
484 #endif | |
485 | |
486 #ifdef FEAT_TERMINAL | |
487 if (term_show_buffer(wp->w_buffer)) | |
488 { | |
489 extra_check = TRUE; | |
490 get_term_attr = TRUE; | |
491 win_attr = term_get_attr(wp->w_buffer, lnum, -1); | |
492 } | |
493 #endif | |
494 | |
495 #ifdef FEAT_SPELL | |
496 if (wp->w_p_spell | |
497 && *wp->w_s->b_p_spl != NUL | |
498 && wp->w_s->b_langp.ga_len > 0 | |
499 && *(char **)(wp->w_s->b_langp.ga_data) != NULL) | |
500 { | |
501 // Prepare for spell checking. | |
502 has_spell = TRUE; | |
503 extra_check = TRUE; | |
504 | |
505 // Get the start of the next line, so that words that wrap to the | |
506 // next line are found too: "et<line-break>al.". | |
507 // Trick: skip a few chars for C/shell/Vim comments | |
508 nextline[SPWORDLEN] = NUL; | |
509 if (lnum < wp->w_buffer->b_ml.ml_line_count) | |
510 { | |
511 line = ml_get_buf(wp->w_buffer, lnum + 1, FALSE); | |
512 spell_cat_line(nextline + SPWORDLEN, line, SPWORDLEN); | |
513 } | |
514 | |
515 // When a word wrapped from the previous line the start of the | |
516 // current line is valid. | |
517 if (lnum == checked_lnum) | |
518 cur_checked_col = checked_col; | |
519 checked_lnum = 0; | |
520 | |
521 // When there was a sentence end in the previous line may require a | |
522 // word starting with capital in this line. In line 1 always check | |
523 // the first word. | |
524 if (lnum != capcol_lnum) | |
525 cap_col = -1; | |
526 if (lnum == 1) | |
527 cap_col = 0; | |
528 capcol_lnum = 0; | |
529 } | |
530 #endif | |
531 | |
532 // handle Visual active in this window | |
533 if (VIsual_active && wp->w_buffer == curwin->w_buffer) | |
534 { | |
535 if (LTOREQ_POS(curwin->w_cursor, VIsual)) | |
536 { | |
537 // Visual is after curwin->w_cursor | |
538 top = &curwin->w_cursor; | |
539 bot = &VIsual; | |
540 } | |
541 else | |
542 { | |
543 // Visual is before curwin->w_cursor | |
544 top = &VIsual; | |
545 bot = &curwin->w_cursor; | |
546 } | |
547 lnum_in_visual_area = (lnum >= top->lnum && lnum <= bot->lnum); | |
548 if (VIsual_mode == Ctrl_V) | |
549 { | |
550 // block mode | |
551 if (lnum_in_visual_area) | |
552 { | |
553 fromcol = wp->w_old_cursor_fcol; | |
554 tocol = wp->w_old_cursor_lcol; | |
555 } | |
556 } | |
557 else | |
558 { | |
559 // non-block mode | |
560 if (lnum > top->lnum && lnum <= bot->lnum) | |
561 fromcol = 0; | |
562 else if (lnum == top->lnum) | |
563 { | |
564 if (VIsual_mode == 'V') // linewise | |
565 fromcol = 0; | |
566 else | |
567 { | |
568 getvvcol(wp, top, (colnr_T *)&fromcol, NULL, NULL); | |
569 if (gchar_pos(top) == NUL) | |
570 tocol = fromcol + 1; | |
571 } | |
572 } | |
573 if (VIsual_mode != 'V' && lnum == bot->lnum) | |
574 { | |
575 if (*p_sel == 'e' && bot->col == 0 && bot->coladd == 0) | |
576 { | |
577 fromcol = -10; | |
578 tocol = MAXCOL; | |
579 } | |
580 else if (bot->col == MAXCOL) | |
581 tocol = MAXCOL; | |
582 else | |
583 { | |
584 pos = *bot; | |
585 if (*p_sel == 'e') | |
586 getvvcol(wp, &pos, (colnr_T *)&tocol, NULL, NULL); | |
587 else | |
588 { | |
589 getvvcol(wp, &pos, NULL, NULL, (colnr_T *)&tocol); | |
590 ++tocol; | |
591 } | |
592 } | |
593 } | |
594 } | |
595 | |
596 // Check if the character under the cursor should not be inverted | |
597 if (!highlight_match && lnum == curwin->w_cursor.lnum && wp == curwin | |
598 #ifdef FEAT_GUI | |
599 && !gui.in_use | |
600 #endif | |
601 ) | |
602 noinvcur = TRUE; | |
603 | |
604 // if inverting in this line set area_highlighting | |
605 if (fromcol >= 0) | |
606 { | |
607 area_highlighting = TRUE; | |
608 vi_attr = HL_ATTR(HLF_V); | |
609 #if defined(FEAT_CLIPBOARD) && defined(FEAT_X11) | |
610 if ((clip_star.available && !clip_star.owned | |
611 && clip_isautosel_star()) | |
612 || (clip_plus.available && !clip_plus.owned | |
613 && clip_isautosel_plus())) | |
614 vi_attr = HL_ATTR(HLF_VNC); | |
615 #endif | |
616 } | |
617 } | |
618 | |
619 // handle 'incsearch' and ":s///c" highlighting | |
620 else if (highlight_match | |
621 && wp == curwin | |
622 && lnum >= curwin->w_cursor.lnum | |
623 && lnum <= curwin->w_cursor.lnum + search_match_lines) | |
624 { | |
625 if (lnum == curwin->w_cursor.lnum) | |
626 getvcol(curwin, &(curwin->w_cursor), | |
627 (colnr_T *)&fromcol, NULL, NULL); | |
628 else | |
629 fromcol = 0; | |
630 if (lnum == curwin->w_cursor.lnum + search_match_lines) | |
631 { | |
632 pos.lnum = lnum; | |
633 pos.col = search_match_endcol; | |
634 getvcol(curwin, &pos, (colnr_T *)&tocol, NULL, NULL); | |
635 } | |
636 else | |
637 tocol = MAXCOL; | |
638 // do at least one character; happens when past end of line | |
639 if (fromcol == tocol) | |
640 tocol = fromcol + 1; | |
641 area_highlighting = TRUE; | |
642 vi_attr = HL_ATTR(HLF_I); | |
643 } | |
644 } | |
645 | |
646 #ifdef FEAT_DIFF | |
647 filler_lines = diff_check(wp, lnum); | |
648 if (filler_lines < 0) | |
649 { | |
650 if (filler_lines == -1) | |
651 { | |
652 if (diff_find_change(wp, lnum, &change_start, &change_end)) | |
653 diff_hlf = HLF_ADD; // added line | |
654 else if (change_start == 0) | |
655 diff_hlf = HLF_TXD; // changed text | |
656 else | |
657 diff_hlf = HLF_CHD; // changed line | |
658 } | |
659 else | |
660 diff_hlf = HLF_ADD; // added line | |
661 filler_lines = 0; | |
662 area_highlighting = TRUE; | |
663 } | |
664 if (lnum == wp->w_topline) | |
665 filler_lines = wp->w_topfill; | |
666 filler_todo = filler_lines; | |
667 #endif | |
668 | |
669 #ifdef FEAT_SIGNS | |
670 sign_present = buf_get_signattrs(wp->w_buffer, lnum, &sattr); | |
671 #endif | |
672 | |
673 #ifdef LINE_ATTR | |
674 # ifdef FEAT_SIGNS | |
675 // If this line has a sign with line highlighting set line_attr. | |
676 if (sign_present) | |
677 line_attr = sattr.linehl; | |
678 # endif | |
679 # if defined(FEAT_QUICKFIX) | |
680 // Highlight the current line in the quickfix window. | |
681 if (bt_quickfix(wp->w_buffer) && qf_current_entry(wp) == lnum) | |
682 line_attr = HL_ATTR(HLF_QFL); | |
683 # endif | |
684 if (line_attr != 0) | |
685 area_highlighting = TRUE; | |
686 #endif | |
687 | |
688 line = ml_get_buf(wp->w_buffer, lnum, FALSE); | |
689 ptr = line; | |
690 | |
691 #ifdef FEAT_SPELL | |
692 if (has_spell && !number_only) | |
693 { | |
694 // For checking first word with a capital skip white space. | |
695 if (cap_col == 0) | |
696 cap_col = getwhitecols(line); | |
697 | |
698 // To be able to spell-check over line boundaries copy the end of the | |
699 // current line into nextline[]. Above the start of the next line was | |
700 // copied to nextline[SPWORDLEN]. | |
701 if (nextline[SPWORDLEN] == NUL) | |
702 { | |
703 // No next line or it is empty. | |
704 nextlinecol = MAXCOL; | |
705 nextline_idx = 0; | |
706 } | |
707 else | |
708 { | |
709 v = (long)STRLEN(line); | |
710 if (v < SPWORDLEN) | |
711 { | |
712 // Short line, use it completely and append the start of the | |
713 // next line. | |
714 nextlinecol = 0; | |
715 mch_memmove(nextline, line, (size_t)v); | |
716 STRMOVE(nextline + v, nextline + SPWORDLEN); | |
717 nextline_idx = v + 1; | |
718 } | |
719 else | |
720 { | |
721 // Long line, use only the last SPWORDLEN bytes. | |
722 nextlinecol = v - SPWORDLEN; | |
723 mch_memmove(nextline, line + nextlinecol, SPWORDLEN); | |
724 nextline_idx = SPWORDLEN + 1; | |
725 } | |
726 } | |
727 } | |
728 #endif | |
729 | |
730 if (wp->w_p_list) | |
731 { | |
732 if (lcs_space || lcs_trail || lcs_nbsp) | |
733 extra_check = TRUE; | |
734 // find start of trailing whitespace | |
735 if (lcs_trail) | |
736 { | |
737 trailcol = (colnr_T)STRLEN(ptr); | |
738 while (trailcol > (colnr_T)0 && VIM_ISWHITE(ptr[trailcol - 1])) | |
739 --trailcol; | |
740 trailcol += (colnr_T) (ptr - line); | |
741 } | |
742 } | |
743 | |
744 wcr_attr = get_wcr_attr(wp); | |
745 if (wcr_attr != 0) | |
746 { | |
747 win_attr = wcr_attr; | |
748 area_highlighting = TRUE; | |
749 } | |
750 #ifdef FEAT_TEXT_PROP | |
751 if (WIN_IS_POPUP(wp)) | |
752 screen_line_flags |= SLF_POPUP; | |
753 #endif | |
754 | |
755 // 'nowrap' or 'wrap' and a single line that doesn't fit: Advance to the | |
756 // first character to be displayed. | |
757 if (wp->w_p_wrap) | |
758 v = wp->w_skipcol; | |
759 else | |
760 v = wp->w_leftcol; | |
761 if (v > 0 && !number_only) | |
762 { | |
763 char_u *prev_ptr = ptr; | |
764 | |
765 while (vcol < v && *ptr != NUL) | |
766 { | |
767 c = win_lbr_chartabsize(wp, line, ptr, (colnr_T)vcol, NULL); | |
768 vcol += c; | |
769 prev_ptr = ptr; | |
770 MB_PTR_ADV(ptr); | |
771 } | |
772 | |
773 // When: | |
774 // - 'cuc' is set, or | |
775 // - 'colorcolumn' is set, or | |
776 // - 'virtualedit' is set, or | |
777 // - the visual mode is active, | |
778 // the end of the line may be before the start of the displayed part. | |
779 if (vcol < v && ( | |
780 #ifdef FEAT_SYN_HL | |
781 wp->w_p_cuc || draw_color_col || | |
782 #endif | |
783 virtual_active() || | |
784 (VIsual_active && wp->w_buffer == curwin->w_buffer))) | |
785 vcol = v; | |
786 | |
787 // Handle a character that's not completely on the screen: Put ptr at | |
788 // that character but skip the first few screen characters. | |
789 if (vcol > v) | |
790 { | |
791 vcol -= c; | |
792 ptr = prev_ptr; | |
793 // If the character fits on the screen, don't need to skip it. | |
794 // Except for a TAB. | |
795 if (( (*mb_ptr2cells)(ptr) >= c || *ptr == TAB) && col == 0) | |
796 n_skip = v - vcol; | |
797 } | |
798 | |
799 // Adjust for when the inverted text is before the screen, | |
800 // and when the start of the inverted text is before the screen. | |
801 if (tocol <= vcol) | |
802 fromcol = 0; | |
803 else if (fromcol >= 0 && fromcol < vcol) | |
804 fromcol = vcol; | |
805 | |
806 #ifdef FEAT_LINEBREAK | |
807 // When w_skipcol is non-zero, first line needs 'showbreak' | |
808 if (wp->w_p_wrap) | |
809 need_showbreak = TRUE; | |
810 #endif | |
811 #ifdef FEAT_SPELL | |
812 // When spell checking a word we need to figure out the start of the | |
813 // word and if it's badly spelled or not. | |
814 if (has_spell) | |
815 { | |
816 int len; | |
817 colnr_T linecol = (colnr_T)(ptr - line); | |
818 hlf_T spell_hlf = HLF_COUNT; | |
819 | |
820 pos = wp->w_cursor; | |
821 wp->w_cursor.lnum = lnum; | |
822 wp->w_cursor.col = linecol; | |
823 len = spell_move_to(wp, FORWARD, TRUE, TRUE, &spell_hlf); | |
824 | |
825 // spell_move_to() may call ml_get() and make "line" invalid | |
826 line = ml_get_buf(wp->w_buffer, lnum, FALSE); | |
827 ptr = line + linecol; | |
828 | |
829 if (len == 0 || (int)wp->w_cursor.col > ptr - line) | |
830 { | |
831 // no bad word found at line start, don't check until end of a | |
832 // word | |
833 spell_hlf = HLF_COUNT; | |
834 word_end = (int)(spell_to_word_end(ptr, wp) - line + 1); | |
835 } | |
836 else | |
837 { | |
838 // bad word found, use attributes until end of word | |
839 word_end = wp->w_cursor.col + len + 1; | |
840 | |
841 // Turn index into actual attributes. | |
842 if (spell_hlf != HLF_COUNT) | |
843 spell_attr = highlight_attr[spell_hlf]; | |
844 } | |
845 wp->w_cursor = pos; | |
846 | |
847 # ifdef FEAT_SYN_HL | |
848 // Need to restart syntax highlighting for this line. | |
849 if (has_syntax) | |
850 syntax_start(wp, lnum); | |
851 # endif | |
852 } | |
853 #endif | |
854 } | |
855 | |
856 // Correct highlighting for cursor that can't be disabled. | |
857 // Avoids having to check this for each character. | |
858 if (fromcol >= 0) | |
859 { | |
860 if (noinvcur) | |
861 { | |
862 if ((colnr_T)fromcol == wp->w_virtcol) | |
863 { | |
864 // highlighting starts at cursor, let it start just after the | |
865 // cursor | |
866 fromcol_prev = fromcol; | |
867 fromcol = -1; | |
868 } | |
869 else if ((colnr_T)fromcol < wp->w_virtcol) | |
870 // restart highlighting after the cursor | |
871 fromcol_prev = wp->w_virtcol; | |
872 } | |
873 if (fromcol >= tocol) | |
874 fromcol = -1; | |
875 } | |
876 | |
877 #ifdef FEAT_SEARCH_EXTRA | |
878 if (!number_only) | |
879 { | |
880 v = (long)(ptr - line); | |
881 area_highlighting |= prepare_search_hl_line(wp, lnum, (colnr_T)v, | |
882 &line, &screen_search_hl, | |
883 &search_attr); | |
884 ptr = line + v; // "line" may have been updated | |
885 } | |
886 #endif | |
887 | |
888 #ifdef FEAT_SYN_HL | |
889 // Cursor line highlighting for 'cursorline' in the current window. | |
890 if (wp->w_p_cul && lnum == wp->w_cursor.lnum) | |
891 { | |
892 // Do not show the cursor line in the text when Visual mode is active, | |
893 // because it's not clear what is selected then. Do update | |
894 // w_last_cursorline. | |
895 if (!(wp == curwin && VIsual_active) | |
896 && wp->w_p_culopt_flags != CULOPT_NBR) | |
897 { | |
898 cul_screenline = (wp->w_p_wrap | |
899 && (wp->w_p_culopt_flags & CULOPT_SCRLINE)); | |
900 | |
901 // Only set line_attr here when "screenline" is not present in | |
902 // 'cursorlineopt'. Otherwise it's done later. | |
903 if (!cul_screenline) | |
904 { | |
905 cul_attr = HL_ATTR(HLF_CUL); | |
906 line_attr = cul_attr; | |
907 wp->w_last_cursorline = wp->w_cursor.lnum; | |
908 } | |
909 else | |
910 { | |
911 line_attr_save = line_attr; | |
912 wp->w_last_cursorline = 0; | |
913 margin_columns_win(wp, &left_curline_col, &right_curline_col); | |
914 } | |
915 area_highlighting = TRUE; | |
916 } | |
917 else | |
918 wp->w_last_cursorline = wp->w_cursor.lnum; | |
919 } | |
920 #endif | |
921 | |
922 #ifdef FEAT_TEXT_PROP | |
923 { | |
924 char_u *prop_start; | |
925 | |
926 text_prop_count = get_text_props(wp->w_buffer, lnum, | |
927 &prop_start, FALSE); | |
928 if (text_prop_count > 0) | |
929 { | |
930 // Make a copy of the properties, so that they are properly | |
931 // aligned. | |
932 text_props = ALLOC_MULT(textprop_T, text_prop_count); | |
933 if (text_props != NULL) | |
934 mch_memmove(text_props, prop_start, | |
935 text_prop_count * sizeof(textprop_T)); | |
936 | |
937 // Allocate an array for the indexes. | |
938 text_prop_idxs = ALLOC_MULT(int, text_prop_count); | |
939 area_highlighting = TRUE; | |
940 extra_check = TRUE; | |
941 } | |
942 } | |
943 #endif | |
944 | |
945 off = (unsigned)(current_ScreenLine - ScreenLines); | |
946 col = 0; | |
947 | |
948 #ifdef FEAT_RIGHTLEFT | |
949 if (wp->w_p_rl) | |
950 { | |
951 // Rightleft window: process the text in the normal direction, but put | |
952 // it in current_ScreenLine[] from right to left. Start at the | |
953 // rightmost column of the window. | |
954 col = wp->w_width - 1; | |
955 off += col; | |
956 screen_line_flags |= SLF_RIGHTLEFT; | |
957 } | |
958 #endif | |
959 | |
960 // Repeat for the whole displayed line. | |
961 for (;;) | |
962 { | |
963 #if defined(FEAT_CONCEAL) || defined(FEAT_SEARCH_EXTRA) | |
964 int has_match_conc = 0; // match wants to conceal | |
965 #endif | |
966 #ifdef FEAT_CONCEAL | |
967 int did_decrement_ptr = FALSE; | |
968 #endif | |
969 // Skip this quickly when working on the text. | |
970 if (draw_state != WL_LINE) | |
971 { | |
972 #ifdef FEAT_CMDWIN | |
973 if (draw_state == WL_CMDLINE - 1 && n_extra == 0) | |
974 { | |
975 draw_state = WL_CMDLINE; | |
976 if (cmdwin_type != 0 && wp == curwin) | |
977 { | |
978 // Draw the cmdline character. | |
979 n_extra = 1; | |
980 c_extra = cmdwin_type; | |
981 c_final = NUL; | |
982 char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_AT)); | |
983 } | |
984 } | |
985 #endif | |
986 | |
987 #ifdef FEAT_FOLDING | |
988 if (draw_state == WL_FOLD - 1 && n_extra == 0) | |
989 { | |
990 int fdc = compute_foldcolumn(wp, 0); | |
991 | |
992 draw_state = WL_FOLD; | |
993 if (fdc > 0) | |
994 { | |
995 // Draw the 'foldcolumn'. Allocate a buffer, "extra" may | |
996 // already be in use. | |
997 vim_free(p_extra_free); | |
998 p_extra_free = alloc(12 + 1); | |
999 | |
1000 if (p_extra_free != NULL) | |
1001 { | |
1002 fill_foldcolumn(p_extra_free, wp, FALSE, lnum); | |
1003 n_extra = fdc; | |
1004 p_extra_free[n_extra] = NUL; | |
1005 p_extra = p_extra_free; | |
1006 c_extra = NUL; | |
1007 c_final = NUL; | |
1008 char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_FC)); | |
1009 } | |
1010 } | |
1011 } | |
1012 #endif | |
1013 | |
1014 #ifdef FEAT_SIGNS | |
1015 if (draw_state == WL_SIGN - 1 && n_extra == 0) | |
1016 { | |
1017 draw_state = WL_SIGN; | |
1018 // Show the sign column when there are any signs in this | |
1019 // buffer or when using Netbeans. | |
1020 if (signcolumn_on(wp)) | |
1021 get_sign_display_info(FALSE, wp, lnum, &sattr, wcr_attr, | |
1022 row, startrow, filler_lines, filler_todo, &c_extra, | |
1023 &c_final, extra, &p_extra, &n_extra, &char_attr); | |
1024 } | |
1025 #endif | |
1026 | |
1027 if (draw_state == WL_NR - 1 && n_extra == 0) | |
1028 { | |
1029 draw_state = WL_NR; | |
1030 // Display the absolute or relative line number. After the | |
1031 // first fill with blanks when the 'n' flag isn't in 'cpo' | |
1032 if ((wp->w_p_nu || wp->w_p_rnu) | |
1033 && (row == startrow | |
1034 #ifdef FEAT_DIFF | |
1035 + filler_lines | |
1036 #endif | |
1037 || vim_strchr(p_cpo, CPO_NUMCOL) == NULL)) | |
1038 { | |
1039 #ifdef FEAT_SIGNS | |
1040 // If 'signcolumn' is set to 'number' and a sign is present | |
1041 // in 'lnum', then display the sign instead of the line | |
1042 // number. | |
1043 if ((*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u') | |
1044 && sign_present) | |
1045 get_sign_display_info(TRUE, wp, lnum, &sattr, wcr_attr, | |
1046 row, startrow, filler_lines, filler_todo, | |
1047 &c_extra, &c_final, extra, &p_extra, &n_extra, | |
1048 &char_attr); | |
1049 else | |
1050 #endif | |
1051 { | |
1052 // Draw the line number (empty space after wrapping). | |
1053 if (row == startrow | |
1054 #ifdef FEAT_DIFF | |
1055 + filler_lines | |
1056 #endif | |
1057 ) | |
1058 { | |
1059 long num; | |
1060 char *fmt = "%*ld "; | |
1061 | |
1062 if (wp->w_p_nu && !wp->w_p_rnu) | |
1063 // 'number' + 'norelativenumber' | |
1064 num = (long)lnum; | |
1065 else | |
1066 { | |
1067 // 'relativenumber', don't use negative numbers | |
1068 num = labs((long)get_cursor_rel_lnum(wp, lnum)); | |
1069 if (num == 0 && wp->w_p_nu && wp->w_p_rnu) | |
1070 { | |
1071 // 'number' + 'relativenumber' | |
1072 num = lnum; | |
1073 fmt = "%-*ld "; | |
1074 } | |
1075 } | |
1076 | |
1077 sprintf((char *)extra, fmt, | |
1078 number_width(wp), num); | |
1079 if (wp->w_skipcol > 0) | |
1080 for (p_extra = extra; *p_extra == ' '; ++p_extra) | |
1081 *p_extra = '-'; | |
1082 #ifdef FEAT_RIGHTLEFT | |
1083 if (wp->w_p_rl) // reverse line numbers | |
1084 { | |
1085 char_u *p1, *p2; | |
1086 int t; | |
1087 | |
1088 // like rl_mirror(), but keep the space at the end | |
1089 p2 = skiptowhite(extra) - 1; | |
1090 for (p1 = extra; p1 < p2; ++p1, --p2) | |
1091 { | |
1092 t = *p1; | |
1093 *p1 = *p2; | |
1094 *p2 = t; | |
1095 } | |
1096 } | |
1097 #endif | |
1098 p_extra = extra; | |
1099 c_extra = NUL; | |
1100 c_final = NUL; | |
1101 } | |
1102 else | |
1103 { | |
1104 c_extra = ' '; | |
1105 c_final = NUL; | |
1106 } | |
1107 n_extra = number_width(wp) + 1; | |
1108 char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_N)); | |
1109 #ifdef FEAT_SYN_HL | |
1110 // When 'cursorline' is set highlight the line number of | |
1111 // the current line differently. | |
1112 // When 'cursorlineopt' has "screenline" only highlight | |
1113 // the line number itself. | |
1114 // TODO: Can we use CursorLine instead of CursorLineNr | |
1115 // when CursorLineNr isn't set? | |
1116 if ((wp->w_p_cul || wp->w_p_rnu) | |
1117 && (wp->w_p_culopt_flags & CULOPT_NBR) | |
1118 && (row == startrow | |
1119 || wp->w_p_culopt_flags & CULOPT_LINE) | |
1120 && lnum == wp->w_cursor.lnum) | |
1121 char_attr = hl_combine_attr(wcr_attr, HL_ATTR(HLF_CLN)); | |
1122 #endif | |
1123 } | |
1124 } | |
1125 } | |
1126 | |
1127 #ifdef FEAT_LINEBREAK | |
1128 if (wp->w_p_brisbr && draw_state == WL_BRI - 1 | |
1129 && n_extra == 0 && *p_sbr != NUL) | |
1130 // draw indent after showbreak value | |
1131 draw_state = WL_BRI; | |
1132 else if (wp->w_p_brisbr && draw_state == WL_SBR && n_extra == 0) | |
1133 // After the showbreak, draw the breakindent | |
1134 draw_state = WL_BRI - 1; | |
1135 | |
1136 // draw 'breakindent': indent wrapped text accordingly | |
1137 if (draw_state == WL_BRI - 1 && n_extra == 0) | |
1138 { | |
1139 draw_state = WL_BRI; | |
1140 // if need_showbreak is set, breakindent also applies | |
1141 if (wp->w_p_bri && n_extra == 0 | |
1142 && (row != startrow || need_showbreak) | |
1143 # ifdef FEAT_DIFF | |
1144 && filler_lines == 0 | |
1145 # endif | |
1146 ) | |
1147 { | |
1148 char_attr = 0; | |
1149 # ifdef FEAT_DIFF | |
1150 if (diff_hlf != (hlf_T)0) | |
1151 { | |
1152 char_attr = HL_ATTR(diff_hlf); | |
1153 # ifdef FEAT_SYN_HL | |
1154 if (cul_attr != 0) | |
1155 char_attr = hl_combine_attr(char_attr, cul_attr); | |
1156 # endif | |
1157 } | |
1158 # endif | |
1159 p_extra = NULL; | |
1160 c_extra = ' '; | |
1161 n_extra = get_breakindent_win(wp, | |
1162 ml_get_buf(wp->w_buffer, lnum, FALSE)); | |
1163 // Correct end of highlighted area for 'breakindent', | |
1164 // required when 'linebreak' is also set. | |
1165 if (tocol == vcol) | |
1166 tocol += n_extra; | |
1167 } | |
1168 } | |
1169 #endif | |
1170 | |
1171 #if defined(FEAT_LINEBREAK) || defined(FEAT_DIFF) | |
1172 if (draw_state == WL_SBR - 1 && n_extra == 0) | |
1173 { | |
1174 draw_state = WL_SBR; | |
1175 # ifdef FEAT_DIFF | |
1176 if (filler_todo > 0) | |
1177 { | |
1178 // Draw "deleted" diff line(s). | |
1179 if (char2cells(fill_diff) > 1) | |
1180 { | |
1181 c_extra = '-'; | |
1182 c_final = NUL; | |
1183 } | |
1184 else | |
1185 { | |
1186 c_extra = fill_diff; | |
1187 c_final = NUL; | |
1188 } | |
1189 # ifdef FEAT_RIGHTLEFT | |
1190 if (wp->w_p_rl) | |
1191 n_extra = col + 1; | |
1192 else | |
1193 # endif | |
1194 n_extra = wp->w_width - col; | |
1195 char_attr = HL_ATTR(HLF_DED); | |
1196 } | |
1197 # endif | |
1198 # ifdef FEAT_LINEBREAK | |
1199 if (*p_sbr != NUL && need_showbreak) | |
1200 { | |
1201 // Draw 'showbreak' at the start of each broken line. | |
1202 p_extra = p_sbr; | |
1203 c_extra = NUL; | |
1204 c_final = NUL; | |
1205 n_extra = (int)STRLEN(p_sbr); | |
1206 char_attr = HL_ATTR(HLF_AT); | |
1207 need_showbreak = FALSE; | |
1208 vcol_sbr = vcol + MB_CHARLEN(p_sbr); | |
1209 // Correct end of highlighted area for 'showbreak', | |
1210 // required when 'linebreak' is also set. | |
1211 if (tocol == vcol) | |
1212 tocol += n_extra; | |
1213 // combine 'showbreak' with 'wincolor' | |
1214 if (win_attr != 0) | |
1215 char_attr = hl_combine_attr(win_attr, char_attr); | |
1216 # ifdef FEAT_SYN_HL | |
1217 // combine 'showbreak' with 'cursorline' | |
1218 if (cul_attr != 0) | |
1219 char_attr = hl_combine_attr(char_attr, cul_attr); | |
1220 # endif | |
1221 } | |
1222 # endif | |
1223 } | |
1224 #endif | |
1225 | |
1226 if (draw_state == WL_LINE - 1 && n_extra == 0) | |
1227 { | |
1228 draw_state = WL_LINE; | |
1229 if (saved_n_extra) | |
1230 { | |
1231 // Continue item from end of wrapped line. | |
1232 n_extra = saved_n_extra; | |
1233 c_extra = saved_c_extra; | |
1234 c_final = saved_c_final; | |
1235 p_extra = saved_p_extra; | |
1236 char_attr = saved_char_attr; | |
1237 } | |
1238 else | |
1239 char_attr = win_attr; | |
1240 } | |
1241 } | |
1242 #ifdef FEAT_SYN_HL | |
1243 if (cul_screenline) | |
1244 { | |
1245 if (draw_state == WL_LINE | |
1246 && vcol >= left_curline_col | |
1247 && vcol < right_curline_col) | |
1248 { | |
1249 cul_attr = HL_ATTR(HLF_CUL); | |
1250 line_attr = cul_attr; | |
1251 } | |
1252 else | |
1253 { | |
1254 cul_attr = 0; | |
1255 line_attr = line_attr_save; | |
1256 } | |
1257 } | |
1258 #endif | |
1259 | |
1260 // When still displaying '$' of change command, stop at cursor. | |
1261 // When only displaying the (relative) line number and that's done, | |
1262 // stop here. | |
1263 if ((dollar_vcol >= 0 && wp == curwin | |
1264 && lnum == wp->w_cursor.lnum && vcol >= (long)wp->w_virtcol | |
1265 #ifdef FEAT_DIFF | |
1266 && filler_todo <= 0 | |
1267 #endif | |
1268 ) | |
1269 || (number_only && draw_state > WL_NR)) | |
1270 { | |
1271 screen_line(screen_row, wp->w_wincol, col, -(int)wp->w_width, | |
1272 screen_line_flags); | |
1273 // Pretend we have finished updating the window. Except when | |
1274 // 'cursorcolumn' is set. | |
1275 #ifdef FEAT_SYN_HL | |
1276 if (wp->w_p_cuc) | |
1277 row = wp->w_cline_row + wp->w_cline_height; | |
1278 else | |
1279 #endif | |
1280 row = wp->w_height; | |
1281 break; | |
1282 } | |
1283 | |
1284 if (draw_state == WL_LINE && (area_highlighting | |
1285 #ifdef FEAT_SPELL | |
1286 || has_spell | |
1287 #endif | |
1288 )) | |
1289 { | |
1290 // handle Visual or match highlighting in this line | |
1291 if (vcol == fromcol | |
1292 || (has_mbyte && vcol + 1 == fromcol && n_extra == 0 | |
1293 && (*mb_ptr2cells)(ptr) > 1) | |
1294 || ((int)vcol_prev == fromcol_prev | |
1295 && vcol_prev < vcol // not at margin | |
1296 && vcol < tocol)) | |
1297 area_attr = vi_attr; // start highlighting | |
1298 else if (area_attr != 0 | |
1299 && (vcol == tocol | |
1300 || (noinvcur && (colnr_T)vcol == wp->w_virtcol))) | |
1301 area_attr = 0; // stop highlighting | |
1302 | |
1303 #ifdef FEAT_SEARCH_EXTRA | |
1304 if (!n_extra) | |
1305 { | |
1306 // Check for start/end of 'hlsearch' and other matches. | |
1307 // After end, check for start/end of next match. | |
1308 // When another match, have to check for start again. | |
1309 v = (long)(ptr - line); | |
1310 search_attr = update_search_hl(wp, lnum, (colnr_T)v, &line, | |
1311 &screen_search_hl, &has_match_conc, | |
1312 &match_conc, did_line_attr, lcs_eol_one); | |
1313 ptr = line + v; // "line" may have been changed | |
1314 } | |
1315 #endif | |
1316 | |
1317 #ifdef FEAT_DIFF | |
1318 if (diff_hlf != (hlf_T)0) | |
1319 { | |
1320 if (diff_hlf == HLF_CHD && ptr - line >= change_start | |
1321 && n_extra == 0) | |
1322 diff_hlf = HLF_TXD; // changed text | |
1323 if (diff_hlf == HLF_TXD && ptr - line > change_end | |
1324 && n_extra == 0) | |
1325 diff_hlf = HLF_CHD; // changed line | |
1326 line_attr = HL_ATTR(diff_hlf); | |
1327 if (wp->w_p_cul && lnum == wp->w_cursor.lnum | |
1328 && wp->w_p_culopt_flags != CULOPT_NBR | |
1329 && (!cul_screenline || (vcol >= left_curline_col | |
1330 && vcol <= right_curline_col))) | |
1331 line_attr = hl_combine_attr( | |
1332 line_attr, HL_ATTR(HLF_CUL)); | |
1333 } | |
1334 #endif | |
1335 | |
1336 #ifdef FEAT_TEXT_PROP | |
1337 if (text_props != NULL) | |
1338 { | |
1339 int pi; | |
1340 int bcol = (int)(ptr - line); | |
1341 | |
1342 if (n_extra > 0) | |
1343 --bcol; // still working on the previous char, e.g. Tab | |
1344 | |
1345 // Check if any active property ends. | |
1346 for (pi = 0; pi < text_props_active; ++pi) | |
1347 { | |
1348 int tpi = text_prop_idxs[pi]; | |
1349 | |
1350 if (bcol >= text_props[tpi].tp_col - 1 | |
1351 + text_props[tpi].tp_len) | |
1352 { | |
1353 if (pi + 1 < text_props_active) | |
1354 mch_memmove(text_prop_idxs + pi, | |
1355 text_prop_idxs + pi + 1, | |
1356 sizeof(int) | |
1357 * (text_props_active - (pi + 1))); | |
1358 --text_props_active; | |
1359 --pi; | |
1360 } | |
1361 } | |
1362 | |
1363 // Add any text property that starts in this column. | |
1364 while (text_prop_next < text_prop_count | |
1365 && bcol >= text_props[text_prop_next].tp_col - 1) | |
1366 text_prop_idxs[text_props_active++] = text_prop_next++; | |
1367 | |
1368 text_prop_attr = 0; | |
1369 text_prop_combine = FALSE; | |
1370 if (text_props_active > 0) | |
1371 { | |
1372 // Sort the properties on priority and/or starting last. | |
1373 // Then combine the attributes, highest priority last. | |
1374 current_text_props = text_props; | |
1375 current_buf = wp->w_buffer; | |
1376 qsort((void *)text_prop_idxs, (size_t)text_props_active, | |
1377 sizeof(int), text_prop_compare); | |
1378 | |
1379 for (pi = 0; pi < text_props_active; ++pi) | |
1380 { | |
1381 int tpi = text_prop_idxs[pi]; | |
1382 proptype_T *pt = text_prop_type_by_id( | |
1383 wp->w_buffer, text_props[tpi].tp_type); | |
1384 | |
1385 if (pt != NULL && pt->pt_hl_id > 0) | |
1386 { | |
1387 int pt_attr = syn_id2attr(pt->pt_hl_id); | |
1388 | |
1389 text_prop_type = pt; | |
1390 text_prop_attr = | |
1391 hl_combine_attr(text_prop_attr, pt_attr); | |
1392 text_prop_combine = pt->pt_flags & PT_FLAG_COMBINE; | |
1393 } | |
1394 } | |
1395 } | |
1396 } | |
1397 #endif | |
1398 | |
1399 // Decide which of the highlight attributes to use. | |
1400 attr_pri = TRUE; | |
1401 #ifdef LINE_ATTR | |
1402 if (area_attr != 0) | |
1403 char_attr = hl_combine_attr(line_attr, area_attr); | |
1404 else if (search_attr != 0) | |
1405 char_attr = hl_combine_attr(line_attr, search_attr); | |
1406 # ifdef FEAT_TEXT_PROP | |
1407 else if (text_prop_type != NULL) | |
1408 { | |
1409 char_attr = hl_combine_attr( | |
1410 line_attr != 0 ? line_attr : win_attr, text_prop_attr); | |
1411 } | |
1412 # endif | |
1413 else if (line_attr != 0 && ((fromcol == -10 && tocol == MAXCOL) | |
1414 || vcol < fromcol || vcol_prev < fromcol_prev | |
1415 || vcol >= tocol)) | |
1416 { | |
1417 // Use line_attr when not in the Visual or 'incsearch' area | |
1418 // (area_attr may be 0 when "noinvcur" is set). | |
1419 char_attr = line_attr; | |
1420 attr_pri = FALSE; | |
1421 } | |
1422 #else | |
1423 if (area_attr != 0) | |
1424 char_attr = area_attr; | |
1425 else if (search_attr != 0) | |
1426 char_attr = search_attr; | |
1427 #endif | |
1428 else | |
1429 { | |
1430 attr_pri = FALSE; | |
1431 #ifdef FEAT_TEXT_PROP | |
1432 if (text_prop_type != NULL) | |
1433 { | |
1434 if (text_prop_combine) | |
1435 char_attr = hl_combine_attr( | |
1436 syntax_attr, text_prop_attr); | |
1437 else | |
1438 char_attr = hl_combine_attr( | |
1439 win_attr, text_prop_attr); | |
1440 } | |
1441 else | |
1442 #endif | |
1443 #ifdef FEAT_SYN_HL | |
1444 if (has_syntax) | |
1445 char_attr = syntax_attr; | |
1446 else | |
1447 #endif | |
1448 char_attr = 0; | |
1449 } | |
1450 } | |
1451 if (char_attr == 0) | |
1452 char_attr = win_attr; | |
1453 | |
1454 // Get the next character to put on the screen. | |
1455 | |
1456 // The "p_extra" points to the extra stuff that is inserted to | |
1457 // represent special characters (non-printable stuff) and other | |
1458 // things. When all characters are the same, c_extra is used. | |
1459 // If c_final is set, it will compulsorily be used at the end. | |
1460 // "p_extra" must end in a NUL to avoid mb_ptr2len() reads past | |
1461 // "p_extra[n_extra]". | |
1462 // For the '$' of the 'list' option, n_extra == 1, p_extra == "". | |
1463 if (n_extra > 0) | |
1464 { | |
1465 if (c_extra != NUL || (n_extra == 1 && c_final != NUL)) | |
1466 { | |
1467 c = (n_extra == 1 && c_final != NUL) ? c_final : c_extra; | |
1468 mb_c = c; // doesn't handle non-utf-8 multi-byte! | |
1469 if (enc_utf8 && utf_char2len(c) > 1) | |
1470 { | |
1471 mb_utf8 = TRUE; | |
1472 u8cc[0] = 0; | |
1473 c = 0xc0; | |
1474 } | |
1475 else | |
1476 mb_utf8 = FALSE; | |
1477 } | |
1478 else | |
1479 { | |
1480 c = *p_extra; | |
1481 if (has_mbyte) | |
1482 { | |
1483 mb_c = c; | |
1484 if (enc_utf8) | |
1485 { | |
1486 // If the UTF-8 character is more than one byte: | |
1487 // Decode it into "mb_c". | |
1488 mb_l = utfc_ptr2len(p_extra); | |
1489 mb_utf8 = FALSE; | |
1490 if (mb_l > n_extra) | |
1491 mb_l = 1; | |
1492 else if (mb_l > 1) | |
1493 { | |
1494 mb_c = utfc_ptr2char(p_extra, u8cc); | |
1495 mb_utf8 = TRUE; | |
1496 c = 0xc0; | |
1497 } | |
1498 } | |
1499 else | |
1500 { | |
1501 // if this is a DBCS character, put it in "mb_c" | |
1502 mb_l = MB_BYTE2LEN(c); | |
1503 if (mb_l >= n_extra) | |
1504 mb_l = 1; | |
1505 else if (mb_l > 1) | |
1506 mb_c = (c << 8) + p_extra[1]; | |
1507 } | |
1508 if (mb_l == 0) // at the NUL at end-of-line | |
1509 mb_l = 1; | |
1510 | |
1511 // If a double-width char doesn't fit display a '>' in the | |
1512 // last column. | |
1513 if (( | |
1514 # ifdef FEAT_RIGHTLEFT | |
1515 wp->w_p_rl ? (col <= 0) : | |
1516 # endif | |
1517 (col >= wp->w_width - 1)) | |
1518 && (*mb_char2cells)(mb_c) == 2) | |
1519 { | |
1520 c = '>'; | |
1521 mb_c = c; | |
1522 mb_l = 1; | |
1523 mb_utf8 = FALSE; | |
1524 multi_attr = HL_ATTR(HLF_AT); | |
1525 #ifdef FEAT_SYN_HL | |
1526 if (cul_attr) | |
1527 multi_attr = hl_combine_attr(multi_attr, cul_attr); | |
1528 #endif | |
1529 // put the pointer back to output the double-width | |
1530 // character at the start of the next line. | |
1531 ++n_extra; | |
1532 --p_extra; | |
1533 } | |
1534 else | |
1535 { | |
1536 n_extra -= mb_l - 1; | |
1537 p_extra += mb_l - 1; | |
1538 } | |
1539 } | |
1540 ++p_extra; | |
1541 } | |
1542 --n_extra; | |
1543 } | |
1544 else | |
1545 { | |
1546 #ifdef FEAT_LINEBREAK | |
1547 int c0; | |
1548 #endif | |
1549 | |
1550 if (p_extra_free != NULL) | |
1551 VIM_CLEAR(p_extra_free); | |
1552 // Get a character from the line itself. | |
1553 c = *ptr; | |
1554 #ifdef FEAT_LINEBREAK | |
1555 c0 = *ptr; | |
1556 #endif | |
1557 if (has_mbyte) | |
1558 { | |
1559 mb_c = c; | |
1560 if (enc_utf8) | |
1561 { | |
1562 // If the UTF-8 character is more than one byte: Decode it | |
1563 // into "mb_c". | |
1564 mb_l = utfc_ptr2len(ptr); | |
1565 mb_utf8 = FALSE; | |
1566 if (mb_l > 1) | |
1567 { | |
1568 mb_c = utfc_ptr2char(ptr, u8cc); | |
1569 // Overlong encoded ASCII or ASCII with composing char | |
1570 // is displayed normally, except a NUL. | |
1571 if (mb_c < 0x80) | |
1572 { | |
1573 c = mb_c; | |
1574 #ifdef FEAT_LINEBREAK | |
1575 c0 = mb_c; | |
1576 #endif | |
1577 } | |
1578 mb_utf8 = TRUE; | |
1579 | |
1580 // At start of the line we can have a composing char. | |
1581 // Draw it as a space with a composing char. | |
1582 if (utf_iscomposing(mb_c)) | |
1583 { | |
1584 int i; | |
1585 | |
1586 for (i = Screen_mco - 1; i > 0; --i) | |
1587 u8cc[i] = u8cc[i - 1]; | |
1588 u8cc[0] = mb_c; | |
1589 mb_c = ' '; | |
1590 } | |
1591 } | |
1592 | |
1593 if ((mb_l == 1 && c >= 0x80) | |
1594 || (mb_l >= 1 && mb_c == 0) | |
1595 || (mb_l > 1 && (!vim_isprintc(mb_c)))) | |
1596 { | |
1597 // Illegal UTF-8 byte: display as <xx>. | |
1598 // Non-BMP character : display as ? or fullwidth ?. | |
1599 transchar_hex(extra, mb_c); | |
1600 # ifdef FEAT_RIGHTLEFT | |
1601 if (wp->w_p_rl) // reverse | |
1602 rl_mirror(extra); | |
1603 # endif | |
1604 p_extra = extra; | |
1605 c = *p_extra; | |
1606 mb_c = mb_ptr2char_adv(&p_extra); | |
1607 mb_utf8 = (c >= 0x80); | |
1608 n_extra = (int)STRLEN(p_extra); | |
1609 c_extra = NUL; | |
1610 c_final = NUL; | |
1611 if (area_attr == 0 && search_attr == 0) | |
1612 { | |
1613 n_attr = n_extra + 1; | |
1614 extra_attr = HL_ATTR(HLF_8); | |
1615 saved_attr2 = char_attr; // save current attr | |
1616 } | |
1617 } | |
1618 else if (mb_l == 0) // at the NUL at end-of-line | |
1619 mb_l = 1; | |
1620 #ifdef FEAT_ARABIC | |
1621 else if (p_arshape && !p_tbidi && ARABIC_CHAR(mb_c)) | |
1622 { | |
1623 // Do Arabic shaping. | |
1624 int pc, pc1, nc; | |
1625 int pcc[MAX_MCO]; | |
1626 | |
1627 // The idea of what is the previous and next | |
1628 // character depends on 'rightleft'. | |
1629 if (wp->w_p_rl) | |
1630 { | |
1631 pc = prev_c; | |
1632 pc1 = prev_c1; | |
1633 nc = utf_ptr2char(ptr + mb_l); | |
1634 prev_c1 = u8cc[0]; | |
1635 } | |
1636 else | |
1637 { | |
1638 pc = utfc_ptr2char(ptr + mb_l, pcc); | |
1639 nc = prev_c; | |
1640 pc1 = pcc[0]; | |
1641 } | |
1642 prev_c = mb_c; | |
1643 | |
1644 mb_c = arabic_shape(mb_c, &c, &u8cc[0], pc, pc1, nc); | |
1645 } | |
1646 else | |
1647 prev_c = mb_c; | |
1648 #endif | |
1649 } | |
1650 else // enc_dbcs | |
1651 { | |
1652 mb_l = MB_BYTE2LEN(c); | |
1653 if (mb_l == 0) // at the NUL at end-of-line | |
1654 mb_l = 1; | |
1655 else if (mb_l > 1) | |
1656 { | |
1657 // We assume a second byte below 32 is illegal. | |
1658 // Hopefully this is OK for all double-byte encodings! | |
1659 if (ptr[1] >= 32) | |
1660 mb_c = (c << 8) + ptr[1]; | |
1661 else | |
1662 { | |
1663 if (ptr[1] == NUL) | |
1664 { | |
1665 // head byte at end of line | |
1666 mb_l = 1; | |
1667 transchar_nonprint(extra, c); | |
1668 } | |
1669 else | |
1670 { | |
1671 // illegal tail byte | |
1672 mb_l = 2; | |
1673 STRCPY(extra, "XX"); | |
1674 } | |
1675 p_extra = extra; | |
1676 n_extra = (int)STRLEN(extra) - 1; | |
1677 c_extra = NUL; | |
1678 c_final = NUL; | |
1679 c = *p_extra++; | |
1680 if (area_attr == 0 && search_attr == 0) | |
1681 { | |
1682 n_attr = n_extra + 1; | |
1683 extra_attr = HL_ATTR(HLF_8); | |
1684 saved_attr2 = char_attr; // save current attr | |
1685 } | |
1686 mb_c = c; | |
1687 } | |
1688 } | |
1689 } | |
1690 // If a double-width char doesn't fit display a '>' in the | |
1691 // last column; the character is displayed at the start of the | |
1692 // next line. | |
1693 if (( | |
1694 # ifdef FEAT_RIGHTLEFT | |
1695 wp->w_p_rl ? (col <= 0) : | |
1696 # endif | |
1697 (col >= wp->w_width - 1)) | |
1698 && (*mb_char2cells)(mb_c) == 2) | |
1699 { | |
1700 c = '>'; | |
1701 mb_c = c; | |
1702 mb_utf8 = FALSE; | |
1703 mb_l = 1; | |
1704 multi_attr = HL_ATTR(HLF_AT); | |
1705 // Put pointer back so that the character will be | |
1706 // displayed at the start of the next line. | |
1707 --ptr; | |
1708 #ifdef FEAT_CONCEAL | |
1709 did_decrement_ptr = TRUE; | |
1710 #endif | |
1711 } | |
1712 else if (*ptr != NUL) | |
1713 ptr += mb_l - 1; | |
1714 | |
1715 // If a double-width char doesn't fit at the left side display | |
1716 // a '<' in the first column. Don't do this for unprintable | |
1717 // characters. | |
1718 if (n_skip > 0 && mb_l > 1 && n_extra == 0) | |
1719 { | |
1720 n_extra = 1; | |
1721 c_extra = MB_FILLER_CHAR; | |
1722 c_final = NUL; | |
1723 c = ' '; | |
1724 if (area_attr == 0 && search_attr == 0) | |
1725 { | |
1726 n_attr = n_extra + 1; | |
1727 extra_attr = HL_ATTR(HLF_AT); | |
1728 saved_attr2 = char_attr; // save current attr | |
1729 } | |
1730 mb_c = c; | |
1731 mb_utf8 = FALSE; | |
1732 mb_l = 1; | |
1733 } | |
1734 | |
1735 } | |
1736 ++ptr; | |
1737 | |
1738 if (extra_check) | |
1739 { | |
1740 #ifdef FEAT_SPELL | |
1741 int can_spell = TRUE; | |
1742 #endif | |
1743 | |
1744 #ifdef FEAT_TERMINAL | |
1745 if (get_term_attr) | |
1746 { | |
1747 syntax_attr = term_get_attr(wp->w_buffer, lnum, vcol); | |
1748 | |
1749 if (!attr_pri) | |
1750 char_attr = syntax_attr; | |
1751 else | |
1752 char_attr = hl_combine_attr(syntax_attr, char_attr); | |
1753 } | |
1754 #endif | |
1755 | |
1756 #ifdef FEAT_SYN_HL | |
1757 // Get syntax attribute, unless still at the start of the line | |
1758 // (double-wide char that doesn't fit). | |
1759 v = (long)(ptr - line); | |
1760 if (has_syntax && v > 0) | |
1761 { | |
1762 // Get the syntax attribute for the character. If there | |
1763 // is an error, disable syntax highlighting. | |
1764 save_did_emsg = did_emsg; | |
1765 did_emsg = FALSE; | |
1766 | |
1767 syntax_attr = get_syntax_attr((colnr_T)v - 1, | |
1768 # ifdef FEAT_SPELL | |
1769 has_spell ? &can_spell : | |
1770 # endif | |
1771 NULL, FALSE); | |
1772 | |
1773 if (did_emsg) | |
1774 { | |
1775 wp->w_s->b_syn_error = TRUE; | |
1776 has_syntax = FALSE; | |
1777 syntax_attr = 0; | |
1778 } | |
1779 else | |
1780 did_emsg = save_did_emsg; | |
1781 | |
1782 // combine syntax attribute with 'wincolor' | |
1783 if (win_attr != 0) | |
1784 syntax_attr = hl_combine_attr(win_attr, syntax_attr); | |
1785 | |
1786 # ifdef SYN_TIME_LIMIT | |
1787 if (wp->w_s->b_syn_slow) | |
1788 has_syntax = FALSE; | |
1789 # endif | |
1790 | |
1791 // Need to get the line again, a multi-line regexp may | |
1792 // have made it invalid. | |
1793 line = ml_get_buf(wp->w_buffer, lnum, FALSE); | |
1794 ptr = line + v; | |
1795 | |
1796 # ifdef FEAT_TEXT_PROP | |
1797 // Text properties overrule syntax highlighting or combine. | |
1798 if (text_prop_attr == 0 || text_prop_combine) | |
1799 # endif | |
1800 { | |
1801 int comb_attr = syntax_attr; | |
1802 # ifdef FEAT_TEXT_PROP | |
1803 comb_attr = hl_combine_attr(text_prop_attr, comb_attr); | |
1804 # endif | |
1805 if (!attr_pri) | |
1806 { | |
1807 #ifdef FEAT_SYN_HL | |
1808 if (cul_attr) | |
1809 char_attr = hl_combine_attr( | |
1810 comb_attr, cul_attr); | |
1811 else | |
1812 #endif | |
1813 if (line_attr) | |
1814 char_attr = hl_combine_attr( | |
1815 comb_attr, line_attr); | |
1816 else | |
1817 char_attr = comb_attr; | |
1818 } | |
1819 else | |
1820 char_attr = hl_combine_attr(comb_attr, char_attr); | |
1821 } | |
1822 # ifdef FEAT_CONCEAL | |
1823 // no concealing past the end of the line, it interferes | |
1824 // with line highlighting | |
1825 if (c == NUL) | |
1826 syntax_flags = 0; | |
1827 else | |
1828 syntax_flags = get_syntax_info(&syntax_seqnr); | |
1829 # endif | |
1830 } | |
1831 #endif | |
1832 | |
1833 #ifdef FEAT_SPELL | |
1834 // Check spelling (unless at the end of the line). | |
1835 // Only do this when there is no syntax highlighting, the | |
1836 // @Spell cluster is not used or the current syntax item | |
1837 // contains the @Spell cluster. | |
1838 if (has_spell && v >= word_end && v > cur_checked_col) | |
1839 { | |
1840 spell_attr = 0; | |
1841 if (c != 0 && ( | |
1842 # ifdef FEAT_SYN_HL | |
1843 !has_syntax || | |
1844 # endif | |
1845 can_spell)) | |
1846 { | |
1847 char_u *prev_ptr, *p; | |
1848 int len; | |
1849 hlf_T spell_hlf = HLF_COUNT; | |
1850 if (has_mbyte) | |
1851 { | |
1852 prev_ptr = ptr - mb_l; | |
1853 v -= mb_l - 1; | |
1854 } | |
1855 else | |
1856 prev_ptr = ptr - 1; | |
1857 | |
1858 // Use nextline[] if possible, it has the start of the | |
1859 // next line concatenated. | |
1860 if ((prev_ptr - line) - nextlinecol >= 0) | |
1861 p = nextline + (prev_ptr - line) - nextlinecol; | |
1862 else | |
1863 p = prev_ptr; | |
1864 cap_col -= (int)(prev_ptr - line); | |
1865 len = spell_check(wp, p, &spell_hlf, &cap_col, | |
1866 nochange); | |
1867 word_end = v + len; | |
1868 | |
1869 // In Insert mode only highlight a word that | |
1870 // doesn't touch the cursor. | |
1871 if (spell_hlf != HLF_COUNT | |
1872 && (State & INSERT) != 0 | |
1873 && wp->w_cursor.lnum == lnum | |
1874 && wp->w_cursor.col >= | |
1875 (colnr_T)(prev_ptr - line) | |
1876 && wp->w_cursor.col < (colnr_T)word_end) | |
1877 { | |
1878 spell_hlf = HLF_COUNT; | |
1879 spell_redraw_lnum = lnum; | |
1880 } | |
1881 | |
1882 if (spell_hlf == HLF_COUNT && p != prev_ptr | |
1883 && (p - nextline) + len > nextline_idx) | |
1884 { | |
1885 // Remember that the good word continues at the | |
1886 // start of the next line. | |
1887 checked_lnum = lnum + 1; | |
1888 checked_col = (int)((p - nextline) + len - nextline_idx); | |
1889 } | |
1890 | |
1891 // Turn index into actual attributes. | |
1892 if (spell_hlf != HLF_COUNT) | |
1893 spell_attr = highlight_attr[spell_hlf]; | |
1894 | |
1895 if (cap_col > 0) | |
1896 { | |
1897 if (p != prev_ptr | |
1898 && (p - nextline) + cap_col >= nextline_idx) | |
1899 { | |
1900 // Remember that the word in the next line | |
1901 // must start with a capital. | |
1902 capcol_lnum = lnum + 1; | |
1903 cap_col = (int)((p - nextline) + cap_col | |
1904 - nextline_idx); | |
1905 } | |
1906 else | |
1907 // Compute the actual column. | |
1908 cap_col += (int)(prev_ptr - line); | |
1909 } | |
1910 } | |
1911 } | |
1912 if (spell_attr != 0) | |
1913 { | |
1914 if (!attr_pri) | |
1915 char_attr = hl_combine_attr(char_attr, spell_attr); | |
1916 else | |
1917 char_attr = hl_combine_attr(spell_attr, char_attr); | |
1918 } | |
1919 #endif | |
1920 #ifdef FEAT_LINEBREAK | |
1921 // Found last space before word: check for line break. | |
1922 if (wp->w_p_lbr && c0 == c | |
1923 && VIM_ISBREAK(c) && !VIM_ISBREAK((int)*ptr)) | |
1924 { | |
1925 int mb_off = has_mbyte ? (*mb_head_off)(line, ptr - 1) : 0; | |
1926 char_u *p = ptr - (mb_off + 1); | |
1927 | |
1928 // TODO: is passing p for start of the line OK? | |
1929 n_extra = win_lbr_chartabsize(wp, line, p, (colnr_T)vcol, | |
1930 NULL) - 1; | |
1931 if (c == TAB && n_extra + col > wp->w_width) | |
1932 # ifdef FEAT_VARTABS | |
1933 n_extra = tabstop_padding(vcol, wp->w_buffer->b_p_ts, | |
1934 wp->w_buffer->b_p_vts_array) - 1; | |
1935 # else | |
1936 n_extra = (int)wp->w_buffer->b_p_ts | |
1937 - vcol % (int)wp->w_buffer->b_p_ts - 1; | |
1938 # endif | |
1939 | |
1940 c_extra = mb_off > 0 ? MB_FILLER_CHAR : ' '; | |
1941 c_final = NUL; | |
1942 if (VIM_ISWHITE(c)) | |
1943 { | |
1944 #ifdef FEAT_CONCEAL | |
1945 if (c == TAB) | |
1946 // See "Tab alignment" below. | |
1947 FIX_FOR_BOGUSCOLS; | |
1948 #endif | |
1949 if (!wp->w_p_list) | |
1950 c = ' '; | |
1951 } | |
1952 } | |
1953 #endif | |
1954 | |
1955 // 'list': Change char 160 to lcs_nbsp and space to lcs_space. | |
1956 // But not when the character is followed by a composing | |
1957 // character (use mb_l to check that). | |
1958 if (wp->w_p_list | |
1959 && ((((c == 160 && mb_l == 1) | |
1960 || (mb_utf8 | |
1961 && ((mb_c == 160 && mb_l == 2) | |
1962 || (mb_c == 0x202f && mb_l == 3)))) | |
1963 && lcs_nbsp) | |
1964 || (c == ' ' | |
1965 && mb_l == 1 | |
1966 && lcs_space | |
1967 && ptr - line <= trailcol))) | |
1968 { | |
1969 c = (c == ' ') ? lcs_space : lcs_nbsp; | |
1970 if (area_attr == 0 && search_attr == 0) | |
1971 { | |
1972 n_attr = 1; | |
1973 extra_attr = HL_ATTR(HLF_8); | |
1974 saved_attr2 = char_attr; // save current attr | |
1975 } | |
1976 mb_c = c; | |
1977 if (enc_utf8 && utf_char2len(c) > 1) | |
1978 { | |
1979 mb_utf8 = TRUE; | |
1980 u8cc[0] = 0; | |
1981 c = 0xc0; | |
1982 } | |
1983 else | |
1984 mb_utf8 = FALSE; | |
1985 } | |
1986 | |
1987 if (trailcol != MAXCOL && ptr > line + trailcol && c == ' ') | |
1988 { | |
1989 c = lcs_trail; | |
1990 if (!attr_pri) | |
1991 { | |
1992 n_attr = 1; | |
1993 extra_attr = HL_ATTR(HLF_8); | |
1994 saved_attr2 = char_attr; // save current attr | |
1995 } | |
1996 mb_c = c; | |
1997 if (enc_utf8 && utf_char2len(c) > 1) | |
1998 { | |
1999 mb_utf8 = TRUE; | |
2000 u8cc[0] = 0; | |
2001 c = 0xc0; | |
2002 } | |
2003 else | |
2004 mb_utf8 = FALSE; | |
2005 } | |
2006 } | |
2007 | |
2008 // Handling of non-printable characters. | |
2009 if (!vim_isprintc(c)) | |
2010 { | |
2011 // when getting a character from the file, we may have to | |
2012 // turn it into something else on the way to putting it | |
2013 // into "ScreenLines". | |
2014 if (c == TAB && (!wp->w_p_list || lcs_tab1)) | |
2015 { | |
2016 int tab_len = 0; | |
2017 long vcol_adjusted = vcol; // removed showbreak length | |
2018 #ifdef FEAT_LINEBREAK | |
2019 // only adjust the tab_len, when at the first column | |
2020 // after the showbreak value was drawn | |
2021 if (*p_sbr != NUL && vcol == vcol_sbr && wp->w_p_wrap) | |
2022 vcol_adjusted = vcol - MB_CHARLEN(p_sbr); | |
2023 #endif | |
2024 // tab amount depends on current column | |
2025 #ifdef FEAT_VARTABS | |
2026 tab_len = tabstop_padding(vcol_adjusted, | |
2027 wp->w_buffer->b_p_ts, | |
2028 wp->w_buffer->b_p_vts_array) - 1; | |
2029 #else | |
2030 tab_len = (int)wp->w_buffer->b_p_ts | |
2031 - vcol_adjusted % (int)wp->w_buffer->b_p_ts - 1; | |
2032 #endif | |
2033 | |
2034 #ifdef FEAT_LINEBREAK | |
2035 if (!wp->w_p_lbr || !wp->w_p_list) | |
2036 #endif | |
2037 // tab amount depends on current column | |
2038 n_extra = tab_len; | |
2039 #ifdef FEAT_LINEBREAK | |
2040 else | |
2041 { | |
2042 char_u *p; | |
2043 int len; | |
2044 int i; | |
2045 int saved_nextra = n_extra; | |
2046 | |
2047 #ifdef FEAT_CONCEAL | |
2048 if (vcol_off > 0) | |
2049 // there are characters to conceal | |
2050 tab_len += vcol_off; | |
2051 // boguscols before FIX_FOR_BOGUSCOLS macro from above | |
2052 if (wp->w_p_list && lcs_tab1 && old_boguscols > 0 | |
2053 && n_extra > tab_len) | |
2054 tab_len += n_extra - tab_len; | |
2055 #endif | |
2056 | |
2057 // if n_extra > 0, it gives the number of chars, to | |
2058 // use for a tab, else we need to calculate the width | |
2059 // for a tab | |
2060 len = (tab_len * mb_char2len(lcs_tab2)); | |
2061 if (n_extra > 0) | |
2062 len += n_extra - tab_len; | |
2063 c = lcs_tab1; | |
2064 p = alloc(len + 1); | |
2065 vim_memset(p, ' ', len); | |
2066 p[len] = NUL; | |
2067 vim_free(p_extra_free); | |
2068 p_extra_free = p; | |
2069 for (i = 0; i < tab_len; i++) | |
2070 { | |
2071 int lcs = lcs_tab2; | |
2072 | |
2073 if (*p == NUL) | |
2074 { | |
2075 tab_len = i; | |
2076 break; | |
2077 } | |
2078 | |
2079 // if lcs_tab3 is given, need to change the char | |
2080 // for tab | |
2081 if (lcs_tab3 && i == tab_len - 1) | |
2082 lcs = lcs_tab3; | |
2083 mb_char2bytes(lcs, p); | |
2084 p += mb_char2len(lcs); | |
2085 n_extra += mb_char2len(lcs) | |
2086 - (saved_nextra > 0 ? 1 : 0); | |
2087 } | |
2088 p_extra = p_extra_free; | |
2089 #ifdef FEAT_CONCEAL | |
2090 // n_extra will be increased by FIX_FOX_BOGUSCOLS | |
2091 // macro below, so need to adjust for that here | |
2092 if (vcol_off > 0) | |
2093 n_extra -= vcol_off; | |
2094 #endif | |
2095 } | |
2096 #endif | |
2097 #ifdef FEAT_CONCEAL | |
2098 { | |
2099 int vc_saved = vcol_off; | |
2100 | |
2101 // Tab alignment should be identical regardless of | |
2102 // 'conceallevel' value. So tab compensates of all | |
2103 // previous concealed characters, and thus resets | |
2104 // vcol_off and boguscols accumulated so far in the | |
2105 // line. Note that the tab can be longer than | |
2106 // 'tabstop' when there are concealed characters. | |
2107 FIX_FOR_BOGUSCOLS; | |
2108 | |
2109 // Make sure, the highlighting for the tab char will be | |
2110 // correctly set further below (effectively reverts the | |
2111 // FIX_FOR_BOGSUCOLS macro | |
2112 if (n_extra == tab_len + vc_saved && wp->w_p_list | |
2113 && lcs_tab1) | |
2114 tab_len += vc_saved; | |
2115 } | |
2116 #endif | |
2117 mb_utf8 = FALSE; // don't draw as UTF-8 | |
2118 if (wp->w_p_list) | |
2119 { | |
2120 c = (n_extra == 0 && lcs_tab3) ? lcs_tab3 : lcs_tab1; | |
2121 #ifdef FEAT_LINEBREAK | |
2122 if (wp->w_p_lbr) | |
2123 c_extra = NUL; // using p_extra from above | |
2124 else | |
2125 #endif | |
2126 c_extra = lcs_tab2; | |
2127 c_final = lcs_tab3; | |
2128 n_attr = tab_len + 1; | |
2129 extra_attr = HL_ATTR(HLF_8); | |
2130 saved_attr2 = char_attr; // save current attr | |
2131 mb_c = c; | |
2132 if (enc_utf8 && utf_char2len(c) > 1) | |
2133 { | |
2134 mb_utf8 = TRUE; | |
2135 u8cc[0] = 0; | |
2136 c = 0xc0; | |
2137 } | |
2138 } | |
2139 else | |
2140 { | |
2141 c_final = NUL; | |
2142 c_extra = ' '; | |
2143 c = ' '; | |
2144 } | |
2145 } | |
2146 else if (c == NUL | |
2147 && (wp->w_p_list | |
2148 || ((fromcol >= 0 || fromcol_prev >= 0) | |
2149 && tocol > vcol | |
2150 && VIsual_mode != Ctrl_V | |
2151 && ( | |
2152 # ifdef FEAT_RIGHTLEFT | |
2153 wp->w_p_rl ? (col >= 0) : | |
2154 # endif | |
2155 (col < wp->w_width)) | |
2156 && !(noinvcur | |
2157 && lnum == wp->w_cursor.lnum | |
2158 && (colnr_T)vcol == wp->w_virtcol))) | |
2159 && lcs_eol_one > 0) | |
2160 { | |
2161 // Display a '$' after the line or highlight an extra | |
2162 // character if the line break is included. | |
2163 #if defined(FEAT_DIFF) || defined(LINE_ATTR) | |
2164 // For a diff line the highlighting continues after the | |
2165 // "$". | |
2166 if ( | |
2167 # ifdef FEAT_DIFF | |
2168 diff_hlf == (hlf_T)0 | |
2169 # ifdef LINE_ATTR | |
2170 && | |
2171 # endif | |
2172 # endif | |
2173 # ifdef LINE_ATTR | |
2174 line_attr == 0 | |
2175 # endif | |
2176 ) | |
2177 #endif | |
2178 { | |
2179 // In virtualedit, visual selections may extend | |
2180 // beyond end of line. | |
2181 if (area_highlighting && virtual_active() | |
2182 && tocol != MAXCOL && vcol < tocol) | |
2183 n_extra = 0; | |
2184 else | |
2185 { | |
2186 p_extra = at_end_str; | |
2187 n_extra = 1; | |
2188 c_extra = NUL; | |
2189 c_final = NUL; | |
2190 } | |
2191 } | |
2192 if (wp->w_p_list && lcs_eol > 0) | |
2193 c = lcs_eol; | |
2194 else | |
2195 c = ' '; | |
2196 lcs_eol_one = -1; | |
2197 --ptr; // put it back at the NUL | |
2198 if (!attr_pri) | |
2199 { | |
2200 extra_attr = HL_ATTR(HLF_AT); | |
2201 n_attr = 1; | |
2202 } | |
2203 mb_c = c; | |
2204 if (enc_utf8 && utf_char2len(c) > 1) | |
2205 { | |
2206 mb_utf8 = TRUE; | |
2207 u8cc[0] = 0; | |
2208 c = 0xc0; | |
2209 } | |
2210 else | |
2211 mb_utf8 = FALSE; // don't draw as UTF-8 | |
2212 } | |
2213 else if (c != NUL) | |
2214 { | |
2215 p_extra = transchar(c); | |
2216 if (n_extra == 0) | |
2217 n_extra = byte2cells(c) - 1; | |
2218 #ifdef FEAT_RIGHTLEFT | |
2219 if ((dy_flags & DY_UHEX) && wp->w_p_rl) | |
2220 rl_mirror(p_extra); // reverse "<12>" | |
2221 #endif | |
2222 c_extra = NUL; | |
2223 c_final = NUL; | |
2224 #ifdef FEAT_LINEBREAK | |
2225 if (wp->w_p_lbr) | |
2226 { | |
2227 char_u *p; | |
2228 | |
2229 c = *p_extra; | |
2230 p = alloc(n_extra + 1); | |
2231 vim_memset(p, ' ', n_extra); | |
2232 STRNCPY(p, p_extra + 1, STRLEN(p_extra) - 1); | |
2233 p[n_extra] = NUL; | |
2234 vim_free(p_extra_free); | |
2235 p_extra_free = p_extra = p; | |
2236 } | |
2237 else | |
2238 #endif | |
2239 { | |
2240 n_extra = byte2cells(c) - 1; | |
2241 c = *p_extra++; | |
2242 } | |
2243 if (!attr_pri) | |
2244 { | |
2245 n_attr = n_extra + 1; | |
2246 extra_attr = HL_ATTR(HLF_8); | |
2247 saved_attr2 = char_attr; // save current attr | |
2248 } | |
2249 mb_utf8 = FALSE; // don't draw as UTF-8 | |
2250 } | |
2251 else if (VIsual_active | |
2252 && (VIsual_mode == Ctrl_V | |
2253 || VIsual_mode == 'v') | |
2254 && virtual_active() | |
2255 && tocol != MAXCOL | |
2256 && vcol < tocol | |
2257 && ( | |
2258 #ifdef FEAT_RIGHTLEFT | |
2259 wp->w_p_rl ? (col >= 0) : | |
2260 #endif | |
2261 (col < wp->w_width))) | |
2262 { | |
2263 c = ' '; | |
2264 --ptr; // put it back at the NUL | |
2265 } | |
2266 #if defined(LINE_ATTR) | |
2267 else if (( | |
2268 # ifdef FEAT_DIFF | |
2269 diff_hlf != (hlf_T)0 || | |
2270 # endif | |
2271 # ifdef FEAT_TERMINAL | |
2272 win_attr != 0 || | |
2273 # endif | |
2274 line_attr != 0 | |
2275 ) && ( | |
2276 # ifdef FEAT_RIGHTLEFT | |
2277 wp->w_p_rl ? (col >= 0) : | |
2278 # endif | |
2279 (col | |
2280 # ifdef FEAT_CONCEAL | |
2281 - boguscols | |
2282 # endif | |
2283 < wp->w_width))) | |
2284 { | |
2285 // Highlight until the right side of the window | |
2286 c = ' '; | |
2287 --ptr; // put it back at the NUL | |
2288 | |
2289 // Remember we do the char for line highlighting. | |
2290 ++did_line_attr; | |
2291 | |
2292 // don't do search HL for the rest of the line | |
2293 if (line_attr != 0 && char_attr == search_attr | |
2294 && (did_line_attr > 1 | |
2295 || (wp->w_p_list && lcs_eol > 0))) | |
2296 char_attr = line_attr; | |
2297 # ifdef FEAT_DIFF | |
2298 if (diff_hlf == HLF_TXD) | |
2299 { | |
2300 diff_hlf = HLF_CHD; | |
2301 if (vi_attr == 0 || char_attr != vi_attr) | |
2302 { | |
2303 char_attr = HL_ATTR(diff_hlf); | |
2304 if (wp->w_p_cul && lnum == wp->w_cursor.lnum | |
2305 && wp->w_p_culopt_flags != CULOPT_NBR | |
2306 && (!cul_screenline | |
2307 || (vcol >= left_curline_col | |
2308 && vcol <= right_curline_col))) | |
2309 char_attr = hl_combine_attr( | |
2310 char_attr, HL_ATTR(HLF_CUL)); | |
2311 } | |
2312 } | |
2313 # endif | |
2314 # ifdef FEAT_TERMINAL | |
2315 if (win_attr != 0) | |
2316 { | |
2317 char_attr = win_attr; | |
2318 if (wp->w_p_cul && lnum == wp->w_cursor.lnum) | |
2319 { | |
2320 if (!cul_screenline || (vcol >= left_curline_col | |
2321 && vcol <= right_curline_col)) | |
2322 char_attr = hl_combine_attr( | |
2323 char_attr, HL_ATTR(HLF_CUL)); | |
2324 } | |
2325 else if (line_attr) | |
2326 char_attr = hl_combine_attr(char_attr, line_attr); | |
2327 } | |
2328 # endif | |
2329 } | |
2330 #endif | |
2331 } | |
2332 | |
2333 #ifdef FEAT_CONCEAL | |
2334 if ( wp->w_p_cole > 0 | |
2335 && (wp != curwin || lnum != wp->w_cursor.lnum || | |
2336 conceal_cursor_line(wp)) | |
2337 && ((syntax_flags & HL_CONCEAL) != 0 || has_match_conc > 0) | |
2338 && !(lnum_in_visual_area | |
2339 && vim_strchr(wp->w_p_cocu, 'v') == NULL)) | |
2340 { | |
2341 char_attr = conceal_attr; | |
2342 if ((prev_syntax_id != syntax_seqnr || has_match_conc > 1) | |
2343 && (syn_get_sub_char() != NUL || match_conc | |
2344 || wp->w_p_cole == 1) | |
2345 && wp->w_p_cole != 3) | |
2346 { | |
2347 // First time at this concealed item: display one | |
2348 // character. | |
2349 if (match_conc) | |
2350 c = match_conc; | |
2351 else if (syn_get_sub_char() != NUL) | |
2352 c = syn_get_sub_char(); | |
2353 else if (lcs_conceal != NUL) | |
2354 c = lcs_conceal; | |
2355 else | |
2356 c = ' '; | |
2357 | |
2358 prev_syntax_id = syntax_seqnr; | |
2359 | |
2360 if (n_extra > 0) | |
2361 vcol_off += n_extra; | |
2362 vcol += n_extra; | |
2363 if (wp->w_p_wrap && n_extra > 0) | |
2364 { | |
2365 # ifdef FEAT_RIGHTLEFT | |
2366 if (wp->w_p_rl) | |
2367 { | |
2368 col -= n_extra; | |
2369 boguscols -= n_extra; | |
2370 } | |
2371 else | |
2372 # endif | |
2373 { | |
2374 boguscols += n_extra; | |
2375 col += n_extra; | |
2376 } | |
2377 } | |
2378 n_extra = 0; | |
2379 n_attr = 0; | |
2380 } | |
2381 else if (n_skip == 0) | |
2382 { | |
2383 is_concealing = TRUE; | |
2384 n_skip = 1; | |
2385 } | |
2386 mb_c = c; | |
2387 if (enc_utf8 && utf_char2len(c) > 1) | |
2388 { | |
2389 mb_utf8 = TRUE; | |
2390 u8cc[0] = 0; | |
2391 c = 0xc0; | |
2392 } | |
2393 else | |
2394 mb_utf8 = FALSE; // don't draw as UTF-8 | |
2395 } | |
2396 else | |
2397 { | |
2398 prev_syntax_id = 0; | |
2399 is_concealing = FALSE; | |
2400 } | |
2401 | |
2402 if (n_skip > 0 && did_decrement_ptr) | |
2403 // not showing the '>', put pointer back to avoid getting stuck | |
2404 ++ptr; | |
2405 | |
2406 #endif // FEAT_CONCEAL | |
2407 } | |
2408 | |
2409 #ifdef FEAT_CONCEAL | |
2410 // In the cursor line and we may be concealing characters: correct | |
2411 // the cursor column when we reach its position. | |
2412 if (!did_wcol && draw_state == WL_LINE | |
2413 && wp == curwin && lnum == wp->w_cursor.lnum | |
2414 && conceal_cursor_line(wp) | |
2415 && (int)wp->w_virtcol <= vcol + n_skip) | |
2416 { | |
2417 # ifdef FEAT_RIGHTLEFT | |
2418 if (wp->w_p_rl) | |
2419 wp->w_wcol = wp->w_width - col + boguscols - 1; | |
2420 else | |
2421 # endif | |
2422 wp->w_wcol = col - boguscols; | |
2423 wp->w_wrow = row; | |
2424 did_wcol = TRUE; | |
2425 curwin->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL; | |
2426 } | |
2427 #endif | |
2428 | |
2429 // Don't override visual selection highlighting. | |
2430 if (n_attr > 0 | |
2431 && draw_state == WL_LINE | |
2432 && !attr_pri) | |
2433 { | |
2434 #ifdef LINE_ATTR | |
2435 if (line_attr) | |
2436 char_attr = hl_combine_attr(extra_attr, line_attr); | |
2437 else | |
2438 #endif | |
2439 char_attr = extra_attr; | |
2440 } | |
2441 | |
2442 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) | |
2443 // XIM don't send preedit_start and preedit_end, but they send | |
2444 // preedit_changed and commit. Thus Vim can't set "im_is_active", use | |
2445 // im_is_preediting() here. | |
2446 if (p_imst == IM_ON_THE_SPOT | |
2447 && xic != NULL | |
2448 && lnum == wp->w_cursor.lnum | |
2449 && (State & INSERT) | |
2450 && !p_imdisable | |
2451 && im_is_preediting() | |
2452 && draw_state == WL_LINE) | |
2453 { | |
2454 colnr_T tcol; | |
2455 | |
2456 if (preedit_end_col == MAXCOL) | |
2457 getvcol(curwin, &(wp->w_cursor), &tcol, NULL, NULL); | |
2458 else | |
2459 tcol = preedit_end_col; | |
2460 if ((long)preedit_start_col <= vcol && vcol < (long)tcol) | |
2461 { | |
2462 if (feedback_old_attr < 0) | |
2463 { | |
2464 feedback_col = 0; | |
2465 feedback_old_attr = char_attr; | |
2466 } | |
2467 char_attr = im_get_feedback_attr(feedback_col); | |
2468 if (char_attr < 0) | |
2469 char_attr = feedback_old_attr; | |
2470 feedback_col++; | |
2471 } | |
2472 else if (feedback_old_attr >= 0) | |
2473 { | |
2474 char_attr = feedback_old_attr; | |
2475 feedback_old_attr = -1; | |
2476 feedback_col = 0; | |
2477 } | |
2478 } | |
2479 #endif | |
2480 // Handle the case where we are in column 0 but not on the first | |
2481 // character of the line and the user wants us to show us a | |
2482 // special character (via 'listchars' option "precedes:<char>". | |
2483 if (lcs_prec_todo != NUL | |
2484 && wp->w_p_list | |
2485 && (wp->w_p_wrap ? wp->w_skipcol > 0 : wp->w_leftcol > 0) | |
2486 #ifdef FEAT_DIFF | |
2487 && filler_todo <= 0 | |
2488 #endif | |
2489 && draw_state > WL_NR | |
2490 && c != NUL) | |
2491 { | |
2492 c = lcs_prec; | |
2493 lcs_prec_todo = NUL; | |
2494 if (has_mbyte && (*mb_char2cells)(mb_c) > 1) | |
2495 { | |
2496 // Double-width character being overwritten by the "precedes" | |
2497 // character, need to fill up half the character. | |
2498 c_extra = MB_FILLER_CHAR; | |
2499 c_final = NUL; | |
2500 n_extra = 1; | |
2501 n_attr = 2; | |
2502 extra_attr = HL_ATTR(HLF_AT); | |
2503 } | |
2504 mb_c = c; | |
2505 if (enc_utf8 && utf_char2len(c) > 1) | |
2506 { | |
2507 mb_utf8 = TRUE; | |
2508 u8cc[0] = 0; | |
2509 c = 0xc0; | |
2510 } | |
2511 else | |
2512 mb_utf8 = FALSE; // don't draw as UTF-8 | |
2513 if (!attr_pri) | |
2514 { | |
2515 saved_attr3 = char_attr; // save current attr | |
2516 char_attr = HL_ATTR(HLF_AT); // later copied to char_attr | |
2517 n_attr3 = 1; | |
2518 } | |
2519 } | |
2520 | |
2521 // At end of the text line or just after the last character. | |
2522 if ((c == NUL | |
2523 #if defined(LINE_ATTR) | |
2524 || did_line_attr == 1 | |
2525 #endif | |
2526 ) && eol_hl_off == 0) | |
2527 { | |
2528 #ifdef FEAT_SEARCH_EXTRA | |
2529 // flag to indicate whether prevcol equals startcol of search_hl or | |
2530 // one of the matches | |
2531 int prevcol_hl_flag = get_prevcol_hl_flag(wp, &screen_search_hl, | |
2532 (long)(ptr - line) - (c == NUL)); | |
2533 #endif | |
2534 // Invert at least one char, used for Visual and empty line or | |
2535 // highlight match at end of line. If it's beyond the last | |
2536 // char on the screen, just overwrite that one (tricky!) Not | |
2537 // needed when a '$' was displayed for 'list'. | |
2538 if (lcs_eol == lcs_eol_one | |
2539 && ((area_attr != 0 && vcol == fromcol | |
2540 && (VIsual_mode != Ctrl_V | |
2541 || lnum == VIsual.lnum | |
2542 || lnum == curwin->w_cursor.lnum) | |
2543 && c == NUL) | |
2544 #ifdef FEAT_SEARCH_EXTRA | |
2545 // highlight 'hlsearch' match at end of line | |
2546 || (prevcol_hl_flag | |
2547 # ifdef FEAT_SYN_HL | |
2548 && !(wp->w_p_cul && lnum == wp->w_cursor.lnum | |
2549 && !(wp == curwin && VIsual_active)) | |
2550 # endif | |
2551 # ifdef FEAT_DIFF | |
2552 && diff_hlf == (hlf_T)0 | |
2553 # endif | |
2554 # if defined(LINE_ATTR) | |
2555 && did_line_attr <= 1 | |
2556 # endif | |
2557 ) | |
2558 #endif | |
2559 )) | |
2560 { | |
2561 int n = 0; | |
2562 | |
2563 #ifdef FEAT_RIGHTLEFT | |
2564 if (wp->w_p_rl) | |
2565 { | |
2566 if (col < 0) | |
2567 n = 1; | |
2568 } | |
2569 else | |
2570 #endif | |
2571 { | |
2572 if (col >= wp->w_width) | |
2573 n = -1; | |
2574 } | |
2575 if (n != 0) | |
2576 { | |
2577 // At the window boundary, highlight the last character | |
2578 // instead (better than nothing). | |
2579 off += n; | |
2580 col += n; | |
2581 } | |
2582 else | |
2583 { | |
2584 // Add a blank character to highlight. | |
2585 ScreenLines[off] = ' '; | |
2586 if (enc_utf8) | |
2587 ScreenLinesUC[off] = 0; | |
2588 } | |
2589 #ifdef FEAT_SEARCH_EXTRA | |
2590 if (area_attr == 0) | |
2591 { | |
2592 // Use attributes from match with highest priority among | |
2593 // 'search_hl' and the match list. | |
2594 get_search_match_hl(wp, &screen_search_hl, | |
2595 (long)(ptr - line), &char_attr); | |
2596 } | |
2597 #endif | |
2598 ScreenAttrs[off] = char_attr; | |
2599 #ifdef FEAT_RIGHTLEFT | |
2600 if (wp->w_p_rl) | |
2601 { | |
2602 --col; | |
2603 --off; | |
2604 } | |
2605 else | |
2606 #endif | |
2607 { | |
2608 ++col; | |
2609 ++off; | |
2610 } | |
2611 ++vcol; | |
2612 eol_hl_off = 1; | |
2613 } | |
2614 } | |
2615 | |
2616 // At end of the text line. | |
2617 if (c == NUL) | |
2618 { | |
2619 #ifdef FEAT_SYN_HL | |
2620 // Highlight 'cursorcolumn' & 'colorcolumn' past end of the line. | |
2621 if (wp->w_p_wrap) | |
2622 v = wp->w_skipcol; | |
2623 else | |
2624 v = wp->w_leftcol; | |
2625 | |
2626 // check if line ends before left margin | |
2627 if (vcol < v + col - win_col_off(wp)) | |
2628 vcol = v + col - win_col_off(wp); | |
2629 #ifdef FEAT_CONCEAL | |
2630 // Get rid of the boguscols now, we want to draw until the right | |
2631 // edge for 'cursorcolumn'. | |
2632 col -= boguscols; | |
2633 boguscols = 0; | |
2634 #endif | |
2635 | |
2636 if (draw_color_col) | |
2637 draw_color_col = advance_color_col(VCOL_HLC, &color_cols); | |
2638 | |
2639 if (((wp->w_p_cuc | |
2640 && (int)wp->w_virtcol >= VCOL_HLC - eol_hl_off | |
2641 && (int)wp->w_virtcol < | |
2642 wp->w_width * (row - startrow + 1) + v | |
2643 && lnum != wp->w_cursor.lnum) | |
2644 || draw_color_col | |
2645 || win_attr != 0) | |
2646 # ifdef FEAT_RIGHTLEFT | |
2647 && !wp->w_p_rl | |
2648 # endif | |
2649 ) | |
2650 { | |
2651 int rightmost_vcol = 0; | |
2652 int i; | |
2653 | |
2654 if (wp->w_p_cuc) | |
2655 rightmost_vcol = wp->w_virtcol; | |
2656 if (draw_color_col) | |
2657 // determine rightmost colorcolumn to possibly draw | |
2658 for (i = 0; color_cols[i] >= 0; ++i) | |
2659 if (rightmost_vcol < color_cols[i]) | |
2660 rightmost_vcol = color_cols[i]; | |
2661 | |
2662 while (col < wp->w_width) | |
2663 { | |
2664 ScreenLines[off] = ' '; | |
2665 if (enc_utf8) | |
2666 ScreenLinesUC[off] = 0; | |
2667 ++col; | |
2668 if (draw_color_col) | |
2669 draw_color_col = advance_color_col(VCOL_HLC, | |
2670 &color_cols); | |
2671 | |
2672 if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol) | |
2673 ScreenAttrs[off++] = HL_ATTR(HLF_CUC); | |
2674 else if (draw_color_col && VCOL_HLC == *color_cols) | |
2675 ScreenAttrs[off++] = HL_ATTR(HLF_MC); | |
2676 else | |
2677 ScreenAttrs[off++] = win_attr; | |
2678 | |
2679 if (VCOL_HLC >= rightmost_vcol && win_attr == 0) | |
2680 break; | |
2681 | |
2682 ++vcol; | |
2683 } | |
2684 } | |
2685 #endif | |
2686 | |
2687 screen_line(screen_row, wp->w_wincol, col, | |
2688 (int)wp->w_width, screen_line_flags); | |
2689 row++; | |
2690 | |
2691 // Update w_cline_height and w_cline_folded if the cursor line was | |
2692 // updated (saves a call to plines() later). | |
2693 if (wp == curwin && lnum == curwin->w_cursor.lnum) | |
2694 { | |
2695 curwin->w_cline_row = startrow; | |
2696 curwin->w_cline_height = row - startrow; | |
2697 #ifdef FEAT_FOLDING | |
2698 curwin->w_cline_folded = FALSE; | |
2699 #endif | |
2700 curwin->w_valid |= (VALID_CHEIGHT|VALID_CROW); | |
2701 } | |
2702 | |
2703 break; | |
2704 } | |
2705 | |
2706 // Show "extends" character from 'listchars' if beyond the line end and | |
2707 // 'list' is set. | |
2708 if (lcs_ext != NUL | |
2709 && wp->w_p_list | |
2710 && !wp->w_p_wrap | |
2711 #ifdef FEAT_DIFF | |
2712 && filler_todo <= 0 | |
2713 #endif | |
2714 && ( | |
2715 #ifdef FEAT_RIGHTLEFT | |
2716 wp->w_p_rl ? col == 0 : | |
2717 #endif | |
2718 col == wp->w_width - 1) | |
2719 && (*ptr != NUL | |
2720 || (wp->w_p_list && lcs_eol_one > 0) | |
2721 || (n_extra && (c_extra != NUL || *p_extra != NUL)))) | |
2722 { | |
2723 c = lcs_ext; | |
2724 char_attr = HL_ATTR(HLF_AT); | |
2725 mb_c = c; | |
2726 if (enc_utf8 && utf_char2len(c) > 1) | |
2727 { | |
2728 mb_utf8 = TRUE; | |
2729 u8cc[0] = 0; | |
2730 c = 0xc0; | |
2731 } | |
2732 else | |
2733 mb_utf8 = FALSE; | |
2734 } | |
2735 | |
2736 #ifdef FEAT_SYN_HL | |
2737 // advance to the next 'colorcolumn' | |
2738 if (draw_color_col) | |
2739 draw_color_col = advance_color_col(VCOL_HLC, &color_cols); | |
2740 | |
2741 // Highlight the cursor column if 'cursorcolumn' is set. But don't | |
2742 // highlight the cursor position itself. | |
2743 // Also highlight the 'colorcolumn' if it is different than | |
2744 // 'cursorcolumn' | |
2745 vcol_save_attr = -1; | |
2746 if (draw_state == WL_LINE && !lnum_in_visual_area | |
2747 && search_attr == 0 && area_attr == 0) | |
2748 { | |
2749 if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol | |
2750 && lnum != wp->w_cursor.lnum) | |
2751 { | |
2752 vcol_save_attr = char_attr; | |
2753 char_attr = hl_combine_attr(char_attr, HL_ATTR(HLF_CUC)); | |
2754 } | |
2755 else if (draw_color_col && VCOL_HLC == *color_cols) | |
2756 { | |
2757 vcol_save_attr = char_attr; | |
2758 char_attr = hl_combine_attr(char_attr, HL_ATTR(HLF_MC)); | |
2759 } | |
2760 } | |
2761 #endif | |
2762 | |
2763 // Store character to be displayed. | |
2764 // Skip characters that are left of the screen for 'nowrap'. | |
2765 vcol_prev = vcol; | |
2766 if (draw_state < WL_LINE || n_skip <= 0) | |
2767 { | |
2768 // Store the character. | |
2769 #if defined(FEAT_RIGHTLEFT) | |
2770 if (has_mbyte && wp->w_p_rl && (*mb_char2cells)(mb_c) > 1) | |
2771 { | |
2772 // A double-wide character is: put first halve in left cell. | |
2773 --off; | |
2774 --col; | |
2775 } | |
2776 #endif | |
2777 ScreenLines[off] = c; | |
2778 if (enc_dbcs == DBCS_JPNU) | |
2779 { | |
2780 if ((mb_c & 0xff00) == 0x8e00) | |
2781 ScreenLines[off] = 0x8e; | |
2782 ScreenLines2[off] = mb_c & 0xff; | |
2783 } | |
2784 else if (enc_utf8) | |
2785 { | |
2786 if (mb_utf8) | |
2787 { | |
2788 int i; | |
2789 | |
2790 ScreenLinesUC[off] = mb_c; | |
2791 if ((c & 0xff) == 0) | |
2792 ScreenLines[off] = 0x80; // avoid storing zero | |
2793 for (i = 0; i < Screen_mco; ++i) | |
2794 { | |
2795 ScreenLinesC[i][off] = u8cc[i]; | |
2796 if (u8cc[i] == 0) | |
2797 break; | |
2798 } | |
2799 } | |
2800 else | |
2801 ScreenLinesUC[off] = 0; | |
2802 } | |
2803 if (multi_attr) | |
2804 { | |
2805 ScreenAttrs[off] = multi_attr; | |
2806 multi_attr = 0; | |
2807 } | |
2808 else | |
2809 ScreenAttrs[off] = char_attr; | |
2810 | |
2811 if (has_mbyte && (*mb_char2cells)(mb_c) > 1) | |
2812 { | |
2813 // Need to fill two screen columns. | |
2814 ++off; | |
2815 ++col; | |
2816 if (enc_utf8) | |
2817 // UTF-8: Put a 0 in the second screen char. | |
2818 ScreenLines[off] = 0; | |
2819 else | |
2820 // DBCS: Put second byte in the second screen char. | |
2821 ScreenLines[off] = mb_c & 0xff; | |
2822 if (draw_state > WL_NR | |
2823 #ifdef FEAT_DIFF | |
2824 && filler_todo <= 0 | |
2825 #endif | |
2826 ) | |
2827 ++vcol; | |
2828 // When "tocol" is halfway a character, set it to the end of | |
2829 // the character, otherwise highlighting won't stop. | |
2830 if (tocol == vcol) | |
2831 ++tocol; | |
2832 #ifdef FEAT_RIGHTLEFT | |
2833 if (wp->w_p_rl) | |
2834 { | |
2835 // now it's time to backup one cell | |
2836 --off; | |
2837 --col; | |
2838 } | |
2839 #endif | |
2840 } | |
2841 #ifdef FEAT_RIGHTLEFT | |
2842 if (wp->w_p_rl) | |
2843 { | |
2844 --off; | |
2845 --col; | |
2846 } | |
2847 else | |
2848 #endif | |
2849 { | |
2850 ++off; | |
2851 ++col; | |
2852 } | |
2853 } | |
2854 #ifdef FEAT_CONCEAL | |
2855 else if (wp->w_p_cole > 0 && is_concealing) | |
2856 { | |
2857 --n_skip; | |
2858 ++vcol_off; | |
2859 if (n_extra > 0) | |
2860 vcol_off += n_extra; | |
2861 if (wp->w_p_wrap) | |
2862 { | |
2863 // Special voodoo required if 'wrap' is on. | |
2864 // | |
2865 // Advance the column indicator to force the line | |
2866 // drawing to wrap early. This will make the line | |
2867 // take up the same screen space when parts are concealed, | |
2868 // so that cursor line computations aren't messed up. | |
2869 // | |
2870 // To avoid the fictitious advance of 'col' causing | |
2871 // trailing junk to be written out of the screen line | |
2872 // we are building, 'boguscols' keeps track of the number | |
2873 // of bad columns we have advanced. | |
2874 if (n_extra > 0) | |
2875 { | |
2876 vcol += n_extra; | |
2877 # ifdef FEAT_RIGHTLEFT | |
2878 if (wp->w_p_rl) | |
2879 { | |
2880 col -= n_extra; | |
2881 boguscols -= n_extra; | |
2882 } | |
2883 else | |
2884 # endif | |
2885 { | |
2886 col += n_extra; | |
2887 boguscols += n_extra; | |
2888 } | |
2889 n_extra = 0; | |
2890 n_attr = 0; | |
2891 } | |
2892 | |
2893 | |
2894 if (has_mbyte && (*mb_char2cells)(mb_c) > 1) | |
2895 { | |
2896 // Need to fill two screen columns. | |
2897 # ifdef FEAT_RIGHTLEFT | |
2898 if (wp->w_p_rl) | |
2899 { | |
2900 --boguscols; | |
2901 --col; | |
2902 } | |
2903 else | |
2904 # endif | |
2905 { | |
2906 ++boguscols; | |
2907 ++col; | |
2908 } | |
2909 } | |
2910 | |
2911 # ifdef FEAT_RIGHTLEFT | |
2912 if (wp->w_p_rl) | |
2913 { | |
2914 --boguscols; | |
2915 --col; | |
2916 } | |
2917 else | |
2918 # endif | |
2919 { | |
2920 ++boguscols; | |
2921 ++col; | |
2922 } | |
2923 } | |
2924 else | |
2925 { | |
2926 if (n_extra > 0) | |
2927 { | |
2928 vcol += n_extra; | |
2929 n_extra = 0; | |
2930 n_attr = 0; | |
2931 } | |
2932 } | |
2933 | |
2934 } | |
2935 #endif // FEAT_CONCEAL | |
2936 else | |
2937 --n_skip; | |
2938 | |
2939 // Only advance the "vcol" when after the 'number' or 'relativenumber' | |
2940 // column. | |
2941 if (draw_state > WL_NR | |
2942 #ifdef FEAT_DIFF | |
2943 && filler_todo <= 0 | |
2944 #endif | |
2945 ) | |
2946 ++vcol; | |
2947 | |
2948 #ifdef FEAT_SYN_HL | |
2949 if (vcol_save_attr >= 0) | |
2950 char_attr = vcol_save_attr; | |
2951 #endif | |
2952 | |
2953 // restore attributes after "predeces" in 'listchars' | |
2954 if (draw_state > WL_NR && n_attr3 > 0 && --n_attr3 == 0) | |
2955 char_attr = saved_attr3; | |
2956 | |
2957 // restore attributes after last 'listchars' or 'number' char | |
2958 if (n_attr > 0 && draw_state == WL_LINE && --n_attr == 0) | |
2959 char_attr = saved_attr2; | |
2960 | |
2961 // At end of screen line and there is more to come: Display the line | |
2962 // so far. If there is no more to display it is caught above. | |
2963 if (( | |
2964 #ifdef FEAT_RIGHTLEFT | |
2965 wp->w_p_rl ? (col < 0) : | |
2966 #endif | |
2967 (col >= wp->w_width)) | |
2968 && (*ptr != NUL | |
2969 #ifdef FEAT_DIFF | |
2970 || filler_todo > 0 | |
2971 #endif | |
2972 || (wp->w_p_list && lcs_eol != NUL && p_extra != at_end_str) | |
2973 || (n_extra != 0 && (c_extra != NUL || *p_extra != NUL))) | |
2974 ) | |
2975 { | |
2976 #ifdef FEAT_CONCEAL | |
2977 screen_line(screen_row, wp->w_wincol, col - boguscols, | |
2978 (int)wp->w_width, screen_line_flags); | |
2979 boguscols = 0; | |
2980 #else | |
2981 screen_line(screen_row, wp->w_wincol, col, | |
2982 (int)wp->w_width, screen_line_flags); | |
2983 #endif | |
2984 ++row; | |
2985 ++screen_row; | |
2986 | |
2987 // When not wrapping and finished diff lines, or when displayed | |
2988 // '$' and highlighting until last column, break here. | |
2989 if ((!wp->w_p_wrap | |
2990 #ifdef FEAT_DIFF | |
2991 && filler_todo <= 0 | |
2992 #endif | |
2993 ) || lcs_eol_one == -1) | |
2994 break; | |
2995 | |
2996 // When the window is too narrow draw all "@" lines. | |
2997 if (draw_state != WL_LINE | |
2998 #ifdef FEAT_DIFF | |
2999 && filler_todo <= 0 | |
3000 #endif | |
3001 ) | |
3002 { | |
3003 win_draw_end(wp, '@', ' ', TRUE, row, wp->w_height, HLF_AT); | |
3004 draw_vsep_win(wp, row); | |
3005 row = endrow; | |
3006 } | |
3007 | |
3008 // When line got too long for screen break here. | |
3009 if (row == endrow) | |
3010 { | |
3011 ++row; | |
3012 break; | |
3013 } | |
3014 | |
3015 if (screen_cur_row == screen_row - 1 | |
3016 #ifdef FEAT_DIFF | |
3017 && filler_todo <= 0 | |
3018 #endif | |
3019 && wp->w_width == Columns) | |
3020 { | |
3021 // Remember that the line wraps, used for modeless copy. | |
3022 LineWraps[screen_row - 1] = TRUE; | |
3023 | |
3024 // Special trick to make copy/paste of wrapped lines work with | |
3025 // xterm/screen: write an extra character beyond the end of | |
3026 // the line. This will work with all terminal types | |
3027 // (regardless of the xn,am settings). | |
3028 // Only do this on a fast tty. | |
3029 // Only do this if the cursor is on the current line | |
3030 // (something has been written in it). | |
3031 // Don't do this for the GUI. | |
3032 // Don't do this for double-width characters. | |
3033 // Don't do this for a window not at the right screen border. | |
3034 if (p_tf | |
3035 #ifdef FEAT_GUI | |
3036 && !gui.in_use | |
3037 #endif | |
3038 && !(has_mbyte | |
3039 && ((*mb_off2cells)(LineOffset[screen_row], | |
3040 LineOffset[screen_row] + screen_Columns) | |
3041 == 2 | |
3042 || (*mb_off2cells)(LineOffset[screen_row - 1] | |
3043 + (int)Columns - 2, | |
3044 LineOffset[screen_row] + screen_Columns) | |
3045 == 2))) | |
3046 { | |
3047 // First make sure we are at the end of the screen line, | |
3048 // then output the same character again to let the | |
3049 // terminal know about the wrap. If the terminal doesn't | |
3050 // auto-wrap, we overwrite the character. | |
3051 if (screen_cur_col != wp->w_width) | |
3052 screen_char(LineOffset[screen_row - 1] | |
3053 + (unsigned)Columns - 1, | |
3054 screen_row - 1, (int)(Columns - 1)); | |
3055 | |
3056 // When there is a multi-byte character, just output a | |
3057 // space to keep it simple. | |
3058 if (has_mbyte && MB_BYTE2LEN(ScreenLines[LineOffset[ | |
3059 screen_row - 1] + (Columns - 1)]) > 1) | |
3060 out_char(' '); | |
3061 else | |
3062 out_char(ScreenLines[LineOffset[screen_row - 1] | |
3063 + (Columns - 1)]); | |
3064 // force a redraw of the first char on the next line | |
3065 ScreenAttrs[LineOffset[screen_row]] = (sattr_T)-1; | |
3066 screen_start(); // don't know where cursor is now | |
3067 } | |
3068 } | |
3069 | |
3070 col = 0; | |
3071 off = (unsigned)(current_ScreenLine - ScreenLines); | |
3072 #ifdef FEAT_RIGHTLEFT | |
3073 if (wp->w_p_rl) | |
3074 { | |
3075 col = wp->w_width - 1; // col is not used if breaking! | |
3076 off += col; | |
3077 } | |
3078 #endif | |
3079 | |
3080 // reset the drawing state for the start of a wrapped line | |
3081 draw_state = WL_START; | |
3082 saved_n_extra = n_extra; | |
3083 saved_p_extra = p_extra; | |
3084 saved_c_extra = c_extra; | |
3085 saved_c_final = c_final; | |
3086 #ifdef FEAT_SYN_HL | |
3087 if (!(cul_screenline | |
3088 # ifdef FEAT_DIFF | |
3089 && diff_hlf == (hlf_T)0) | |
3090 # endif | |
3091 ) | |
3092 saved_char_attr = char_attr; | |
3093 else | |
3094 #endif | |
3095 saved_char_attr = 0; | |
3096 n_extra = 0; | |
3097 lcs_prec_todo = lcs_prec; | |
3098 #ifdef FEAT_LINEBREAK | |
3099 # ifdef FEAT_DIFF | |
3100 if (filler_todo <= 0) | |
3101 # endif | |
3102 need_showbreak = TRUE; | |
3103 #endif | |
3104 #ifdef FEAT_DIFF | |
3105 --filler_todo; | |
3106 // When the filler lines are actually below the last line of the | |
3107 // file, don't draw the line itself, break here. | |
3108 if (filler_todo == 0 && wp->w_botfill) | |
3109 break; | |
3110 #endif | |
3111 } | |
3112 | |
3113 } // for every character in the line | |
3114 | |
3115 #ifdef FEAT_SPELL | |
3116 // After an empty line check first word for capital. | |
3117 if (*skipwhite(line) == NUL) | |
3118 { | |
3119 capcol_lnum = lnum + 1; | |
3120 cap_col = 0; | |
3121 } | |
3122 #endif | |
3123 #ifdef FEAT_TEXT_PROP | |
3124 vim_free(text_props); | |
3125 vim_free(text_prop_idxs); | |
3126 #endif | |
3127 | |
3128 vim_free(p_extra_free); | |
3129 return row; | |
3130 } | |
3131 |