Mercurial > vim
comparison src/misc1.c @ 18265:fe5afdc03bd2 v8.1.2127
patch 8.1.2127: the indent.c file is a bit big
Commit: https://github.com/vim/vim/commit/14c01f83487d5c53192297a710eda2b8a4ab17c9
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Oct 9 22:53:08 2019 +0200
patch 8.1.2127: the indent.c file is a bit big
Problem: The indent.c file is a bit big.
Solution: Move C-indent code a a new cindent.c file. Move other
indent-related code to indent.c. (Yegappan Lakshmanan,
closes #5031)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 09 Oct 2019 23:00:04 +0200 |
parents | e0ec4cd7a865 |
children | 9f51d0cef8da |
comparison
equal
deleted
inserted
replaced
18264:5202d9b99bee | 18265:fe5afdc03bd2 |
---|---|
21 #define URL_SLASH 1 /* path_is_url() has found "://" */ | 21 #define URL_SLASH 1 /* path_is_url() has found "://" */ |
22 #define URL_BACKSLASH 2 /* path_is_url() has found ":\\" */ | 22 #define URL_BACKSLASH 2 /* path_is_url() has found ":\\" */ |
23 | 23 |
24 // All user names (for ~user completion as done by shell). | 24 // All user names (for ~user completion as done by shell). |
25 static garray_T ga_users; | 25 static garray_T ga_users; |
26 | |
27 /* | |
28 * Count the size (in window cells) of the indent in the current line. | |
29 */ | |
30 int | |
31 get_indent(void) | |
32 { | |
33 #ifdef FEAT_VARTABS | |
34 return get_indent_str_vtab(ml_get_curline(), (int)curbuf->b_p_ts, | |
35 curbuf->b_p_vts_array, FALSE); | |
36 #else | |
37 return get_indent_str(ml_get_curline(), (int)curbuf->b_p_ts, FALSE); | |
38 #endif | |
39 } | |
40 | |
41 /* | |
42 * Count the size (in window cells) of the indent in line "lnum". | |
43 */ | |
44 int | |
45 get_indent_lnum(linenr_T lnum) | |
46 { | |
47 #ifdef FEAT_VARTABS | |
48 return get_indent_str_vtab(ml_get(lnum), (int)curbuf->b_p_ts, | |
49 curbuf->b_p_vts_array, FALSE); | |
50 #else | |
51 return get_indent_str(ml_get(lnum), (int)curbuf->b_p_ts, FALSE); | |
52 #endif | |
53 } | |
54 | |
55 #if defined(FEAT_FOLDING) || defined(PROTO) | |
56 /* | |
57 * Count the size (in window cells) of the indent in line "lnum" of buffer | |
58 * "buf". | |
59 */ | |
60 int | |
61 get_indent_buf(buf_T *buf, linenr_T lnum) | |
62 { | |
63 #ifdef FEAT_VARTABS | |
64 return get_indent_str_vtab(ml_get_buf(buf, lnum, FALSE), | |
65 (int)curbuf->b_p_ts, buf->b_p_vts_array, FALSE); | |
66 #else | |
67 return get_indent_str(ml_get_buf(buf, lnum, FALSE), (int)buf->b_p_ts, FALSE); | |
68 #endif | |
69 } | |
70 #endif | |
71 | |
72 /* | |
73 * count the size (in window cells) of the indent in line "ptr", with | |
74 * 'tabstop' at "ts" | |
75 */ | |
76 int | |
77 get_indent_str( | |
78 char_u *ptr, | |
79 int ts, | |
80 int list) /* if TRUE, count only screen size for tabs */ | |
81 { | |
82 int count = 0; | |
83 | |
84 for ( ; *ptr; ++ptr) | |
85 { | |
86 if (*ptr == TAB) | |
87 { | |
88 if (!list || lcs_tab1) /* count a tab for what it is worth */ | |
89 count += ts - (count % ts); | |
90 else | |
91 /* In list mode, when tab is not set, count screen char width | |
92 * for Tab, displays: ^I */ | |
93 count += ptr2cells(ptr); | |
94 } | |
95 else if (*ptr == ' ') | |
96 ++count; /* count a space for one */ | |
97 else | |
98 break; | |
99 } | |
100 return count; | |
101 } | |
102 | |
103 #ifdef FEAT_VARTABS | |
104 /* | |
105 * Count the size (in window cells) of the indent in line "ptr", using | |
106 * variable tabstops. | |
107 * if "list" is TRUE, count only screen size for tabs. | |
108 */ | |
109 int | |
110 get_indent_str_vtab(char_u *ptr, int ts, int *vts, int list) | |
111 { | |
112 int count = 0; | |
113 | |
114 for ( ; *ptr; ++ptr) | |
115 { | |
116 if (*ptr == TAB) /* count a tab for what it is worth */ | |
117 { | |
118 if (!list || lcs_tab1) | |
119 count += tabstop_padding(count, ts, vts); | |
120 else | |
121 /* In list mode, when tab is not set, count screen char width | |
122 * for Tab, displays: ^I */ | |
123 count += ptr2cells(ptr); | |
124 } | |
125 else if (*ptr == ' ') | |
126 ++count; /* count a space for one */ | |
127 else | |
128 break; | |
129 } | |
130 return count; | |
131 } | |
132 #endif | |
133 | |
134 /* | |
135 * Set the indent of the current line. | |
136 * Leaves the cursor on the first non-blank in the line. | |
137 * Caller must take care of undo. | |
138 * "flags": | |
139 * SIN_CHANGED: call changed_bytes() if the line was changed. | |
140 * SIN_INSERT: insert the indent in front of the line. | |
141 * SIN_UNDO: save line for undo before changing it. | |
142 * Returns TRUE if the line was changed. | |
143 */ | |
144 int | |
145 set_indent( | |
146 int size, /* measured in spaces */ | |
147 int flags) | |
148 { | |
149 char_u *p; | |
150 char_u *newline; | |
151 char_u *oldline; | |
152 char_u *s; | |
153 int todo; | |
154 int ind_len; /* measured in characters */ | |
155 int line_len; | |
156 int doit = FALSE; | |
157 int ind_done = 0; /* measured in spaces */ | |
158 #ifdef FEAT_VARTABS | |
159 int ind_col = 0; | |
160 #endif | |
161 int tab_pad; | |
162 int retval = FALSE; | |
163 int orig_char_len = -1; /* number of initial whitespace chars when | |
164 'et' and 'pi' are both set */ | |
165 | |
166 /* | |
167 * First check if there is anything to do and compute the number of | |
168 * characters needed for the indent. | |
169 */ | |
170 todo = size; | |
171 ind_len = 0; | |
172 p = oldline = ml_get_curline(); | |
173 | |
174 /* Calculate the buffer size for the new indent, and check to see if it | |
175 * isn't already set */ | |
176 | |
177 /* if 'expandtab' isn't set: use TABs; if both 'expandtab' and | |
178 * 'preserveindent' are set count the number of characters at the | |
179 * beginning of the line to be copied */ | |
180 if (!curbuf->b_p_et || (!(flags & SIN_INSERT) && curbuf->b_p_pi)) | |
181 { | |
182 /* If 'preserveindent' is set then reuse as much as possible of | |
183 * the existing indent structure for the new indent */ | |
184 if (!(flags & SIN_INSERT) && curbuf->b_p_pi) | |
185 { | |
186 ind_done = 0; | |
187 | |
188 /* count as many characters as we can use */ | |
189 while (todo > 0 && VIM_ISWHITE(*p)) | |
190 { | |
191 if (*p == TAB) | |
192 { | |
193 #ifdef FEAT_VARTABS | |
194 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, | |
195 curbuf->b_p_vts_array); | |
196 #else | |
197 tab_pad = (int)curbuf->b_p_ts | |
198 - (ind_done % (int)curbuf->b_p_ts); | |
199 #endif | |
200 /* stop if this tab will overshoot the target */ | |
201 if (todo < tab_pad) | |
202 break; | |
203 todo -= tab_pad; | |
204 ++ind_len; | |
205 ind_done += tab_pad; | |
206 } | |
207 else | |
208 { | |
209 --todo; | |
210 ++ind_len; | |
211 ++ind_done; | |
212 } | |
213 ++p; | |
214 } | |
215 | |
216 #ifdef FEAT_VARTABS | |
217 /* These diverge from this point. */ | |
218 ind_col = ind_done; | |
219 #endif | |
220 /* Set initial number of whitespace chars to copy if we are | |
221 * preserving indent but expandtab is set */ | |
222 if (curbuf->b_p_et) | |
223 orig_char_len = ind_len; | |
224 | |
225 /* Fill to next tabstop with a tab, if possible */ | |
226 #ifdef FEAT_VARTABS | |
227 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, | |
228 curbuf->b_p_vts_array); | |
229 #else | |
230 tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts); | |
231 #endif | |
232 if (todo >= tab_pad && orig_char_len == -1) | |
233 { | |
234 doit = TRUE; | |
235 todo -= tab_pad; | |
236 ++ind_len; | |
237 /* ind_done += tab_pad; */ | |
238 #ifdef FEAT_VARTABS | |
239 ind_col += tab_pad; | |
240 #endif | |
241 } | |
242 } | |
243 | |
244 /* count tabs required for indent */ | |
245 #ifdef FEAT_VARTABS | |
246 for (;;) | |
247 { | |
248 tab_pad = tabstop_padding(ind_col, curbuf->b_p_ts, | |
249 curbuf->b_p_vts_array); | |
250 if (todo < tab_pad) | |
251 break; | |
252 if (*p != TAB) | |
253 doit = TRUE; | |
254 else | |
255 ++p; | |
256 todo -= tab_pad; | |
257 ++ind_len; | |
258 ind_col += tab_pad; | |
259 } | |
260 #else | |
261 while (todo >= (int)curbuf->b_p_ts) | |
262 { | |
263 if (*p != TAB) | |
264 doit = TRUE; | |
265 else | |
266 ++p; | |
267 todo -= (int)curbuf->b_p_ts; | |
268 ++ind_len; | |
269 /* ind_done += (int)curbuf->b_p_ts; */ | |
270 } | |
271 #endif | |
272 } | |
273 /* count spaces required for indent */ | |
274 while (todo > 0) | |
275 { | |
276 if (*p != ' ') | |
277 doit = TRUE; | |
278 else | |
279 ++p; | |
280 --todo; | |
281 ++ind_len; | |
282 /* ++ind_done; */ | |
283 } | |
284 | |
285 /* Return if the indent is OK already. */ | |
286 if (!doit && !VIM_ISWHITE(*p) && !(flags & SIN_INSERT)) | |
287 return FALSE; | |
288 | |
289 /* Allocate memory for the new line. */ | |
290 if (flags & SIN_INSERT) | |
291 p = oldline; | |
292 else | |
293 p = skipwhite(p); | |
294 line_len = (int)STRLEN(p) + 1; | |
295 | |
296 /* If 'preserveindent' and 'expandtab' are both set keep the original | |
297 * characters and allocate accordingly. We will fill the rest with spaces | |
298 * after the if (!curbuf->b_p_et) below. */ | |
299 if (orig_char_len != -1) | |
300 { | |
301 newline = alloc(orig_char_len + size - ind_done + line_len); | |
302 if (newline == NULL) | |
303 return FALSE; | |
304 todo = size - ind_done; | |
305 ind_len = orig_char_len + todo; /* Set total length of indent in | |
306 * characters, which may have been | |
307 * undercounted until now */ | |
308 p = oldline; | |
309 s = newline; | |
310 while (orig_char_len > 0) | |
311 { | |
312 *s++ = *p++; | |
313 orig_char_len--; | |
314 } | |
315 | |
316 /* Skip over any additional white space (useful when newindent is less | |
317 * than old) */ | |
318 while (VIM_ISWHITE(*p)) | |
319 ++p; | |
320 | |
321 } | |
322 else | |
323 { | |
324 todo = size; | |
325 newline = alloc(ind_len + line_len); | |
326 if (newline == NULL) | |
327 return FALSE; | |
328 s = newline; | |
329 } | |
330 | |
331 /* Put the characters in the new line. */ | |
332 /* if 'expandtab' isn't set: use TABs */ | |
333 if (!curbuf->b_p_et) | |
334 { | |
335 /* If 'preserveindent' is set then reuse as much as possible of | |
336 * the existing indent structure for the new indent */ | |
337 if (!(flags & SIN_INSERT) && curbuf->b_p_pi) | |
338 { | |
339 p = oldline; | |
340 ind_done = 0; | |
341 | |
342 while (todo > 0 && VIM_ISWHITE(*p)) | |
343 { | |
344 if (*p == TAB) | |
345 { | |
346 #ifdef FEAT_VARTABS | |
347 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, | |
348 curbuf->b_p_vts_array); | |
349 #else | |
350 tab_pad = (int)curbuf->b_p_ts | |
351 - (ind_done % (int)curbuf->b_p_ts); | |
352 #endif | |
353 /* stop if this tab will overshoot the target */ | |
354 if (todo < tab_pad) | |
355 break; | |
356 todo -= tab_pad; | |
357 ind_done += tab_pad; | |
358 } | |
359 else | |
360 { | |
361 --todo; | |
362 ++ind_done; | |
363 } | |
364 *s++ = *p++; | |
365 } | |
366 | |
367 /* Fill to next tabstop with a tab, if possible */ | |
368 #ifdef FEAT_VARTABS | |
369 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, | |
370 curbuf->b_p_vts_array); | |
371 #else | |
372 tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts); | |
373 #endif | |
374 if (todo >= tab_pad) | |
375 { | |
376 *s++ = TAB; | |
377 todo -= tab_pad; | |
378 #ifdef FEAT_VARTABS | |
379 ind_done += tab_pad; | |
380 #endif | |
381 } | |
382 | |
383 p = skipwhite(p); | |
384 } | |
385 | |
386 #ifdef FEAT_VARTABS | |
387 for (;;) | |
388 { | |
389 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, | |
390 curbuf->b_p_vts_array); | |
391 if (todo < tab_pad) | |
392 break; | |
393 *s++ = TAB; | |
394 todo -= tab_pad; | |
395 ind_done += tab_pad; | |
396 } | |
397 #else | |
398 while (todo >= (int)curbuf->b_p_ts) | |
399 { | |
400 *s++ = TAB; | |
401 todo -= (int)curbuf->b_p_ts; | |
402 } | |
403 #endif | |
404 } | |
405 while (todo > 0) | |
406 { | |
407 *s++ = ' '; | |
408 --todo; | |
409 } | |
410 mch_memmove(s, p, (size_t)line_len); | |
411 | |
412 // Replace the line (unless undo fails). | |
413 if (!(flags & SIN_UNDO) || u_savesub(curwin->w_cursor.lnum) == OK) | |
414 { | |
415 ml_replace(curwin->w_cursor.lnum, newline, FALSE); | |
416 if (flags & SIN_CHANGED) | |
417 changed_bytes(curwin->w_cursor.lnum, 0); | |
418 | |
419 // Correct saved cursor position if it is in this line. | |
420 if (saved_cursor.lnum == curwin->w_cursor.lnum) | |
421 { | |
422 if (saved_cursor.col >= (colnr_T)(p - oldline)) | |
423 // cursor was after the indent, adjust for the number of | |
424 // bytes added/removed | |
425 saved_cursor.col += ind_len - (colnr_T)(p - oldline); | |
426 else if (saved_cursor.col >= (colnr_T)(s - newline)) | |
427 // cursor was in the indent, and is now after it, put it back | |
428 // at the start of the indent (replacing spaces with TAB) | |
429 saved_cursor.col = (colnr_T)(s - newline); | |
430 } | |
431 #ifdef FEAT_TEXT_PROP | |
432 { | |
433 int added = ind_len - (colnr_T)(p - oldline); | |
434 | |
435 // When increasing indent this behaves like spaces were inserted at | |
436 // the old indent, when decreasing indent it behaves like spaces | |
437 // were deleted at the new indent. | |
438 adjust_prop_columns(curwin->w_cursor.lnum, | |
439 (colnr_T)(added > 0 ? (p - oldline) : ind_len), added, 0); | |
440 } | |
441 #endif | |
442 retval = TRUE; | |
443 } | |
444 else | |
445 vim_free(newline); | |
446 | |
447 curwin->w_cursor.col = ind_len; | |
448 return retval; | |
449 } | |
450 | |
451 /* | |
452 * Return the indent of the current line after a number. Return -1 if no | |
453 * number was found. Used for 'n' in 'formatoptions': numbered list. | |
454 * Since a pattern is used it can actually handle more than numbers. | |
455 */ | |
456 int | |
457 get_number_indent(linenr_T lnum) | |
458 { | |
459 colnr_T col; | |
460 pos_T pos; | |
461 | |
462 regmatch_T regmatch; | |
463 int lead_len = 0; /* length of comment leader */ | |
464 | |
465 if (lnum > curbuf->b_ml.ml_line_count) | |
466 return -1; | |
467 pos.lnum = 0; | |
468 | |
469 /* In format_lines() (i.e. not insert mode), fo+=q is needed too... */ | |
470 if ((State & INSERT) || has_format_option(FO_Q_COMS)) | |
471 lead_len = get_leader_len(ml_get(lnum), NULL, FALSE, TRUE); | |
472 | |
473 regmatch.regprog = vim_regcomp(curbuf->b_p_flp, RE_MAGIC); | |
474 if (regmatch.regprog != NULL) | |
475 { | |
476 regmatch.rm_ic = FALSE; | |
477 | |
478 /* vim_regexec() expects a pointer to a line. This lets us | |
479 * start matching for the flp beyond any comment leader... */ | |
480 if (vim_regexec(®match, ml_get(lnum) + lead_len, (colnr_T)0)) | |
481 { | |
482 pos.lnum = lnum; | |
483 pos.col = (colnr_T)(*regmatch.endp - ml_get(lnum)); | |
484 pos.coladd = 0; | |
485 } | |
486 vim_regfree(regmatch.regprog); | |
487 } | |
488 | |
489 if (pos.lnum == 0 || *ml_get_pos(&pos) == NUL) | |
490 return -1; | |
491 getvcol(curwin, &pos, &col, NULL, NULL); | |
492 return (int)col; | |
493 } | |
494 | |
495 #if defined(FEAT_LINEBREAK) || defined(PROTO) | |
496 /* | |
497 * Return appropriate space number for breakindent, taking influencing | |
498 * parameters into account. Window must be specified, since it is not | |
499 * necessarily always the current one. | |
500 */ | |
501 int | |
502 get_breakindent_win( | |
503 win_T *wp, | |
504 char_u *line) /* start of the line */ | |
505 { | |
506 static int prev_indent = 0; /* cached indent value */ | |
507 static long prev_ts = 0L; /* cached tabstop value */ | |
508 static char_u *prev_line = NULL; /* cached pointer to line */ | |
509 static varnumber_T prev_tick = 0; /* changedtick of cached value */ | |
510 #ifdef FEAT_VARTABS | |
511 static int *prev_vts = NULL; /* cached vartabs values */ | |
512 #endif | |
513 int bri = 0; | |
514 /* window width minus window margin space, i.e. what rests for text */ | |
515 const int eff_wwidth = wp->w_width | |
516 - ((wp->w_p_nu || wp->w_p_rnu) | |
517 && (vim_strchr(p_cpo, CPO_NUMCOL) == NULL) | |
518 ? number_width(wp) + 1 : 0); | |
519 | |
520 /* used cached indent, unless pointer or 'tabstop' changed */ | |
521 if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts | |
522 || prev_tick != CHANGEDTICK(wp->w_buffer) | |
523 #ifdef FEAT_VARTABS | |
524 || prev_vts != wp->w_buffer->b_p_vts_array | |
525 #endif | |
526 ) | |
527 { | |
528 prev_line = line; | |
529 prev_ts = wp->w_buffer->b_p_ts; | |
530 prev_tick = CHANGEDTICK(wp->w_buffer); | |
531 #ifdef FEAT_VARTABS | |
532 prev_vts = wp->w_buffer->b_p_vts_array; | |
533 prev_indent = get_indent_str_vtab(line, | |
534 (int)wp->w_buffer->b_p_ts, | |
535 wp->w_buffer->b_p_vts_array, wp->w_p_list); | |
536 #else | |
537 prev_indent = get_indent_str(line, | |
538 (int)wp->w_buffer->b_p_ts, wp->w_p_list); | |
539 #endif | |
540 } | |
541 bri = prev_indent + wp->w_p_brishift; | |
542 | |
543 /* indent minus the length of the showbreak string */ | |
544 if (wp->w_p_brisbr) | |
545 bri -= vim_strsize(p_sbr); | |
546 | |
547 /* Add offset for number column, if 'n' is in 'cpoptions' */ | |
548 bri += win_col_off2(wp); | |
549 | |
550 /* never indent past left window margin */ | |
551 if (bri < 0) | |
552 bri = 0; | |
553 /* always leave at least bri_min characters on the left, | |
554 * if text width is sufficient */ | |
555 else if (bri > eff_wwidth - wp->w_p_brimin) | |
556 bri = (eff_wwidth - wp->w_p_brimin < 0) | |
557 ? 0 : eff_wwidth - wp->w_p_brimin; | |
558 | |
559 return bri; | |
560 } | |
561 #endif | |
562 | 26 |
563 /* | 27 /* |
564 * get_leader_len() returns the length in bytes of the prefix of the given | 28 * get_leader_len() returns the length in bytes of the prefix of the given |
565 * string which introduces a comment. If this string is not a comment then | 29 * string which introduces a comment. If this string is not a comment then |
566 * 0 is returned. | 30 * 0 is returned. |
1071 void | 535 void |
1072 pchar_cursor(int c) | 536 pchar_cursor(int c) |
1073 { | 537 { |
1074 *(ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE) | 538 *(ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE) |
1075 + curwin->w_cursor.col) = c; | 539 + curwin->w_cursor.col) = c; |
1076 } | |
1077 | |
1078 /* | |
1079 * When extra == 0: Return TRUE if the cursor is before or on the first | |
1080 * non-blank in the line. | |
1081 * When extra == 1: Return TRUE if the cursor is before the first non-blank in | |
1082 * the line. | |
1083 */ | |
1084 int | |
1085 inindent(int extra) | |
1086 { | |
1087 char_u *ptr; | |
1088 colnr_T col; | |
1089 | |
1090 for (col = 0, ptr = ml_get_curline(); VIM_ISWHITE(*ptr); ++col) | |
1091 ++ptr; | |
1092 if (col >= curwin->w_cursor.col + extra) | |
1093 return TRUE; | |
1094 else | |
1095 return FALSE; | |
1096 } | 540 } |
1097 | 541 |
1098 /* | 542 /* |
1099 * Skip to next part of an option argument: Skip space and comma. | 543 * Skip to next part of an option argument: Skip space and comma. |
1100 */ | 544 */ |