Mercurial > vim
comparison src/fold.c @ 18779:8f05b3cf8557 v8.1.2379
patch 8.1.2379: using old C style comments
Commit: https://github.com/vim/vim/commit/217e1b8359447f5550dcb0d1ee43380a90c253c5
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Dec 1 21:41:28 2019 +0100
patch 8.1.2379: using old C style comments
Problem: Using old C style comments.
Solution: Use // comments where appropriate.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 01 Dec 2019 21:45:04 +0100 |
parents | e0ec4cd7a865 |
children | 3af71cbcfdbe |
comparison
equal
deleted
inserted
replaced
18778:2182f82b04e4 | 18779:8f05b3cf8557 |
---|---|
14 | 14 |
15 #include "vim.h" | 15 #include "vim.h" |
16 | 16 |
17 #if defined(FEAT_FOLDING) || defined(PROTO) | 17 #if defined(FEAT_FOLDING) || defined(PROTO) |
18 | 18 |
19 /* local declarations. {{{1 */ | 19 // local declarations. {{{1 |
20 /* typedef fold_T {{{2 */ | 20 // typedef fold_T {{{2 |
21 /* | 21 /* |
22 * The toplevel folds for each window are stored in the w_folds growarray. | 22 * The toplevel folds for each window are stored in the w_folds growarray. |
23 * Each toplevel fold can contain an array of second level folds in the | 23 * Each toplevel fold can contain an array of second level folds in the |
24 * fd_nested growarray. | 24 * fd_nested growarray. |
25 * The info stored in both growarrays is the same: An array of fold_T. | 25 * The info stored in both growarrays is the same: An array of fold_T. |
26 */ | 26 */ |
27 typedef struct | 27 typedef struct |
28 { | 28 { |
29 linenr_T fd_top; /* first line of fold; for nested fold | 29 linenr_T fd_top; // first line of fold; for nested fold |
30 * relative to parent */ | 30 // relative to parent |
31 linenr_T fd_len; /* number of lines in the fold */ | 31 linenr_T fd_len; // number of lines in the fold |
32 garray_T fd_nested; /* array of nested folds */ | 32 garray_T fd_nested; // array of nested folds |
33 char fd_flags; /* see below */ | 33 char fd_flags; // see below |
34 char fd_small; /* TRUE, FALSE or MAYBE: fold smaller than | 34 char fd_small; // TRUE, FALSE or MAYBE: fold smaller than |
35 'foldminlines'; MAYBE applies to nested | 35 // 'foldminlines'; MAYBE applies to nested |
36 folds too */ | 36 // folds too |
37 } fold_T; | 37 } fold_T; |
38 | 38 |
39 #define FD_OPEN 0 /* fold is open (nested ones can be closed) */ | 39 #define FD_OPEN 0 // fold is open (nested ones can be closed) |
40 #define FD_CLOSED 1 /* fold is closed */ | 40 #define FD_CLOSED 1 // fold is closed |
41 #define FD_LEVEL 2 /* depends on 'foldlevel' (nested folds too) */ | 41 #define FD_LEVEL 2 // depends on 'foldlevel' (nested folds too) |
42 | 42 |
43 #define MAX_LEVEL 20 /* maximum fold depth */ | 43 #define MAX_LEVEL 20 // maximum fold depth |
44 | 44 |
45 /* static functions {{{2 */ | 45 // static functions {{{2 |
46 static void newFoldLevelWin(win_T *wp); | 46 static void newFoldLevelWin(win_T *wp); |
47 static int checkCloseRec(garray_T *gap, linenr_T lnum, int level); | 47 static int checkCloseRec(garray_T *gap, linenr_T lnum, int level); |
48 static int foldFind(garray_T *gap, linenr_T lnum, fold_T **fpp); | 48 static int foldFind(garray_T *gap, linenr_T lnum, fold_T **fpp); |
49 static int foldLevelWin(win_T *wp, linenr_T lnum); | 49 static int foldLevelWin(win_T *wp, linenr_T lnum); |
50 static void checkupdate(win_T *wp); | 50 static void checkupdate(win_T *wp); |
82 * level is not available. | 82 * level is not available. |
83 */ | 83 */ |
84 static linenr_T prev_lnum = 0; | 84 static linenr_T prev_lnum = 0; |
85 static int prev_lnum_lvl = -1; | 85 static int prev_lnum_lvl = -1; |
86 | 86 |
87 /* Flags used for "done" argument of setManualFold. */ | 87 // Flags used for "done" argument of setManualFold. |
88 #define DONE_NOTHING 0 | 88 #define DONE_NOTHING 0 |
89 #define DONE_ACTION 1 /* did close or open a fold */ | 89 #define DONE_ACTION 1 // did close or open a fold |
90 #define DONE_FOLD 2 /* did find a fold */ | 90 #define DONE_FOLD 2 // did find a fold |
91 | 91 |
92 static int foldstartmarkerlen; | 92 static int foldstartmarkerlen; |
93 static char_u *foldendmarker; | 93 static char_u *foldendmarker; |
94 static int foldendmarkerlen; | 94 static int foldendmarkerlen; |
95 | 95 |
96 /* Exported folding functions. {{{1 */ | 96 // Exported folding functions. {{{1 |
97 /* copyFoldingState() {{{2 */ | 97 // copyFoldingState() {{{2 |
98 | 98 |
99 /* | 99 /* |
100 * Copy that folding state from window "wp_from" to window "wp_to". | 100 * Copy that folding state from window "wp_from" to window "wp_to". |
101 */ | 101 */ |
102 void | 102 void |
105 wp_to->w_fold_manual = wp_from->w_fold_manual; | 105 wp_to->w_fold_manual = wp_from->w_fold_manual; |
106 wp_to->w_foldinvalid = wp_from->w_foldinvalid; | 106 wp_to->w_foldinvalid = wp_from->w_foldinvalid; |
107 cloneFoldGrowArray(&wp_from->w_folds, &wp_to->w_folds); | 107 cloneFoldGrowArray(&wp_from->w_folds, &wp_to->w_folds); |
108 } | 108 } |
109 | 109 |
110 /* hasAnyFolding() {{{2 */ | 110 // hasAnyFolding() {{{2 |
111 /* | 111 /* |
112 * Return TRUE if there may be folded lines in the current window. | 112 * Return TRUE if there may be folded lines in the current window. |
113 */ | 113 */ |
114 int | 114 int |
115 hasAnyFolding(win_T *win) | 115 hasAnyFolding(win_T *win) |
116 { | 116 { |
117 /* very simple now, but can become more complex later */ | 117 // very simple now, but can become more complex later |
118 return (win->w_p_fen | 118 return (win->w_p_fen |
119 && (!foldmethodIsManual(win) || win->w_folds.ga_len > 0)); | 119 && (!foldmethodIsManual(win) || win->w_folds.ga_len > 0)); |
120 } | 120 } |
121 | 121 |
122 /* hasFolding() {{{2 */ | 122 // hasFolding() {{{2 |
123 /* | 123 /* |
124 * Return TRUE if line "lnum" in the current window is part of a closed | 124 * Return TRUE if line "lnum" in the current window is part of a closed |
125 * fold. | 125 * fold. |
126 * When returning TRUE, *firstp and *lastp are set to the first and last | 126 * When returning TRUE, *firstp and *lastp are set to the first and last |
127 * lnum of the sequence of folded lines (skipped when NULL). | 127 * lnum of the sequence of folded lines (skipped when NULL). |
130 hasFolding(linenr_T lnum, linenr_T *firstp, linenr_T *lastp) | 130 hasFolding(linenr_T lnum, linenr_T *firstp, linenr_T *lastp) |
131 { | 131 { |
132 return hasFoldingWin(curwin, lnum, firstp, lastp, TRUE, NULL); | 132 return hasFoldingWin(curwin, lnum, firstp, lastp, TRUE, NULL); |
133 } | 133 } |
134 | 134 |
135 /* hasFoldingWin() {{{2 */ | 135 // hasFoldingWin() {{{2 |
136 int | 136 int |
137 hasFoldingWin( | 137 hasFoldingWin( |
138 win_T *win, | 138 win_T *win, |
139 linenr_T lnum, | 139 linenr_T lnum, |
140 linenr_T *firstp, | 140 linenr_T *firstp, |
141 linenr_T *lastp, | 141 linenr_T *lastp, |
142 int cache, /* when TRUE: use cached values of window */ | 142 int cache, // when TRUE: use cached values of window |
143 foldinfo_T *infop) /* where to store fold info */ | 143 foldinfo_T *infop) // where to store fold info |
144 { | 144 { |
145 int had_folded = FALSE; | 145 int had_folded = FALSE; |
146 linenr_T first = 0; | 146 linenr_T first = 0; |
147 linenr_T last = 0; | 147 linenr_T last = 0; |
148 linenr_T lnum_rel = lnum; | 148 linenr_T lnum_rel = lnum; |
190 for (;;) | 190 for (;;) |
191 { | 191 { |
192 if (!foldFind(gap, lnum_rel, &fp)) | 192 if (!foldFind(gap, lnum_rel, &fp)) |
193 break; | 193 break; |
194 | 194 |
195 /* Remember lowest level of fold that starts in "lnum". */ | 195 // Remember lowest level of fold that starts in "lnum". |
196 if (lnum_rel == fp->fd_top && low_level == 0) | 196 if (lnum_rel == fp->fd_top && low_level == 0) |
197 low_level = level + 1; | 197 low_level = level + 1; |
198 | 198 |
199 first += fp->fd_top; | 199 first += fp->fd_top; |
200 last += fp->fd_top; | 200 last += fp->fd_top; |
201 | 201 |
202 /* is this fold closed? */ | 202 // is this fold closed? |
203 had_folded = check_closed(win, fp, &use_level, level, | 203 had_folded = check_closed(win, fp, &use_level, level, |
204 &maybe_small, lnum - lnum_rel); | 204 &maybe_small, lnum - lnum_rel); |
205 if (had_folded) | 205 if (had_folded) |
206 { | 206 { |
207 /* Fold closed: Set last and quit loop. */ | 207 // Fold closed: Set last and quit loop. |
208 last += fp->fd_len - 1; | 208 last += fp->fd_len - 1; |
209 break; | 209 break; |
210 } | 210 } |
211 | 211 |
212 /* Fold found, but it's open: Check nested folds. Line number is | 212 // Fold found, but it's open: Check nested folds. Line number is |
213 * relative to containing fold. */ | 213 // relative to containing fold. |
214 gap = &fp->fd_nested; | 214 gap = &fp->fd_nested; |
215 lnum_rel -= fp->fd_top; | 215 lnum_rel -= fp->fd_top; |
216 ++level; | 216 ++level; |
217 } | 217 } |
218 } | 218 } |
241 infop->fi_low_level = low_level == 0 ? level + 1 : low_level; | 241 infop->fi_low_level = low_level == 0 ? level + 1 : low_level; |
242 } | 242 } |
243 return TRUE; | 243 return TRUE; |
244 } | 244 } |
245 | 245 |
246 /* foldLevel() {{{2 */ | 246 // foldLevel() {{{2 |
247 #ifdef FEAT_EVAL | 247 #ifdef FEAT_EVAL |
248 /* | 248 /* |
249 * Return fold level at line number "lnum" in the current window. | 249 * Return fold level at line number "lnum" in the current window. |
250 */ | 250 */ |
251 static int | 251 static int |
252 foldLevel(linenr_T lnum) | 252 foldLevel(linenr_T lnum) |
253 { | 253 { |
254 /* While updating the folds lines between invalid_top and invalid_bot have | 254 // While updating the folds lines between invalid_top and invalid_bot have |
255 * an undefined fold level. Otherwise update the folds first. */ | 255 // an undefined fold level. Otherwise update the folds first. |
256 if (invalid_top == (linenr_T)0) | 256 if (invalid_top == (linenr_T)0) |
257 checkupdate(curwin); | 257 checkupdate(curwin); |
258 else if (lnum == prev_lnum && prev_lnum_lvl >= 0) | 258 else if (lnum == prev_lnum && prev_lnum_lvl >= 0) |
259 return prev_lnum_lvl; | 259 return prev_lnum_lvl; |
260 else if (lnum >= invalid_top && lnum <= invalid_bot) | 260 else if (lnum >= invalid_top && lnum <= invalid_bot) |
261 return -1; | 261 return -1; |
262 | 262 |
263 /* Return quickly when there is no folding at all in this window. */ | 263 // Return quickly when there is no folding at all in this window. |
264 if (!hasAnyFolding(curwin)) | 264 if (!hasAnyFolding(curwin)) |
265 return 0; | 265 return 0; |
266 | 266 |
267 return foldLevelWin(curwin, lnum); | 267 return foldLevelWin(curwin, lnum); |
268 } | 268 } |
269 #endif | 269 #endif |
270 | 270 |
271 /* lineFolded() {{{2 */ | 271 // lineFolded() {{{2 |
272 /* | 272 /* |
273 * Low level function to check if a line is folded. Doesn't use any caching. | 273 * Low level function to check if a line is folded. Doesn't use any caching. |
274 * Return TRUE if line is folded. | 274 * Return TRUE if line is folded. |
275 * Return FALSE if line is not folded. | 275 * Return FALSE if line is not folded. |
276 * Return MAYBE if the line is folded when next to a folded line. | 276 * Return MAYBE if the line is folded when next to a folded line. |
279 lineFolded(win_T *win, linenr_T lnum) | 279 lineFolded(win_T *win, linenr_T lnum) |
280 { | 280 { |
281 return foldedCount(win, lnum, NULL) != 0; | 281 return foldedCount(win, lnum, NULL) != 0; |
282 } | 282 } |
283 | 283 |
284 /* foldedCount() {{{2 */ | 284 // foldedCount() {{{2 |
285 /* | 285 /* |
286 * Count the number of lines that are folded at line number "lnum". | 286 * Count the number of lines that are folded at line number "lnum". |
287 * Normally "lnum" is the first line of a possible fold, and the returned | 287 * Normally "lnum" is the first line of a possible fold, and the returned |
288 * number is the number of lines in the fold. | 288 * number is the number of lines in the fold. |
289 * Doesn't use caching from the displayed window. | 289 * Doesn't use caching from the displayed window. |
298 if (hasFoldingWin(win, lnum, NULL, &last, FALSE, infop)) | 298 if (hasFoldingWin(win, lnum, NULL, &last, FALSE, infop)) |
299 return (long)(last - lnum + 1); | 299 return (long)(last - lnum + 1); |
300 return 0; | 300 return 0; |
301 } | 301 } |
302 | 302 |
303 /* foldmethodIsManual() {{{2 */ | 303 // foldmethodIsManual() {{{2 |
304 /* | 304 /* |
305 * Return TRUE if 'foldmethod' is "manual" | 305 * Return TRUE if 'foldmethod' is "manual" |
306 */ | 306 */ |
307 int | 307 int |
308 foldmethodIsManual(win_T *wp) | 308 foldmethodIsManual(win_T *wp) |
309 { | 309 { |
310 return (wp->w_p_fdm[3] == 'u'); | 310 return (wp->w_p_fdm[3] == 'u'); |
311 } | 311 } |
312 | 312 |
313 /* foldmethodIsIndent() {{{2 */ | 313 // foldmethodIsIndent() {{{2 |
314 /* | 314 /* |
315 * Return TRUE if 'foldmethod' is "indent" | 315 * Return TRUE if 'foldmethod' is "indent" |
316 */ | 316 */ |
317 int | 317 int |
318 foldmethodIsIndent(win_T *wp) | 318 foldmethodIsIndent(win_T *wp) |
319 { | 319 { |
320 return (wp->w_p_fdm[0] == 'i'); | 320 return (wp->w_p_fdm[0] == 'i'); |
321 } | 321 } |
322 | 322 |
323 /* foldmethodIsExpr() {{{2 */ | 323 // foldmethodIsExpr() {{{2 |
324 /* | 324 /* |
325 * Return TRUE if 'foldmethod' is "expr" | 325 * Return TRUE if 'foldmethod' is "expr" |
326 */ | 326 */ |
327 int | 327 int |
328 foldmethodIsExpr(win_T *wp) | 328 foldmethodIsExpr(win_T *wp) |
329 { | 329 { |
330 return (wp->w_p_fdm[1] == 'x'); | 330 return (wp->w_p_fdm[1] == 'x'); |
331 } | 331 } |
332 | 332 |
333 /* foldmethodIsMarker() {{{2 */ | 333 // foldmethodIsMarker() {{{2 |
334 /* | 334 /* |
335 * Return TRUE if 'foldmethod' is "marker" | 335 * Return TRUE if 'foldmethod' is "marker" |
336 */ | 336 */ |
337 int | 337 int |
338 foldmethodIsMarker(win_T *wp) | 338 foldmethodIsMarker(win_T *wp) |
339 { | 339 { |
340 return (wp->w_p_fdm[2] == 'r'); | 340 return (wp->w_p_fdm[2] == 'r'); |
341 } | 341 } |
342 | 342 |
343 /* foldmethodIsSyntax() {{{2 */ | 343 // foldmethodIsSyntax() {{{2 |
344 /* | 344 /* |
345 * Return TRUE if 'foldmethod' is "syntax" | 345 * Return TRUE if 'foldmethod' is "syntax" |
346 */ | 346 */ |
347 int | 347 int |
348 foldmethodIsSyntax(win_T *wp) | 348 foldmethodIsSyntax(win_T *wp) |
349 { | 349 { |
350 return (wp->w_p_fdm[0] == 's'); | 350 return (wp->w_p_fdm[0] == 's'); |
351 } | 351 } |
352 | 352 |
353 /* foldmethodIsDiff() {{{2 */ | 353 // foldmethodIsDiff() {{{2 |
354 /* | 354 /* |
355 * Return TRUE if 'foldmethod' is "diff" | 355 * Return TRUE if 'foldmethod' is "diff" |
356 */ | 356 */ |
357 int | 357 int |
358 foldmethodIsDiff(win_T *wp) | 358 foldmethodIsDiff(win_T *wp) |
359 { | 359 { |
360 return (wp->w_p_fdm[0] == 'd'); | 360 return (wp->w_p_fdm[0] == 'd'); |
361 } | 361 } |
362 | 362 |
363 /* closeFold() {{{2 */ | 363 // closeFold() {{{2 |
364 /* | 364 /* |
365 * Close fold for current window at line "lnum". | 365 * Close fold for current window at line "lnum". |
366 * Repeat "count" times. | 366 * Repeat "count" times. |
367 */ | 367 */ |
368 void | 368 void |
369 closeFold(linenr_T lnum, long count) | 369 closeFold(linenr_T lnum, long count) |
370 { | 370 { |
371 setFoldRepeat(lnum, count, FALSE); | 371 setFoldRepeat(lnum, count, FALSE); |
372 } | 372 } |
373 | 373 |
374 /* closeFoldRecurse() {{{2 */ | 374 // closeFoldRecurse() {{{2 |
375 /* | 375 /* |
376 * Close fold for current window at line "lnum" recursively. | 376 * Close fold for current window at line "lnum" recursively. |
377 */ | 377 */ |
378 void | 378 void |
379 closeFoldRecurse(linenr_T lnum) | 379 closeFoldRecurse(linenr_T lnum) |
380 { | 380 { |
381 (void)setManualFold(lnum, FALSE, TRUE, NULL); | 381 (void)setManualFold(lnum, FALSE, TRUE, NULL); |
382 } | 382 } |
383 | 383 |
384 /* opFoldRange() {{{2 */ | 384 // opFoldRange() {{{2 |
385 /* | 385 /* |
386 * Open or Close folds for current window in lines "first" to "last". | 386 * Open or Close folds for current window in lines "first" to "last". |
387 * Used for "zo", "zO", "zc" and "zC" in Visual mode. | 387 * Used for "zo", "zO", "zc" and "zC" in Visual mode. |
388 */ | 388 */ |
389 void | 389 void |
390 opFoldRange( | 390 opFoldRange( |
391 linenr_T first, | 391 linenr_T first, |
392 linenr_T last, | 392 linenr_T last, |
393 int opening, /* TRUE to open, FALSE to close */ | 393 int opening, // TRUE to open, FALSE to close |
394 int recurse, /* TRUE to do it recursively */ | 394 int recurse, // TRUE to do it recursively |
395 int had_visual) /* TRUE when Visual selection used */ | 395 int had_visual) // TRUE when Visual selection used |
396 { | 396 { |
397 int done = DONE_NOTHING; /* avoid error messages */ | 397 int done = DONE_NOTHING; // avoid error messages |
398 linenr_T lnum; | 398 linenr_T lnum; |
399 linenr_T lnum_next; | 399 linenr_T lnum_next; |
400 | 400 |
401 for (lnum = first; lnum <= last; lnum = lnum_next + 1) | 401 for (lnum = first; lnum <= last; lnum = lnum_next + 1) |
402 { | 402 { |
403 lnum_next = lnum; | 403 lnum_next = lnum; |
404 /* Opening one level only: next fold to open is after the one going to | 404 // Opening one level only: next fold to open is after the one going to |
405 * be opened. */ | 405 // be opened. |
406 if (opening && !recurse) | 406 if (opening && !recurse) |
407 (void)hasFolding(lnum, NULL, &lnum_next); | 407 (void)hasFolding(lnum, NULL, &lnum_next); |
408 (void)setManualFold(lnum, opening, recurse, &done); | 408 (void)setManualFold(lnum, opening, recurse, &done); |
409 /* Closing one level only: next line to close a fold is after just | 409 // Closing one level only: next line to close a fold is after just |
410 * closed fold. */ | 410 // closed fold. |
411 if (!opening && !recurse) | 411 if (!opening && !recurse) |
412 (void)hasFolding(lnum, NULL, &lnum_next); | 412 (void)hasFolding(lnum, NULL, &lnum_next); |
413 } | 413 } |
414 if (done == DONE_NOTHING) | 414 if (done == DONE_NOTHING) |
415 emsg(_(e_nofold)); | 415 emsg(_(e_nofold)); |
416 /* Force a redraw to remove the Visual highlighting. */ | 416 // Force a redraw to remove the Visual highlighting. |
417 if (had_visual) | 417 if (had_visual) |
418 redraw_curbuf_later(INVERTED); | 418 redraw_curbuf_later(INVERTED); |
419 } | 419 } |
420 | 420 |
421 /* openFold() {{{2 */ | 421 // openFold() {{{2 |
422 /* | 422 /* |
423 * Open fold for current window at line "lnum". | 423 * Open fold for current window at line "lnum". |
424 * Repeat "count" times. | 424 * Repeat "count" times. |
425 */ | 425 */ |
426 void | 426 void |
427 openFold(linenr_T lnum, long count) | 427 openFold(linenr_T lnum, long count) |
428 { | 428 { |
429 setFoldRepeat(lnum, count, TRUE); | 429 setFoldRepeat(lnum, count, TRUE); |
430 } | 430 } |
431 | 431 |
432 /* openFoldRecurse() {{{2 */ | 432 // openFoldRecurse() {{{2 |
433 /* | 433 /* |
434 * Open fold for current window at line "lnum" recursively. | 434 * Open fold for current window at line "lnum" recursively. |
435 */ | 435 */ |
436 void | 436 void |
437 openFoldRecurse(linenr_T lnum) | 437 openFoldRecurse(linenr_T lnum) |
438 { | 438 { |
439 (void)setManualFold(lnum, TRUE, TRUE, NULL); | 439 (void)setManualFold(lnum, TRUE, TRUE, NULL); |
440 } | 440 } |
441 | 441 |
442 /* foldOpenCursor() {{{2 */ | 442 // foldOpenCursor() {{{2 |
443 /* | 443 /* |
444 * Open folds until the cursor line is not in a closed fold. | 444 * Open folds until the cursor line is not in a closed fold. |
445 */ | 445 */ |
446 void | 446 void |
447 foldOpenCursor(void) | 447 foldOpenCursor(void) |
457 if (!(done & DONE_ACTION)) | 457 if (!(done & DONE_ACTION)) |
458 break; | 458 break; |
459 } | 459 } |
460 } | 460 } |
461 | 461 |
462 /* newFoldLevel() {{{2 */ | 462 // newFoldLevel() {{{2 |
463 /* | 463 /* |
464 * Set new foldlevel for current window. | 464 * Set new foldlevel for current window. |
465 */ | 465 */ |
466 void | 466 void |
467 newFoldLevel(void) | 467 newFoldLevel(void) |
495 int i; | 495 int i; |
496 | 496 |
497 checkupdate(wp); | 497 checkupdate(wp); |
498 if (wp->w_fold_manual) | 498 if (wp->w_fold_manual) |
499 { | 499 { |
500 /* Set all flags for the first level of folds to FD_LEVEL. Following | 500 // Set all flags for the first level of folds to FD_LEVEL. Following |
501 * manual open/close will then change the flags to FD_OPEN or | 501 // manual open/close will then change the flags to FD_OPEN or |
502 * FD_CLOSED for those folds that don't use 'foldlevel'. */ | 502 // FD_CLOSED for those folds that don't use 'foldlevel'. |
503 fp = (fold_T *)wp->w_folds.ga_data; | 503 fp = (fold_T *)wp->w_folds.ga_data; |
504 for (i = 0; i < wp->w_folds.ga_len; ++i) | 504 for (i = 0; i < wp->w_folds.ga_len; ++i) |
505 fp[i].fd_flags = FD_LEVEL; | 505 fp[i].fd_flags = FD_LEVEL; |
506 wp->w_fold_manual = FALSE; | 506 wp->w_fold_manual = FALSE; |
507 } | 507 } |
508 changed_window_setting_win(wp); | 508 changed_window_setting_win(wp); |
509 } | 509 } |
510 | 510 |
511 /* foldCheckClose() {{{2 */ | 511 // foldCheckClose() {{{2 |
512 /* | 512 /* |
513 * Apply 'foldlevel' to all folds that don't contain the cursor. | 513 * Apply 'foldlevel' to all folds that don't contain the cursor. |
514 */ | 514 */ |
515 void | 515 void |
516 foldCheckClose(void) | 516 foldCheckClose(void) |
517 { | 517 { |
518 if (*p_fcl != NUL) /* can only be "all" right now */ | 518 if (*p_fcl != NUL) // can only be "all" right now |
519 { | 519 { |
520 checkupdate(curwin); | 520 checkupdate(curwin); |
521 if (checkCloseRec(&curwin->w_folds, curwin->w_cursor.lnum, | 521 if (checkCloseRec(&curwin->w_folds, curwin->w_cursor.lnum, |
522 (int)curwin->w_p_fdl)) | 522 (int)curwin->w_p_fdl)) |
523 changed_window_setting(); | 523 changed_window_setting(); |
524 } | 524 } |
525 } | 525 } |
526 | 526 |
527 /* checkCloseRec() {{{2 */ | 527 // checkCloseRec() {{{2 |
528 static int | 528 static int |
529 checkCloseRec(garray_T *gap, linenr_T lnum, int level) | 529 checkCloseRec(garray_T *gap, linenr_T lnum, int level) |
530 { | 530 { |
531 fold_T *fp; | 531 fold_T *fp; |
532 int retval = FALSE; | 532 int retval = FALSE; |
533 int i; | 533 int i; |
534 | 534 |
535 fp = (fold_T *)gap->ga_data; | 535 fp = (fold_T *)gap->ga_data; |
536 for (i = 0; i < gap->ga_len; ++i) | 536 for (i = 0; i < gap->ga_len; ++i) |
537 { | 537 { |
538 /* Only manually opened folds may need to be closed. */ | 538 // Only manually opened folds may need to be closed. |
539 if (fp[i].fd_flags == FD_OPEN) | 539 if (fp[i].fd_flags == FD_OPEN) |
540 { | 540 { |
541 if (level <= 0 && (lnum < fp[i].fd_top | 541 if (level <= 0 && (lnum < fp[i].fd_top |
542 || lnum >= fp[i].fd_top + fp[i].fd_len)) | 542 || lnum >= fp[i].fd_top + fp[i].fd_len)) |
543 { | 543 { |
550 } | 550 } |
551 } | 551 } |
552 return retval; | 552 return retval; |
553 } | 553 } |
554 | 554 |
555 /* foldCreateAllowed() {{{2 */ | 555 // foldCreateAllowed() {{{2 |
556 /* | 556 /* |
557 * Return TRUE if it's allowed to manually create or delete a fold. | 557 * Return TRUE if it's allowed to manually create or delete a fold. |
558 * Give an error message and return FALSE if not. | 558 * Give an error message and return FALSE if not. |
559 */ | 559 */ |
560 int | 560 int |
567 else | 567 else |
568 emsg(_("E351: Cannot delete fold with current 'foldmethod'")); | 568 emsg(_("E351: Cannot delete fold with current 'foldmethod'")); |
569 return FALSE; | 569 return FALSE; |
570 } | 570 } |
571 | 571 |
572 /* foldCreate() {{{2 */ | 572 // foldCreate() {{{2 |
573 /* | 573 /* |
574 * Create a fold from line "start" to line "end" (inclusive) in the current | 574 * Create a fold from line "start" to line "end" (inclusive) in the current |
575 * window. | 575 * window. |
576 */ | 576 */ |
577 void | 577 void |
588 linenr_T start_rel = start; | 588 linenr_T start_rel = start; |
589 linenr_T end_rel = end; | 589 linenr_T end_rel = end; |
590 | 590 |
591 if (start > end) | 591 if (start > end) |
592 { | 592 { |
593 /* reverse the range */ | 593 // reverse the range |
594 end = start_rel; | 594 end = start_rel; |
595 start = end_rel; | 595 start = end_rel; |
596 start_rel = start; | 596 start_rel = start; |
597 end_rel = end; | 597 end_rel = end; |
598 } | 598 } |
599 | 599 |
600 /* When 'foldmethod' is "marker" add markers, which creates the folds. */ | 600 // When 'foldmethod' is "marker" add markers, which creates the folds. |
601 if (foldmethodIsMarker(curwin)) | 601 if (foldmethodIsMarker(curwin)) |
602 { | 602 { |
603 foldCreateMarkers(start, end); | 603 foldCreateMarkers(start, end); |
604 return; | 604 return; |
605 } | 605 } |
606 | 606 |
607 checkupdate(curwin); | 607 checkupdate(curwin); |
608 | 608 |
609 /* Find the place to insert the new fold. */ | 609 // Find the place to insert the new fold. |
610 gap = &curwin->w_folds; | 610 gap = &curwin->w_folds; |
611 for (;;) | 611 for (;;) |
612 { | 612 { |
613 if (!foldFind(gap, start_rel, &fp)) | 613 if (!foldFind(gap, start_rel, &fp)) |
614 break; | 614 break; |
615 if (fp->fd_top + fp->fd_len > end_rel) | 615 if (fp->fd_top + fp->fd_len > end_rel) |
616 { | 616 { |
617 /* New fold is completely inside this fold: Go one level deeper. */ | 617 // New fold is completely inside this fold: Go one level deeper. |
618 gap = &fp->fd_nested; | 618 gap = &fp->fd_nested; |
619 start_rel -= fp->fd_top; | 619 start_rel -= fp->fd_top; |
620 end_rel -= fp->fd_top; | 620 end_rel -= fp->fd_top; |
621 if (use_level || fp->fd_flags == FD_LEVEL) | 621 if (use_level || fp->fd_flags == FD_LEVEL) |
622 { | 622 { |
628 closed = TRUE; | 628 closed = TRUE; |
629 ++level; | 629 ++level; |
630 } | 630 } |
631 else | 631 else |
632 { | 632 { |
633 /* This fold and new fold overlap: Insert here and move some folds | 633 // This fold and new fold overlap: Insert here and move some folds |
634 * inside the new fold. */ | 634 // inside the new fold. |
635 break; | 635 break; |
636 } | 636 } |
637 } | 637 } |
638 | 638 |
639 i = (int)(fp - (fold_T *)gap->ga_data); | 639 i = (int)(fp - (fold_T *)gap->ga_data); |
640 if (ga_grow(gap, 1) == OK) | 640 if (ga_grow(gap, 1) == OK) |
641 { | 641 { |
642 fp = (fold_T *)gap->ga_data + i; | 642 fp = (fold_T *)gap->ga_data + i; |
643 ga_init2(&fold_ga, (int)sizeof(fold_T), 10); | 643 ga_init2(&fold_ga, (int)sizeof(fold_T), 10); |
644 | 644 |
645 /* Count number of folds that will be contained in the new fold. */ | 645 // Count number of folds that will be contained in the new fold. |
646 for (cont = 0; i + cont < gap->ga_len; ++cont) | 646 for (cont = 0; i + cont < gap->ga_len; ++cont) |
647 if (fp[cont].fd_top > end_rel) | 647 if (fp[cont].fd_top > end_rel) |
648 break; | 648 break; |
649 if (cont > 0 && ga_grow(&fold_ga, cont) == OK) | 649 if (cont > 0 && ga_grow(&fold_ga, cont) == OK) |
650 { | 650 { |
651 /* If the first fold starts before the new fold, let the new fold | 651 // If the first fold starts before the new fold, let the new fold |
652 * start there. Otherwise the existing fold would change. */ | 652 // start there. Otherwise the existing fold would change. |
653 if (start_rel > fp->fd_top) | 653 if (start_rel > fp->fd_top) |
654 start_rel = fp->fd_top; | 654 start_rel = fp->fd_top; |
655 | 655 |
656 /* When last contained fold isn't completely contained, adjust end | 656 // When last contained fold isn't completely contained, adjust end |
657 * of new fold. */ | 657 // of new fold. |
658 if (end_rel < fp[cont - 1].fd_top + fp[cont - 1].fd_len - 1) | 658 if (end_rel < fp[cont - 1].fd_top + fp[cont - 1].fd_len - 1) |
659 end_rel = fp[cont - 1].fd_top + fp[cont - 1].fd_len - 1; | 659 end_rel = fp[cont - 1].fd_top + fp[cont - 1].fd_len - 1; |
660 /* Move contained folds to inside new fold. */ | 660 // Move contained folds to inside new fold. |
661 mch_memmove(fold_ga.ga_data, fp, sizeof(fold_T) * cont); | 661 mch_memmove(fold_ga.ga_data, fp, sizeof(fold_T) * cont); |
662 fold_ga.ga_len += cont; | 662 fold_ga.ga_len += cont; |
663 i += cont; | 663 i += cont; |
664 | 664 |
665 /* Adjust line numbers in contained folds to be relative to the | 665 // Adjust line numbers in contained folds to be relative to the |
666 * new fold. */ | 666 // new fold. |
667 for (j = 0; j < cont; ++j) | 667 for (j = 0; j < cont; ++j) |
668 ((fold_T *)fold_ga.ga_data)[j].fd_top -= start_rel; | 668 ((fold_T *)fold_ga.ga_data)[j].fd_top -= start_rel; |
669 } | 669 } |
670 /* Move remaining entries to after the new fold. */ | 670 // Move remaining entries to after the new fold. |
671 if (i < gap->ga_len) | 671 if (i < gap->ga_len) |
672 mch_memmove(fp + 1, (fold_T *)gap->ga_data + i, | 672 mch_memmove(fp + 1, (fold_T *)gap->ga_data + i, |
673 sizeof(fold_T) * (gap->ga_len - i)); | 673 sizeof(fold_T) * (gap->ga_len - i)); |
674 gap->ga_len = gap->ga_len + 1 - cont; | 674 gap->ga_len = gap->ga_len + 1 - cont; |
675 | 675 |
676 /* insert new fold */ | 676 // insert new fold |
677 fp->fd_nested = fold_ga; | 677 fp->fd_nested = fold_ga; |
678 fp->fd_top = start_rel; | 678 fp->fd_top = start_rel; |
679 fp->fd_len = end_rel - start_rel + 1; | 679 fp->fd_len = end_rel - start_rel + 1; |
680 | 680 |
681 /* We want the new fold to be closed. If it would remain open because | 681 // We want the new fold to be closed. If it would remain open because |
682 * of using 'foldlevel', need to adjust fd_flags of containing folds. | 682 // of using 'foldlevel', need to adjust fd_flags of containing folds. |
683 */ | |
684 if (use_level && !closed && level < curwin->w_p_fdl) | 683 if (use_level && !closed && level < curwin->w_p_fdl) |
685 closeFold(start, 1L); | 684 closeFold(start, 1L); |
686 if (!use_level) | 685 if (!use_level) |
687 curwin->w_fold_manual = TRUE; | 686 curwin->w_fold_manual = TRUE; |
688 fp->fd_flags = FD_CLOSED; | 687 fp->fd_flags = FD_CLOSED; |
689 fp->fd_small = MAYBE; | 688 fp->fd_small = MAYBE; |
690 | 689 |
691 /* redraw */ | 690 // redraw |
692 changed_window_setting(); | 691 changed_window_setting(); |
693 } | 692 } |
694 } | 693 } |
695 | 694 |
696 /* deleteFold() {{{2 */ | 695 // deleteFold() {{{2 |
697 /* | 696 /* |
698 * Delete a fold at line "start" in the current window. | 697 * Delete a fold at line "start" in the current window. |
699 * When "end" is not 0, delete all folds from "start" to "end". | 698 * When "end" is not 0, delete all folds from "start" to "end". |
700 * When "recursive" is TRUE delete recursively. | 699 * When "recursive" is TRUE delete recursively. |
701 */ | 700 */ |
702 void | 701 void |
703 deleteFold( | 702 deleteFold( |
704 linenr_T start, | 703 linenr_T start, |
705 linenr_T end, | 704 linenr_T end, |
706 int recursive, | 705 int recursive, |
707 int had_visual) /* TRUE when Visual selection used */ | 706 int had_visual) // TRUE when Visual selection used |
708 { | 707 { |
709 garray_T *gap; | 708 garray_T *gap; |
710 fold_T *fp; | 709 fold_T *fp; |
711 garray_T *found_ga; | 710 garray_T *found_ga; |
712 fold_T *found_fp = NULL; | 711 fold_T *found_fp = NULL; |
722 | 721 |
723 checkupdate(curwin); | 722 checkupdate(curwin); |
724 | 723 |
725 while (lnum <= end) | 724 while (lnum <= end) |
726 { | 725 { |
727 /* Find the deepest fold for "start". */ | 726 // Find the deepest fold for "start". |
728 gap = &curwin->w_folds; | 727 gap = &curwin->w_folds; |
729 found_ga = NULL; | 728 found_ga = NULL; |
730 lnum_off = 0; | 729 lnum_off = 0; |
731 use_level = FALSE; | 730 use_level = FALSE; |
732 for (;;) | 731 for (;;) |
733 { | 732 { |
734 if (!foldFind(gap, lnum - lnum_off, &fp)) | 733 if (!foldFind(gap, lnum - lnum_off, &fp)) |
735 break; | 734 break; |
736 /* lnum is inside this fold, remember info */ | 735 // lnum is inside this fold, remember info |
737 found_ga = gap; | 736 found_ga = gap; |
738 found_fp = fp; | 737 found_fp = fp; |
739 found_off = lnum_off; | 738 found_off = lnum_off; |
740 | 739 |
741 /* if "lnum" is folded, don't check nesting */ | 740 // if "lnum" is folded, don't check nesting |
742 if (check_closed(curwin, fp, &use_level, level, | 741 if (check_closed(curwin, fp, &use_level, level, |
743 &maybe_small, lnum_off)) | 742 &maybe_small, lnum_off)) |
744 break; | 743 break; |
745 | 744 |
746 /* check nested folds */ | 745 // check nested folds |
747 gap = &fp->fd_nested; | 746 gap = &fp->fd_nested; |
748 lnum_off += fp->fd_top; | 747 lnum_off += fp->fd_top; |
749 ++level; | 748 ++level; |
750 } | 749 } |
751 if (found_ga == NULL) | 750 if (found_ga == NULL) |
769 parseMarker(curwin); | 768 parseMarker(curwin); |
770 deleteFoldMarkers(found_fp, recursive, found_off); | 769 deleteFoldMarkers(found_fp, recursive, found_off); |
771 } | 770 } |
772 did_one = TRUE; | 771 did_one = TRUE; |
773 | 772 |
774 /* redraw window */ | 773 // redraw window |
775 changed_window_setting(); | 774 changed_window_setting(); |
776 } | 775 } |
777 } | 776 } |
778 if (!did_one) | 777 if (!did_one) |
779 { | 778 { |
780 emsg(_(e_nofold)); | 779 emsg(_(e_nofold)); |
781 /* Force a redraw to remove the Visual highlighting. */ | 780 // Force a redraw to remove the Visual highlighting. |
782 if (had_visual) | 781 if (had_visual) |
783 redraw_curbuf_later(INVERTED); | 782 redraw_curbuf_later(INVERTED); |
784 } | 783 } |
785 else | 784 else |
786 /* Deleting markers may make cursor column invalid. */ | 785 // Deleting markers may make cursor column invalid. |
787 check_cursor_col(); | 786 check_cursor_col(); |
788 | 787 |
789 if (last_lnum > 0) | 788 if (last_lnum > 0) |
790 changed_lines(first_lnum, (colnr_T)0, last_lnum, 0L); | 789 changed_lines(first_lnum, (colnr_T)0, last_lnum, 0L); |
791 } | 790 } |
792 | 791 |
793 /* clearFolding() {{{2 */ | 792 // clearFolding() {{{2 |
794 /* | 793 /* |
795 * Remove all folding for window "win". | 794 * Remove all folding for window "win". |
796 */ | 795 */ |
797 void | 796 void |
798 clearFolding(win_T *win) | 797 clearFolding(win_T *win) |
799 { | 798 { |
800 deleteFoldRecurse(&win->w_folds); | 799 deleteFoldRecurse(&win->w_folds); |
801 win->w_foldinvalid = FALSE; | 800 win->w_foldinvalid = FALSE; |
802 } | 801 } |
803 | 802 |
804 /* foldUpdate() {{{2 */ | 803 // foldUpdate() {{{2 |
805 /* | 804 /* |
806 * Update folds for changes in the buffer of a window. | 805 * Update folds for changes in the buffer of a window. |
807 * Note that inserted/deleted lines must have already been taken care of by | 806 * Note that inserted/deleted lines must have already been taken care of by |
808 * calling foldMarkAdjust(). | 807 * calling foldMarkAdjust(). |
809 * The changes in lines from top to bot (inclusive). | 808 * The changes in lines from top to bot (inclusive). |
819 if (need_diff_redraw) | 818 if (need_diff_redraw) |
820 // will update later | 819 // will update later |
821 return; | 820 return; |
822 #endif | 821 #endif |
823 | 822 |
824 /* Mark all folds from top to bot as maybe-small. */ | 823 // Mark all folds from top to bot as maybe-small. |
825 (void)foldFind(&wp->w_folds, top, &fp); | 824 (void)foldFind(&wp->w_folds, top, &fp); |
826 while (fp < (fold_T *)wp->w_folds.ga_data + wp->w_folds.ga_len | 825 while (fp < (fold_T *)wp->w_folds.ga_data + wp->w_folds.ga_len |
827 && fp->fd_top < bot) | 826 && fp->fd_top < bot) |
828 { | 827 { |
829 fp->fd_small = MAYBE; | 828 fp->fd_small = MAYBE; |
838 #endif | 837 #endif |
839 || foldmethodIsSyntax(wp)) | 838 || foldmethodIsSyntax(wp)) |
840 { | 839 { |
841 int save_got_int = got_int; | 840 int save_got_int = got_int; |
842 | 841 |
843 /* reset got_int here, otherwise it won't work */ | 842 // reset got_int here, otherwise it won't work |
844 got_int = FALSE; | 843 got_int = FALSE; |
845 foldUpdateIEMS(wp, top, bot); | 844 foldUpdateIEMS(wp, top, bot); |
846 got_int |= save_got_int; | 845 got_int |= save_got_int; |
847 } | 846 } |
848 } | 847 } |
849 | 848 |
850 /* foldUpdateAll() {{{2 */ | 849 // foldUpdateAll() {{{2 |
851 /* | 850 /* |
852 * Update all lines in a window for folding. | 851 * Update all lines in a window for folding. |
853 * Used when a fold setting changes or after reloading the buffer. | 852 * Used when a fold setting changes or after reloading the buffer. |
854 * The actual updating is postponed until fold info is used, to avoid doing | 853 * The actual updating is postponed until fold info is used, to avoid doing |
855 * every time a setting is changed or a syntax item is added. | 854 * every time a setting is changed or a syntax item is added. |
859 { | 858 { |
860 win->w_foldinvalid = TRUE; | 859 win->w_foldinvalid = TRUE; |
861 redraw_win_later(win, NOT_VALID); | 860 redraw_win_later(win, NOT_VALID); |
862 } | 861 } |
863 | 862 |
864 /* foldMoveTo() {{{2 */ | 863 // foldMoveTo() {{{2 |
865 /* | 864 /* |
866 * If "updown" is FALSE: Move to the start or end of the fold. | 865 * If "updown" is FALSE: Move to the start or end of the fold. |
867 * If "updown" is TRUE: move to fold at the same level. | 866 * If "updown" is TRUE: move to fold at the same level. |
868 * If not moved return FAIL. | 867 * If not moved return FAIL. |
869 */ | 868 */ |
870 int | 869 int |
871 foldMoveTo( | 870 foldMoveTo( |
872 int updown, | 871 int updown, |
873 int dir, /* FORWARD or BACKWARD */ | 872 int dir, // FORWARD or BACKWARD |
874 long count) | 873 long count) |
875 { | 874 { |
876 long n; | 875 long n; |
877 int retval = FAIL; | 876 int retval = FAIL; |
878 linenr_T lnum_off; | 877 linenr_T lnum_off; |
885 int level; | 884 int level; |
886 int last; | 885 int last; |
887 | 886 |
888 checkupdate(curwin); | 887 checkupdate(curwin); |
889 | 888 |
890 /* Repeat "count" times. */ | 889 // Repeat "count" times. |
891 for (n = 0; n < count; ++n) | 890 for (n = 0; n < count; ++n) |
892 { | 891 { |
893 /* Find nested folds. Stop when a fold is closed. The deepest fold | 892 // Find nested folds. Stop when a fold is closed. The deepest fold |
894 * that moves the cursor is used. */ | 893 // that moves the cursor is used. |
895 lnum_off = 0; | 894 lnum_off = 0; |
896 gap = &curwin->w_folds; | 895 gap = &curwin->w_folds; |
897 use_level = FALSE; | 896 use_level = FALSE; |
898 maybe_small = FALSE; | 897 maybe_small = FALSE; |
899 lnum_found = curwin->w_cursor.lnum; | 898 lnum_found = curwin->w_cursor.lnum; |
904 if (!foldFind(gap, curwin->w_cursor.lnum - lnum_off, &fp)) | 903 if (!foldFind(gap, curwin->w_cursor.lnum - lnum_off, &fp)) |
905 { | 904 { |
906 if (!updown) | 905 if (!updown) |
907 break; | 906 break; |
908 | 907 |
909 /* When moving up, consider a fold above the cursor; when | 908 // When moving up, consider a fold above the cursor; when |
910 * moving down consider a fold below the cursor. */ | 909 // moving down consider a fold below the cursor. |
911 if (dir == FORWARD) | 910 if (dir == FORWARD) |
912 { | 911 { |
913 if (fp - (fold_T *)gap->ga_data >= gap->ga_len) | 912 if (fp - (fold_T *)gap->ga_data >= gap->ga_len) |
914 break; | 913 break; |
915 --fp; | 914 --fp; |
917 else | 916 else |
918 { | 917 { |
919 if (fp == (fold_T *)gap->ga_data) | 918 if (fp == (fold_T *)gap->ga_data) |
920 break; | 919 break; |
921 } | 920 } |
922 /* don't look for contained folds, they will always move | 921 // don't look for contained folds, they will always move |
923 * the cursor too far. */ | 922 // the cursor too far. |
924 last = TRUE; | 923 last = TRUE; |
925 } | 924 } |
926 | 925 |
927 if (!last) | 926 if (!last) |
928 { | 927 { |
929 /* Check if this fold is closed. */ | 928 // Check if this fold is closed. |
930 if (check_closed(curwin, fp, &use_level, level, | 929 if (check_closed(curwin, fp, &use_level, level, |
931 &maybe_small, lnum_off)) | 930 &maybe_small, lnum_off)) |
932 last = TRUE; | 931 last = TRUE; |
933 | 932 |
934 /* "[z" and "]z" stop at closed fold */ | 933 // "[z" and "]z" stop at closed fold |
935 if (last && !updown) | 934 if (last && !updown) |
936 break; | 935 break; |
937 } | 936 } |
938 | 937 |
939 if (updown) | 938 if (updown) |
940 { | 939 { |
941 if (dir == FORWARD) | 940 if (dir == FORWARD) |
942 { | 941 { |
943 /* to start of next fold if there is one */ | 942 // to start of next fold if there is one |
944 if (fp + 1 - (fold_T *)gap->ga_data < gap->ga_len) | 943 if (fp + 1 - (fold_T *)gap->ga_data < gap->ga_len) |
945 { | 944 { |
946 lnum = fp[1].fd_top + lnum_off; | 945 lnum = fp[1].fd_top + lnum_off; |
947 if (lnum > curwin->w_cursor.lnum) | 946 if (lnum > curwin->w_cursor.lnum) |
948 lnum_found = lnum; | 947 lnum_found = lnum; |
949 } | 948 } |
950 } | 949 } |
951 else | 950 else |
952 { | 951 { |
953 /* to end of previous fold if there is one */ | 952 // to end of previous fold if there is one |
954 if (fp > (fold_T *)gap->ga_data) | 953 if (fp > (fold_T *)gap->ga_data) |
955 { | 954 { |
956 lnum = fp[-1].fd_top + lnum_off + fp[-1].fd_len - 1; | 955 lnum = fp[-1].fd_top + lnum_off + fp[-1].fd_len - 1; |
957 if (lnum < curwin->w_cursor.lnum) | 956 if (lnum < curwin->w_cursor.lnum) |
958 lnum_found = lnum; | 957 lnum_found = lnum; |
959 } | 958 } |
960 } | 959 } |
961 } | 960 } |
962 else | 961 else |
963 { | 962 { |
964 /* Open fold found, set cursor to its start/end and then check | 963 // Open fold found, set cursor to its start/end and then check |
965 * nested folds. */ | 964 // nested folds. |
966 if (dir == FORWARD) | 965 if (dir == FORWARD) |
967 { | 966 { |
968 lnum = fp->fd_top + lnum_off + fp->fd_len - 1; | 967 lnum = fp->fd_top + lnum_off + fp->fd_len - 1; |
969 if (lnum > curwin->w_cursor.lnum) | 968 if (lnum > curwin->w_cursor.lnum) |
970 lnum_found = lnum; | 969 lnum_found = lnum; |
978 } | 977 } |
979 | 978 |
980 if (last) | 979 if (last) |
981 break; | 980 break; |
982 | 981 |
983 /* Check nested folds (if any). */ | 982 // Check nested folds (if any). |
984 gap = &fp->fd_nested; | 983 gap = &fp->fd_nested; |
985 lnum_off += fp->fd_top; | 984 lnum_off += fp->fd_top; |
986 ++level; | 985 ++level; |
987 } | 986 } |
988 if (lnum_found != curwin->w_cursor.lnum) | 987 if (lnum_found != curwin->w_cursor.lnum) |
998 } | 997 } |
999 | 998 |
1000 return retval; | 999 return retval; |
1001 } | 1000 } |
1002 | 1001 |
1003 /* foldInitWin() {{{2 */ | 1002 // foldInitWin() {{{2 |
1004 /* | 1003 /* |
1005 * Init the fold info in a new window. | 1004 * Init the fold info in a new window. |
1006 */ | 1005 */ |
1007 void | 1006 void |
1008 foldInitWin(win_T *new_win) | 1007 foldInitWin(win_T *new_win) |
1009 { | 1008 { |
1010 ga_init2(&new_win->w_folds, (int)sizeof(fold_T), 10); | 1009 ga_init2(&new_win->w_folds, (int)sizeof(fold_T), 10); |
1011 } | 1010 } |
1012 | 1011 |
1013 /* find_wl_entry() {{{2 */ | 1012 // find_wl_entry() {{{2 |
1014 /* | 1013 /* |
1015 * Find an entry in the win->w_lines[] array for buffer line "lnum". | 1014 * Find an entry in the win->w_lines[] array for buffer line "lnum". |
1016 * Only valid entries are considered (for entries where wl_valid is FALSE the | 1015 * Only valid entries are considered (for entries where wl_valid is FALSE the |
1017 * line number can be wrong). | 1016 * line number can be wrong). |
1018 * Returns index of entry or -1 if not found. | 1017 * Returns index of entry or -1 if not found. |
1031 return i; | 1030 return i; |
1032 } | 1031 } |
1033 return -1; | 1032 return -1; |
1034 } | 1033 } |
1035 | 1034 |
1036 /* foldAdjustVisual() {{{2 */ | 1035 // foldAdjustVisual() {{{2 |
1037 /* | 1036 /* |
1038 * Adjust the Visual area to include any fold at the start or end completely. | 1037 * Adjust the Visual area to include any fold at the start or end completely. |
1039 */ | 1038 */ |
1040 void | 1039 void |
1041 foldAdjustVisual(void) | 1040 foldAdjustVisual(void) |
1062 { | 1061 { |
1063 ptr = ml_get(end->lnum); | 1062 ptr = ml_get(end->lnum); |
1064 end->col = (colnr_T)STRLEN(ptr); | 1063 end->col = (colnr_T)STRLEN(ptr); |
1065 if (end->col > 0 && *p_sel == 'o') | 1064 if (end->col > 0 && *p_sel == 'o') |
1066 --end->col; | 1065 --end->col; |
1067 /* prevent cursor from moving on the trail byte */ | 1066 // prevent cursor from moving on the trail byte |
1068 if (has_mbyte) | 1067 if (has_mbyte) |
1069 mb_adjust_cursor(); | 1068 mb_adjust_cursor(); |
1070 } | 1069 } |
1071 } | 1070 } |
1072 | 1071 |
1073 /* cursor_foldstart() {{{2 */ | 1072 // cursor_foldstart() {{{2 |
1074 /* | 1073 /* |
1075 * Move the cursor to the first line of a closed fold. | 1074 * Move the cursor to the first line of a closed fold. |
1076 */ | 1075 */ |
1077 void | 1076 void |
1078 foldAdjustCursor(void) | 1077 foldAdjustCursor(void) |
1079 { | 1078 { |
1080 (void)hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum, NULL); | 1079 (void)hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum, NULL); |
1081 } | 1080 } |
1082 | 1081 |
1083 /* Internal functions for "fold_T" {{{1 */ | 1082 // Internal functions for "fold_T" {{{1 |
1084 /* cloneFoldGrowArray() {{{2 */ | 1083 // cloneFoldGrowArray() {{{2 |
1085 /* | 1084 /* |
1086 * Will "clone" (i.e deep copy) a garray_T of folds. | 1085 * Will "clone" (i.e deep copy) a garray_T of folds. |
1087 * | 1086 * |
1088 * Return FAIL if the operation cannot be completed, otherwise OK. | 1087 * Return FAIL if the operation cannot be completed, otherwise OK. |
1089 */ | 1088 */ |
1112 ++from_p; | 1111 ++from_p; |
1113 ++to_p; | 1112 ++to_p; |
1114 } | 1113 } |
1115 } | 1114 } |
1116 | 1115 |
1117 /* foldFind() {{{2 */ | 1116 // foldFind() {{{2 |
1118 /* | 1117 /* |
1119 * Search for line "lnum" in folds of growarray "gap". | 1118 * Search for line "lnum" in folds of growarray "gap". |
1120 * Set *fpp to the fold struct for the fold that contains "lnum" or | 1119 * Set *fpp to the fold struct for the fold that contains "lnum" or |
1121 * the first fold below it (careful: it can be beyond the end of the array!). | 1120 * the first fold below it (careful: it can be beyond the end of the array!). |
1122 * Returns FALSE when there is no fold that contains "lnum". | 1121 * Returns FALSE when there is no fold that contains "lnum". |
1138 high = gap->ga_len - 1; | 1137 high = gap->ga_len - 1; |
1139 while (low <= high) | 1138 while (low <= high) |
1140 { | 1139 { |
1141 i = (low + high) / 2; | 1140 i = (low + high) / 2; |
1142 if (fp[i].fd_top > lnum) | 1141 if (fp[i].fd_top > lnum) |
1143 /* fold below lnum, adjust high */ | 1142 // fold below lnum, adjust high |
1144 high = i - 1; | 1143 high = i - 1; |
1145 else if (fp[i].fd_top + fp[i].fd_len <= lnum) | 1144 else if (fp[i].fd_top + fp[i].fd_len <= lnum) |
1146 /* fold above lnum, adjust low */ | 1145 // fold above lnum, adjust low |
1147 low = i + 1; | 1146 low = i + 1; |
1148 else | 1147 else |
1149 { | 1148 { |
1150 /* lnum is inside this fold */ | 1149 // lnum is inside this fold |
1151 *fpp = fp + i; | 1150 *fpp = fp + i; |
1152 return TRUE; | 1151 return TRUE; |
1153 } | 1152 } |
1154 } | 1153 } |
1155 *fpp = fp + low; | 1154 *fpp = fp + low; |
1156 return FALSE; | 1155 return FALSE; |
1157 } | 1156 } |
1158 | 1157 |
1159 /* foldLevelWin() {{{2 */ | 1158 // foldLevelWin() {{{2 |
1160 /* | 1159 /* |
1161 * Return fold level at line number "lnum" in window "wp". | 1160 * Return fold level at line number "lnum" in window "wp". |
1162 */ | 1161 */ |
1163 static int | 1162 static int |
1164 foldLevelWin(win_T *wp, linenr_T lnum) | 1163 foldLevelWin(win_T *wp, linenr_T lnum) |
1166 fold_T *fp; | 1165 fold_T *fp; |
1167 linenr_T lnum_rel = lnum; | 1166 linenr_T lnum_rel = lnum; |
1168 int level = 0; | 1167 int level = 0; |
1169 garray_T *gap; | 1168 garray_T *gap; |
1170 | 1169 |
1171 /* Recursively search for a fold that contains "lnum". */ | 1170 // Recursively search for a fold that contains "lnum". |
1172 gap = &wp->w_folds; | 1171 gap = &wp->w_folds; |
1173 for (;;) | 1172 for (;;) |
1174 { | 1173 { |
1175 if (!foldFind(gap, lnum_rel, &fp)) | 1174 if (!foldFind(gap, lnum_rel, &fp)) |
1176 break; | 1175 break; |
1177 /* Check nested folds. Line number is relative to containing fold. */ | 1176 // Check nested folds. Line number is relative to containing fold. |
1178 gap = &fp->fd_nested; | 1177 gap = &fp->fd_nested; |
1179 lnum_rel -= fp->fd_top; | 1178 lnum_rel -= fp->fd_top; |
1180 ++level; | 1179 ++level; |
1181 } | 1180 } |
1182 | 1181 |
1183 return level; | 1182 return level; |
1184 } | 1183 } |
1185 | 1184 |
1186 /* checkupdate() {{{2 */ | 1185 // checkupdate() {{{2 |
1187 /* | 1186 /* |
1188 * Check if the folds in window "wp" are invalid and update them if needed. | 1187 * Check if the folds in window "wp" are invalid and update them if needed. |
1189 */ | 1188 */ |
1190 static void | 1189 static void |
1191 checkupdate(win_T *wp) | 1190 checkupdate(win_T *wp) |
1192 { | 1191 { |
1193 if (wp->w_foldinvalid) | 1192 if (wp->w_foldinvalid) |
1194 { | 1193 { |
1195 foldUpdate(wp, (linenr_T)1, (linenr_T)MAXLNUM); /* will update all */ | 1194 foldUpdate(wp, (linenr_T)1, (linenr_T)MAXLNUM); // will update all |
1196 wp->w_foldinvalid = FALSE; | 1195 wp->w_foldinvalid = FALSE; |
1197 } | 1196 } |
1198 } | 1197 } |
1199 | 1198 |
1200 /* setFoldRepeat() {{{2 */ | 1199 // setFoldRepeat() {{{2 |
1201 /* | 1200 /* |
1202 * Open or close fold for current window at line "lnum". | 1201 * Open or close fold for current window at line "lnum". |
1203 * Repeat "count" times. | 1202 * Repeat "count" times. |
1204 */ | 1203 */ |
1205 static void | 1204 static void |
1212 { | 1211 { |
1213 done = DONE_NOTHING; | 1212 done = DONE_NOTHING; |
1214 (void)setManualFold(lnum, do_open, FALSE, &done); | 1213 (void)setManualFold(lnum, do_open, FALSE, &done); |
1215 if (!(done & DONE_ACTION)) | 1214 if (!(done & DONE_ACTION)) |
1216 { | 1215 { |
1217 /* Only give an error message when no fold could be opened. */ | 1216 // Only give an error message when no fold could be opened. |
1218 if (n == 0 && !(done & DONE_FOLD)) | 1217 if (n == 0 && !(done & DONE_FOLD)) |
1219 emsg(_(e_nofold)); | 1218 emsg(_(e_nofold)); |
1220 break; | 1219 break; |
1221 } | 1220 } |
1222 } | 1221 } |
1223 } | 1222 } |
1224 | 1223 |
1225 /* setManualFold() {{{2 */ | 1224 // setManualFold() {{{2 |
1226 /* | 1225 /* |
1227 * Open or close the fold in the current window which contains "lnum". | 1226 * Open or close the fold in the current window which contains "lnum". |
1228 * Also does this for other windows in diff mode when needed. | 1227 * Also does this for other windows in diff mode when needed. |
1229 */ | 1228 */ |
1230 static linenr_T | 1229 static linenr_T |
1231 setManualFold( | 1230 setManualFold( |
1232 linenr_T lnum, | 1231 linenr_T lnum, |
1233 int opening, /* TRUE when opening, FALSE when closing */ | 1232 int opening, // TRUE when opening, FALSE when closing |
1234 int recurse, /* TRUE when closing/opening recursive */ | 1233 int recurse, // TRUE when closing/opening recursive |
1235 int *donep) | 1234 int *donep) |
1236 { | 1235 { |
1237 #ifdef FEAT_DIFF | 1236 #ifdef FEAT_DIFF |
1238 if (foldmethodIsDiff(curwin) && curwin->w_p_scb) | 1237 if (foldmethodIsDiff(curwin) && curwin->w_p_scb) |
1239 { | 1238 { |
1257 #endif | 1256 #endif |
1258 | 1257 |
1259 return setManualFoldWin(curwin, lnum, opening, recurse, donep); | 1258 return setManualFoldWin(curwin, lnum, opening, recurse, donep); |
1260 } | 1259 } |
1261 | 1260 |
1262 /* setManualFoldWin() {{{2 */ | 1261 // setManualFoldWin() {{{2 |
1263 /* | 1262 /* |
1264 * Open or close the fold in window "wp" which contains "lnum". | 1263 * Open or close the fold in window "wp" which contains "lnum". |
1265 * "donep", when not NULL, points to flag that is set to DONE_FOLD when some | 1264 * "donep", when not NULL, points to flag that is set to DONE_FOLD when some |
1266 * fold was found and to DONE_ACTION when some fold was opened or closed. | 1265 * fold was found and to DONE_ACTION when some fold was opened or closed. |
1267 * When "donep" is NULL give an error message when no fold was found for | 1266 * When "donep" is NULL give an error message when no fold was found for |
1271 */ | 1270 */ |
1272 static linenr_T | 1271 static linenr_T |
1273 setManualFoldWin( | 1272 setManualFoldWin( |
1274 win_T *wp, | 1273 win_T *wp, |
1275 linenr_T lnum, | 1274 linenr_T lnum, |
1276 int opening, /* TRUE when opening, FALSE when closing */ | 1275 int opening, // TRUE when opening, FALSE when closing |
1277 int recurse, /* TRUE when closing/opening recursive */ | 1276 int recurse, // TRUE when closing/opening recursive |
1278 int *donep) | 1277 int *donep) |
1279 { | 1278 { |
1280 fold_T *fp; | 1279 fold_T *fp; |
1281 fold_T *fp2; | 1280 fold_T *fp2; |
1282 fold_T *found = NULL; | 1281 fold_T *found = NULL; |
1297 gap = &wp->w_folds; | 1296 gap = &wp->w_folds; |
1298 for (;;) | 1297 for (;;) |
1299 { | 1298 { |
1300 if (!foldFind(gap, lnum, &fp)) | 1299 if (!foldFind(gap, lnum, &fp)) |
1301 { | 1300 { |
1302 /* If there is a following fold, continue there next time. */ | 1301 // If there is a following fold, continue there next time. |
1303 if (fp < (fold_T *)gap->ga_data + gap->ga_len) | 1302 if (fp < (fold_T *)gap->ga_data + gap->ga_len) |
1304 next = fp->fd_top + off; | 1303 next = fp->fd_top + off; |
1305 break; | 1304 break; |
1306 } | 1305 } |
1307 | 1306 |
1308 /* lnum is inside this fold */ | 1307 // lnum is inside this fold |
1309 found_fold = TRUE; | 1308 found_fold = TRUE; |
1310 | 1309 |
1311 /* If there is a following fold, continue there next time. */ | 1310 // If there is a following fold, continue there next time. |
1312 if (fp + 1 < (fold_T *)gap->ga_data + gap->ga_len) | 1311 if (fp + 1 < (fold_T *)gap->ga_data + gap->ga_len) |
1313 next = fp[1].fd_top + off; | 1312 next = fp[1].fd_top + off; |
1314 | 1313 |
1315 /* Change from level-dependent folding to manual. */ | 1314 // Change from level-dependent folding to manual. |
1316 if (use_level || fp->fd_flags == FD_LEVEL) | 1315 if (use_level || fp->fd_flags == FD_LEVEL) |
1317 { | 1316 { |
1318 use_level = TRUE; | 1317 use_level = TRUE; |
1319 if (level >= wp->w_p_fdl) | 1318 if (level >= wp->w_p_fdl) |
1320 fp->fd_flags = FD_CLOSED; | 1319 fp->fd_flags = FD_CLOSED; |
1323 fp2 = (fold_T *)fp->fd_nested.ga_data; | 1322 fp2 = (fold_T *)fp->fd_nested.ga_data; |
1324 for (j = 0; j < fp->fd_nested.ga_len; ++j) | 1323 for (j = 0; j < fp->fd_nested.ga_len; ++j) |
1325 fp2[j].fd_flags = FD_LEVEL; | 1324 fp2[j].fd_flags = FD_LEVEL; |
1326 } | 1325 } |
1327 | 1326 |
1328 /* Simple case: Close recursively means closing the fold. */ | 1327 // Simple case: Close recursively means closing the fold. |
1329 if (!opening && recurse) | 1328 if (!opening && recurse) |
1330 { | 1329 { |
1331 if (fp->fd_flags != FD_CLOSED) | 1330 if (fp->fd_flags != FD_CLOSED) |
1332 { | 1331 { |
1333 done |= DONE_ACTION; | 1332 done |= DONE_ACTION; |
1334 fp->fd_flags = FD_CLOSED; | 1333 fp->fd_flags = FD_CLOSED; |
1335 } | 1334 } |
1336 } | 1335 } |
1337 else if (fp->fd_flags == FD_CLOSED) | 1336 else if (fp->fd_flags == FD_CLOSED) |
1338 { | 1337 { |
1339 /* When opening, open topmost closed fold. */ | 1338 // When opening, open topmost closed fold. |
1340 if (opening) | 1339 if (opening) |
1341 { | 1340 { |
1342 fp->fd_flags = FD_OPEN; | 1341 fp->fd_flags = FD_OPEN; |
1343 done |= DONE_ACTION; | 1342 done |= DONE_ACTION; |
1344 if (recurse) | 1343 if (recurse) |
1345 foldOpenNested(fp); | 1344 foldOpenNested(fp); |
1346 } | 1345 } |
1347 break; | 1346 break; |
1348 } | 1347 } |
1349 | 1348 |
1350 /* fold is open, check nested folds */ | 1349 // fold is open, check nested folds |
1351 found = fp; | 1350 found = fp; |
1352 gap = &fp->fd_nested; | 1351 gap = &fp->fd_nested; |
1353 lnum -= fp->fd_top; | 1352 lnum -= fp->fd_top; |
1354 off += fp->fd_top; | 1353 off += fp->fd_top; |
1355 ++level; | 1354 ++level; |
1356 } | 1355 } |
1357 if (found_fold) | 1356 if (found_fold) |
1358 { | 1357 { |
1359 /* When closing and not recurse, close deepest open fold. */ | 1358 // When closing and not recurse, close deepest open fold. |
1360 if (!opening && found != NULL) | 1359 if (!opening && found != NULL) |
1361 { | 1360 { |
1362 found->fd_flags = FD_CLOSED; | 1361 found->fd_flags = FD_CLOSED; |
1363 done |= DONE_ACTION; | 1362 done |= DONE_ACTION; |
1364 } | 1363 } |
1374 *donep |= done; | 1373 *donep |= done; |
1375 | 1374 |
1376 return next; | 1375 return next; |
1377 } | 1376 } |
1378 | 1377 |
1379 /* foldOpenNested() {{{2 */ | 1378 // foldOpenNested() {{{2 |
1380 /* | 1379 /* |
1381 * Open all nested folds in fold "fpr" recursively. | 1380 * Open all nested folds in fold "fpr" recursively. |
1382 */ | 1381 */ |
1383 static void | 1382 static void |
1384 foldOpenNested(fold_T *fpr) | 1383 foldOpenNested(fold_T *fpr) |
1392 foldOpenNested(&fp[i]); | 1391 foldOpenNested(&fp[i]); |
1393 fp[i].fd_flags = FD_OPEN; | 1392 fp[i].fd_flags = FD_OPEN; |
1394 } | 1393 } |
1395 } | 1394 } |
1396 | 1395 |
1397 /* deleteFoldEntry() {{{2 */ | 1396 // deleteFoldEntry() {{{2 |
1398 /* | 1397 /* |
1399 * Delete fold "idx" from growarray "gap". | 1398 * Delete fold "idx" from growarray "gap". |
1400 * When "recursive" is TRUE also delete all the folds contained in it. | 1399 * When "recursive" is TRUE also delete all the folds contained in it. |
1401 * When "recursive" is FALSE contained folds are moved one level up. | 1400 * When "recursive" is FALSE contained folds are moved one level up. |
1402 */ | 1401 */ |
1409 fold_T *nfp; | 1408 fold_T *nfp; |
1410 | 1409 |
1411 fp = (fold_T *)gap->ga_data + idx; | 1410 fp = (fold_T *)gap->ga_data + idx; |
1412 if (recursive || fp->fd_nested.ga_len == 0) | 1411 if (recursive || fp->fd_nested.ga_len == 0) |
1413 { | 1412 { |
1414 /* recursively delete the contained folds */ | 1413 // recursively delete the contained folds |
1415 deleteFoldRecurse(&fp->fd_nested); | 1414 deleteFoldRecurse(&fp->fd_nested); |
1416 --gap->ga_len; | 1415 --gap->ga_len; |
1417 if (idx < gap->ga_len) | 1416 if (idx < gap->ga_len) |
1418 mch_memmove(fp, fp + 1, sizeof(fold_T) * (gap->ga_len - idx)); | 1417 mch_memmove(fp, fp + 1, sizeof(fold_T) * (gap->ga_len - idx)); |
1419 } | 1418 } |
1420 else | 1419 else |
1421 { | 1420 { |
1422 /* Move nested folds one level up, to overwrite the fold that is | 1421 // Move nested folds one level up, to overwrite the fold that is |
1423 * deleted. */ | 1422 // deleted. |
1424 moved = fp->fd_nested.ga_len; | 1423 moved = fp->fd_nested.ga_len; |
1425 if (ga_grow(gap, (int)(moved - 1)) == OK) | 1424 if (ga_grow(gap, (int)(moved - 1)) == OK) |
1426 { | 1425 { |
1427 /* Get "fp" again, the array may have been reallocated. */ | 1426 // Get "fp" again, the array may have been reallocated. |
1428 fp = (fold_T *)gap->ga_data + idx; | 1427 fp = (fold_T *)gap->ga_data + idx; |
1429 | 1428 |
1430 /* adjust fd_top and fd_flags for the moved folds */ | 1429 // adjust fd_top and fd_flags for the moved folds |
1431 nfp = (fold_T *)fp->fd_nested.ga_data; | 1430 nfp = (fold_T *)fp->fd_nested.ga_data; |
1432 for (i = 0; i < moved; ++i) | 1431 for (i = 0; i < moved; ++i) |
1433 { | 1432 { |
1434 nfp[i].fd_top += fp->fd_top; | 1433 nfp[i].fd_top += fp->fd_top; |
1435 if (fp->fd_flags == FD_LEVEL) | 1434 if (fp->fd_flags == FD_LEVEL) |
1436 nfp[i].fd_flags = FD_LEVEL; | 1435 nfp[i].fd_flags = FD_LEVEL; |
1437 if (fp->fd_small == MAYBE) | 1436 if (fp->fd_small == MAYBE) |
1438 nfp[i].fd_small = MAYBE; | 1437 nfp[i].fd_small = MAYBE; |
1439 } | 1438 } |
1440 | 1439 |
1441 /* move the existing folds down to make room */ | 1440 // move the existing folds down to make room |
1442 if (idx + 1 < gap->ga_len) | 1441 if (idx + 1 < gap->ga_len) |
1443 mch_memmove(fp + moved, fp + 1, | 1442 mch_memmove(fp + moved, fp + 1, |
1444 sizeof(fold_T) * (gap->ga_len - (idx + 1))); | 1443 sizeof(fold_T) * (gap->ga_len - (idx + 1))); |
1445 /* move the contained folds one level up */ | 1444 // move the contained folds one level up |
1446 mch_memmove(fp, nfp, (size_t)(sizeof(fold_T) * moved)); | 1445 mch_memmove(fp, nfp, (size_t)(sizeof(fold_T) * moved)); |
1447 vim_free(nfp); | 1446 vim_free(nfp); |
1448 gap->ga_len += moved - 1; | 1447 gap->ga_len += moved - 1; |
1449 } | 1448 } |
1450 } | 1449 } |
1451 } | 1450 } |
1452 | 1451 |
1453 /* deleteFoldRecurse() {{{2 */ | 1452 // deleteFoldRecurse() {{{2 |
1454 /* | 1453 /* |
1455 * Delete nested folds in a fold. | 1454 * Delete nested folds in a fold. |
1456 */ | 1455 */ |
1457 void | 1456 void |
1458 deleteFoldRecurse(garray_T *gap) | 1457 deleteFoldRecurse(garray_T *gap) |
1462 for (i = 0; i < gap->ga_len; ++i) | 1461 for (i = 0; i < gap->ga_len; ++i) |
1463 deleteFoldRecurse(&(((fold_T *)(gap->ga_data))[i].fd_nested)); | 1462 deleteFoldRecurse(&(((fold_T *)(gap->ga_data))[i].fd_nested)); |
1464 ga_clear(gap); | 1463 ga_clear(gap); |
1465 } | 1464 } |
1466 | 1465 |
1467 /* foldMarkAdjust() {{{2 */ | 1466 // foldMarkAdjust() {{{2 |
1468 /* | 1467 /* |
1469 * Update line numbers of folds for inserted/deleted lines. | 1468 * Update line numbers of folds for inserted/deleted lines. |
1470 */ | 1469 */ |
1471 void | 1470 void |
1472 foldMarkAdjust( | 1471 foldMarkAdjust( |
1474 linenr_T line1, | 1473 linenr_T line1, |
1475 linenr_T line2, | 1474 linenr_T line2, |
1476 long amount, | 1475 long amount, |
1477 long amount_after) | 1476 long amount_after) |
1478 { | 1477 { |
1479 /* If deleting marks from line1 to line2, but not deleting all those | 1478 // If deleting marks from line1 to line2, but not deleting all those |
1480 * lines, set line2 so that only deleted lines have their folds removed. */ | 1479 // lines, set line2 so that only deleted lines have their folds removed. |
1481 if (amount == MAXLNUM && line2 >= line1 && line2 - line1 >= -amount_after) | 1480 if (amount == MAXLNUM && line2 >= line1 && line2 - line1 >= -amount_after) |
1482 line2 = line1 - amount_after - 1; | 1481 line2 = line1 - amount_after - 1; |
1483 /* If appending a line in Insert mode, it should be included in the fold | 1482 // If appending a line in Insert mode, it should be included in the fold |
1484 * just above the line. */ | 1483 // just above the line. |
1485 if ((State & INSERT) && amount == (linenr_T)1 && line2 == MAXLNUM) | 1484 if ((State & INSERT) && amount == (linenr_T)1 && line2 == MAXLNUM) |
1486 --line1; | 1485 --line1; |
1487 foldMarkAdjustRecurse(&wp->w_folds, line1, line2, amount, amount_after); | 1486 foldMarkAdjustRecurse(&wp->w_folds, line1, line2, amount, amount_after); |
1488 } | 1487 } |
1489 | 1488 |
1490 /* foldMarkAdjustRecurse() {{{2 */ | 1489 // foldMarkAdjustRecurse() {{{2 |
1491 static void | 1490 static void |
1492 foldMarkAdjustRecurse( | 1491 foldMarkAdjustRecurse( |
1493 garray_T *gap, | 1492 garray_T *gap, |
1494 linenr_T line1, | 1493 linenr_T line1, |
1495 linenr_T line2, | 1494 linenr_T line2, |
1499 fold_T *fp; | 1498 fold_T *fp; |
1500 int i; | 1499 int i; |
1501 linenr_T last; | 1500 linenr_T last; |
1502 linenr_T top; | 1501 linenr_T top; |
1503 | 1502 |
1504 /* In Insert mode an inserted line at the top of a fold is considered part | 1503 // In Insert mode an inserted line at the top of a fold is considered part |
1505 * of the fold, otherwise it isn't. */ | 1504 // of the fold, otherwise it isn't. |
1506 if ((State & INSERT) && amount == (linenr_T)1 && line2 == MAXLNUM) | 1505 if ((State & INSERT) && amount == (linenr_T)1 && line2 == MAXLNUM) |
1507 top = line1 + 1; | 1506 top = line1 + 1; |
1508 else | 1507 else |
1509 top = line1; | 1508 top = line1; |
1510 | 1509 |
1511 /* Find the fold containing or just below "line1". */ | 1510 // Find the fold containing or just below "line1". |
1512 (void)foldFind(gap, line1, &fp); | 1511 (void)foldFind(gap, line1, &fp); |
1513 | 1512 |
1514 /* | 1513 /* |
1515 * Adjust all folds below "line1" that are affected. | 1514 * Adjust all folds below "line1" that are affected. |
1516 */ | 1515 */ |
1526 * line2 2 3 4 5 | 1525 * line2 2 3 4 5 |
1527 * 3 5 6 | 1526 * 3 5 6 |
1528 * 3 5 6 | 1527 * 3 5 6 |
1529 */ | 1528 */ |
1530 | 1529 |
1531 last = fp->fd_top + fp->fd_len - 1; /* last line of fold */ | 1530 last = fp->fd_top + fp->fd_len - 1; // last line of fold |
1532 | 1531 |
1533 /* 1. fold completely above line1: nothing to do */ | 1532 // 1. fold completely above line1: nothing to do |
1534 if (last < line1) | 1533 if (last < line1) |
1535 continue; | 1534 continue; |
1536 | 1535 |
1537 /* 6. fold below line2: only adjust for amount_after */ | 1536 // 6. fold below line2: only adjust for amount_after |
1538 if (fp->fd_top > line2) | 1537 if (fp->fd_top > line2) |
1539 { | 1538 { |
1540 if (amount_after == 0) | 1539 if (amount_after == 0) |
1541 break; | 1540 break; |
1542 fp->fd_top += amount_after; | 1541 fp->fd_top += amount_after; |
1543 } | 1542 } |
1544 else | 1543 else |
1545 { | 1544 { |
1546 if (fp->fd_top >= top && last <= line2) | 1545 if (fp->fd_top >= top && last <= line2) |
1547 { | 1546 { |
1548 /* 4. fold completely contained in range */ | 1547 // 4. fold completely contained in range |
1549 if (amount == MAXLNUM) | 1548 if (amount == MAXLNUM) |
1550 { | 1549 { |
1551 /* Deleting lines: delete the fold completely */ | 1550 // Deleting lines: delete the fold completely |
1552 deleteFoldEntry(gap, i, TRUE); | 1551 deleteFoldEntry(gap, i, TRUE); |
1553 --i; /* adjust index for deletion */ | 1552 --i; // adjust index for deletion |
1554 --fp; | 1553 --fp; |
1555 } | 1554 } |
1556 else | 1555 else |
1557 fp->fd_top += amount; | 1556 fp->fd_top += amount; |
1558 } | 1557 } |
1559 else | 1558 else |
1560 { | 1559 { |
1561 if (fp->fd_top < top) | 1560 if (fp->fd_top < top) |
1562 { | 1561 { |
1563 /* 2 or 3: need to correct nested folds too */ | 1562 // 2 or 3: need to correct nested folds too |
1564 foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top, | 1563 foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top, |
1565 line2 - fp->fd_top, amount, amount_after); | 1564 line2 - fp->fd_top, amount, amount_after); |
1566 if (last <= line2) | 1565 if (last <= line2) |
1567 { | 1566 { |
1568 /* 2. fold contains line1, line2 is below fold */ | 1567 // 2. fold contains line1, line2 is below fold |
1569 if (amount == MAXLNUM) | 1568 if (amount == MAXLNUM) |
1570 fp->fd_len = line1 - fp->fd_top; | 1569 fp->fd_len = line1 - fp->fd_top; |
1571 else | 1570 else |
1572 fp->fd_len += amount; | 1571 fp->fd_len += amount; |
1573 } | 1572 } |
1574 else | 1573 else |
1575 { | 1574 { |
1576 /* 3. fold contains line1 and line2 */ | 1575 // 3. fold contains line1 and line2 |
1577 fp->fd_len += amount_after; | 1576 fp->fd_len += amount_after; |
1578 } | 1577 } |
1579 } | 1578 } |
1580 else | 1579 else |
1581 { | 1580 { |
1582 /* 5. fold is below line1 and contains line2; need to | 1581 // 5. fold is below line1 and contains line2; need to |
1583 * correct nested folds too */ | 1582 // correct nested folds too |
1584 if (amount == MAXLNUM) | 1583 if (amount == MAXLNUM) |
1585 { | 1584 { |
1586 foldMarkAdjustRecurse(&fp->fd_nested, | 1585 foldMarkAdjustRecurse(&fp->fd_nested, |
1587 line1 - fp->fd_top, | 1586 line1 - fp->fd_top, |
1588 line2 - fp->fd_top, | 1587 line2 - fp->fd_top, |
1605 } | 1604 } |
1606 } | 1605 } |
1607 } | 1606 } |
1608 } | 1607 } |
1609 | 1608 |
1610 /* getDeepestNesting() {{{2 */ | 1609 // getDeepestNesting() {{{2 |
1611 /* | 1610 /* |
1612 * Get the lowest 'foldlevel' value that makes the deepest nested fold in the | 1611 * Get the lowest 'foldlevel' value that makes the deepest nested fold in the |
1613 * current window open. | 1612 * current window open. |
1614 */ | 1613 */ |
1615 int | 1614 int |
1636 } | 1635 } |
1637 | 1636 |
1638 return maxlevel; | 1637 return maxlevel; |
1639 } | 1638 } |
1640 | 1639 |
1641 /* check_closed() {{{2 */ | 1640 // check_closed() {{{2 |
1642 /* | 1641 /* |
1643 * Check if a fold is closed and update the info needed to check nested folds. | 1642 * Check if a fold is closed and update the info needed to check nested folds. |
1644 */ | 1643 */ |
1645 static int | 1644 static int |
1646 check_closed( | 1645 check_closed( |
1647 win_T *win, | 1646 win_T *win, |
1648 fold_T *fp, | 1647 fold_T *fp, |
1649 int *use_levelp, /* TRUE: outer fold had FD_LEVEL */ | 1648 int *use_levelp, // TRUE: outer fold had FD_LEVEL |
1650 int level, /* folding depth */ | 1649 int level, // folding depth |
1651 int *maybe_smallp, /* TRUE: outer this had fd_small == MAYBE */ | 1650 int *maybe_smallp, // TRUE: outer this had fd_small == MAYBE |
1652 linenr_T lnum_off) /* line number offset for fp->fd_top */ | 1651 linenr_T lnum_off) // line number offset for fp->fd_top |
1653 { | 1652 { |
1654 int closed = FALSE; | 1653 int closed = FALSE; |
1655 | 1654 |
1656 /* Check if this fold is closed. If the flag is FD_LEVEL this | 1655 // Check if this fold is closed. If the flag is FD_LEVEL this |
1657 * fold and all folds it contains depend on 'foldlevel'. */ | 1656 // fold and all folds it contains depend on 'foldlevel'. |
1658 if (*use_levelp || fp->fd_flags == FD_LEVEL) | 1657 if (*use_levelp || fp->fd_flags == FD_LEVEL) |
1659 { | 1658 { |
1660 *use_levelp = TRUE; | 1659 *use_levelp = TRUE; |
1661 if (level >= win->w_p_fdl) | 1660 if (level >= win->w_p_fdl) |
1662 closed = TRUE; | 1661 closed = TRUE; |
1663 } | 1662 } |
1664 else if (fp->fd_flags == FD_CLOSED) | 1663 else if (fp->fd_flags == FD_CLOSED) |
1665 closed = TRUE; | 1664 closed = TRUE; |
1666 | 1665 |
1667 /* Small fold isn't closed anyway. */ | 1666 // Small fold isn't closed anyway. |
1668 if (fp->fd_small == MAYBE) | 1667 if (fp->fd_small == MAYBE) |
1669 *maybe_smallp = TRUE; | 1668 *maybe_smallp = TRUE; |
1670 if (closed) | 1669 if (closed) |
1671 { | 1670 { |
1672 if (*maybe_smallp) | 1671 if (*maybe_smallp) |
1676 closed = FALSE; | 1675 closed = FALSE; |
1677 } | 1676 } |
1678 return closed; | 1677 return closed; |
1679 } | 1678 } |
1680 | 1679 |
1681 /* checkSmall() {{{2 */ | 1680 // checkSmall() {{{2 |
1682 /* | 1681 /* |
1683 * Update fd_small field of fold "fp". | 1682 * Update fd_small field of fold "fp". |
1684 */ | 1683 */ |
1685 static void | 1684 static void |
1686 checkSmall( | 1685 checkSmall( |
1687 win_T *wp, | 1686 win_T *wp, |
1688 fold_T *fp, | 1687 fold_T *fp, |
1689 linenr_T lnum_off) /* offset for fp->fd_top */ | 1688 linenr_T lnum_off) // offset for fp->fd_top |
1690 { | 1689 { |
1691 int count; | 1690 int count; |
1692 int n; | 1691 int n; |
1693 | 1692 |
1694 if (fp->fd_small == MAYBE) | 1693 if (fp->fd_small == MAYBE) |
1695 { | 1694 { |
1696 /* Mark any nested folds to maybe-small */ | 1695 // Mark any nested folds to maybe-small |
1697 setSmallMaybe(&fp->fd_nested); | 1696 setSmallMaybe(&fp->fd_nested); |
1698 | 1697 |
1699 if (fp->fd_len > curwin->w_p_fml) | 1698 if (fp->fd_len > curwin->w_p_fml) |
1700 fp->fd_small = FALSE; | 1699 fp->fd_small = FALSE; |
1701 else | 1700 else |
1713 fp->fd_small = TRUE; | 1712 fp->fd_small = TRUE; |
1714 } | 1713 } |
1715 } | 1714 } |
1716 } | 1715 } |
1717 | 1716 |
1718 /* setSmallMaybe() {{{2 */ | 1717 // setSmallMaybe() {{{2 |
1719 /* | 1718 /* |
1720 * Set small flags in "gap" to MAYBE. | 1719 * Set small flags in "gap" to MAYBE. |
1721 */ | 1720 */ |
1722 static void | 1721 static void |
1723 setSmallMaybe(garray_T *gap) | 1722 setSmallMaybe(garray_T *gap) |
1728 fp = (fold_T *)gap->ga_data; | 1727 fp = (fold_T *)gap->ga_data; |
1729 for (i = 0; i < gap->ga_len; ++i) | 1728 for (i = 0; i < gap->ga_len; ++i) |
1730 fp[i].fd_small = MAYBE; | 1729 fp[i].fd_small = MAYBE; |
1731 } | 1730 } |
1732 | 1731 |
1733 /* foldCreateMarkers() {{{2 */ | 1732 // foldCreateMarkers() {{{2 |
1734 /* | 1733 /* |
1735 * Create a fold from line "start" to line "end" (inclusive) in the current | 1734 * Create a fold from line "start" to line "end" (inclusive) in the current |
1736 * window by adding markers. | 1735 * window by adding markers. |
1737 */ | 1736 */ |
1738 static void | 1737 static void |
1746 parseMarker(curwin); | 1745 parseMarker(curwin); |
1747 | 1746 |
1748 foldAddMarker(start, curwin->w_p_fmr, foldstartmarkerlen); | 1747 foldAddMarker(start, curwin->w_p_fmr, foldstartmarkerlen); |
1749 foldAddMarker(end, foldendmarker, foldendmarkerlen); | 1748 foldAddMarker(end, foldendmarker, foldendmarkerlen); |
1750 | 1749 |
1751 /* Update both changes here, to avoid all folds after the start are | 1750 // Update both changes here, to avoid all folds after the start are |
1752 * changed when the start marker is inserted and the end isn't. */ | 1751 // changed when the start marker is inserted and the end isn't. |
1753 changed_lines(start, (colnr_T)0, end, 0L); | 1752 changed_lines(start, (colnr_T)0, end, 0L); |
1754 } | 1753 } |
1755 | 1754 |
1756 /* foldAddMarker() {{{2 */ | 1755 // foldAddMarker() {{{2 |
1757 /* | 1756 /* |
1758 * Add "marker[markerlen]" in 'commentstring' to line "lnum". | 1757 * Add "marker[markerlen]" in 'commentstring' to line "lnum". |
1759 */ | 1758 */ |
1760 static void | 1759 static void |
1761 foldAddMarker(linenr_T lnum, char_u *marker, int markerlen) | 1760 foldAddMarker(linenr_T lnum, char_u *marker, int markerlen) |
1765 int line_len; | 1764 int line_len; |
1766 char_u *newline; | 1765 char_u *newline; |
1767 char_u *p = (char_u *)strstr((char *)curbuf->b_p_cms, "%s"); | 1766 char_u *p = (char_u *)strstr((char *)curbuf->b_p_cms, "%s"); |
1768 int line_is_comment = FALSE; | 1767 int line_is_comment = FALSE; |
1769 | 1768 |
1770 /* Allocate a new line: old-line + 'cms'-start + marker + 'cms'-end */ | 1769 // Allocate a new line: old-line + 'cms'-start + marker + 'cms'-end |
1771 line = ml_get(lnum); | 1770 line = ml_get(lnum); |
1772 line_len = (int)STRLEN(line); | 1771 line_len = (int)STRLEN(line); |
1773 | 1772 |
1774 if (u_save(lnum - 1, lnum + 1) == OK) | 1773 if (u_save(lnum - 1, lnum + 1) == OK) |
1775 { | 1774 { |
1776 /* Check if the line ends with an unclosed comment */ | 1775 // Check if the line ends with an unclosed comment |
1777 (void)skip_comment(line, FALSE, FALSE, &line_is_comment); | 1776 (void)skip_comment(line, FALSE, FALSE, &line_is_comment); |
1778 newline = alloc(line_len + markerlen + STRLEN(cms) + 1); | 1777 newline = alloc(line_len + markerlen + STRLEN(cms) + 1); |
1779 if (newline == NULL) | 1778 if (newline == NULL) |
1780 return; | 1779 return; |
1781 STRCPY(newline, line); | 1780 STRCPY(newline, line); |
1782 /* Append the marker to the end of the line */ | 1781 // Append the marker to the end of the line |
1783 if (p == NULL || line_is_comment) | 1782 if (p == NULL || line_is_comment) |
1784 vim_strncpy(newline + line_len, marker, markerlen); | 1783 vim_strncpy(newline + line_len, marker, markerlen); |
1785 else | 1784 else |
1786 { | 1785 { |
1787 STRCPY(newline + line_len, cms); | 1786 STRCPY(newline + line_len, cms); |
1791 | 1790 |
1792 ml_replace(lnum, newline, FALSE); | 1791 ml_replace(lnum, newline, FALSE); |
1793 } | 1792 } |
1794 } | 1793 } |
1795 | 1794 |
1796 /* deleteFoldMarkers() {{{2 */ | 1795 // deleteFoldMarkers() {{{2 |
1797 /* | 1796 /* |
1798 * Delete the markers for a fold, causing it to be deleted. | 1797 * Delete the markers for a fold, causing it to be deleted. |
1799 */ | 1798 */ |
1800 static void | 1799 static void |
1801 deleteFoldMarkers( | 1800 deleteFoldMarkers( |
1802 fold_T *fp, | 1801 fold_T *fp, |
1803 int recursive, | 1802 int recursive, |
1804 linenr_T lnum_off) /* offset for fp->fd_top */ | 1803 linenr_T lnum_off) // offset for fp->fd_top |
1805 { | 1804 { |
1806 int i; | 1805 int i; |
1807 | 1806 |
1808 if (recursive) | 1807 if (recursive) |
1809 for (i = 0; i < fp->fd_nested.ga_len; ++i) | 1808 for (i = 0; i < fp->fd_nested.ga_len; ++i) |
1812 foldDelMarker(fp->fd_top + lnum_off, curwin->w_p_fmr, foldstartmarkerlen); | 1811 foldDelMarker(fp->fd_top + lnum_off, curwin->w_p_fmr, foldstartmarkerlen); |
1813 foldDelMarker(fp->fd_top + lnum_off + fp->fd_len - 1, | 1812 foldDelMarker(fp->fd_top + lnum_off + fp->fd_len - 1, |
1814 foldendmarker, foldendmarkerlen); | 1813 foldendmarker, foldendmarkerlen); |
1815 } | 1814 } |
1816 | 1815 |
1817 /* foldDelMarker() {{{2 */ | 1816 // foldDelMarker() {{{2 |
1818 /* | 1817 /* |
1819 * Delete marker "marker[markerlen]" at the end of line "lnum". | 1818 * Delete marker "marker[markerlen]" at the end of line "lnum". |
1820 * Delete 'commentstring' if it matches. | 1819 * Delete 'commentstring' if it matches. |
1821 * If the marker is not found, there is no error message. Could be a missing | 1820 * If the marker is not found, there is no error message. Could be a missing |
1822 * close-marker. | 1821 * close-marker. |
1836 return; | 1835 return; |
1837 line = ml_get(lnum); | 1836 line = ml_get(lnum); |
1838 for (p = line; *p != NUL; ++p) | 1837 for (p = line; *p != NUL; ++p) |
1839 if (STRNCMP(p, marker, markerlen) == 0) | 1838 if (STRNCMP(p, marker, markerlen) == 0) |
1840 { | 1839 { |
1841 /* Found the marker, include a digit if it's there. */ | 1840 // Found the marker, include a digit if it's there. |
1842 len = markerlen; | 1841 len = markerlen; |
1843 if (VIM_ISDIGIT(p[len])) | 1842 if (VIM_ISDIGIT(p[len])) |
1844 ++len; | 1843 ++len; |
1845 if (*cms != NUL) | 1844 if (*cms != NUL) |
1846 { | 1845 { |
1847 /* Also delete 'commentstring' if it matches. */ | 1846 // Also delete 'commentstring' if it matches. |
1848 cms2 = (char_u *)strstr((char *)cms, "%s"); | 1847 cms2 = (char_u *)strstr((char *)cms, "%s"); |
1849 if (p - line >= cms2 - cms | 1848 if (p - line >= cms2 - cms |
1850 && STRNCMP(p - (cms2 - cms), cms, cms2 - cms) == 0 | 1849 && STRNCMP(p - (cms2 - cms), cms, cms2 - cms) == 0 |
1851 && STRNCMP(p + len, cms2 + 2, STRLEN(cms2 + 2)) == 0) | 1850 && STRNCMP(p + len, cms2 + 2, STRLEN(cms2 + 2)) == 0) |
1852 { | 1851 { |
1854 len += (int)STRLEN(cms) - 2; | 1853 len += (int)STRLEN(cms) - 2; |
1855 } | 1854 } |
1856 } | 1855 } |
1857 if (u_save(lnum - 1, lnum + 1) == OK) | 1856 if (u_save(lnum - 1, lnum + 1) == OK) |
1858 { | 1857 { |
1859 /* Make new line: text-before-marker + text-after-marker */ | 1858 // Make new line: text-before-marker + text-after-marker |
1860 newline = alloc(STRLEN(line) - len + 1); | 1859 newline = alloc(STRLEN(line) - len + 1); |
1861 if (newline != NULL) | 1860 if (newline != NULL) |
1862 { | 1861 { |
1863 STRNCPY(newline, line, p - line); | 1862 STRNCPY(newline, line, p - line); |
1864 STRCPY(newline + (p - line), p + len); | 1863 STRCPY(newline + (p - line), p + len); |
1867 } | 1866 } |
1868 break; | 1867 break; |
1869 } | 1868 } |
1870 } | 1869 } |
1871 | 1870 |
1872 /* get_foldtext() {{{2 */ | 1871 // get_foldtext() {{{2 |
1873 /* | 1872 /* |
1874 * Return the text for a closed fold at line "lnum", with last line "lnume". | 1873 * Return the text for a closed fold at line "lnum", with last line "lnume". |
1875 * When 'foldtext' isn't set puts the result in "buf[FOLD_TEXT_LEN]". | 1874 * When 'foldtext' isn't set puts the result in "buf[FOLD_TEXT_LEN]". |
1876 * Otherwise the result is in allocated memory. | 1875 * Otherwise the result is in allocated memory. |
1877 */ | 1876 */ |
1883 foldinfo_T *foldinfo, | 1882 foldinfo_T *foldinfo, |
1884 char_u *buf) | 1883 char_u *buf) |
1885 { | 1884 { |
1886 char_u *text = NULL; | 1885 char_u *text = NULL; |
1887 #ifdef FEAT_EVAL | 1886 #ifdef FEAT_EVAL |
1888 /* an error occurred when evaluating 'fdt' setting */ | 1887 // an error occurred when evaluating 'fdt' setting |
1889 static int got_fdt_error = FALSE; | 1888 static int got_fdt_error = FALSE; |
1890 int save_did_emsg = did_emsg; | 1889 int save_did_emsg = did_emsg; |
1891 static win_T *last_wp = NULL; | 1890 static win_T *last_wp = NULL; |
1892 static linenr_T last_lnum = 0; | 1891 static linenr_T last_lnum = 0; |
1893 | 1892 |
1894 if (last_wp != wp || last_wp == NULL | 1893 if (last_wp != wp || last_wp == NULL |
1895 || last_lnum > lnum || last_lnum == 0) | 1894 || last_lnum > lnum || last_lnum == 0) |
1896 /* window changed, try evaluating foldtext setting once again */ | 1895 // window changed, try evaluating foldtext setting once again |
1897 got_fdt_error = FALSE; | 1896 got_fdt_error = FALSE; |
1898 | 1897 |
1899 if (!got_fdt_error) | 1898 if (!got_fdt_error) |
1900 /* a previous error should not abort evaluating 'foldexpr' */ | 1899 // a previous error should not abort evaluating 'foldexpr' |
1901 did_emsg = FALSE; | 1900 did_emsg = FALSE; |
1902 | 1901 |
1903 if (*wp->w_p_fdt != NUL) | 1902 if (*wp->w_p_fdt != NUL) |
1904 { | 1903 { |
1905 char_u dashes[MAX_LEVEL + 2]; | 1904 char_u dashes[MAX_LEVEL + 2]; |
1906 win_T *save_curwin; | 1905 win_T *save_curwin; |
1907 int level; | 1906 int level; |
1908 char_u *p; | 1907 char_u *p; |
1909 | 1908 |
1910 /* Set "v:foldstart" and "v:foldend". */ | 1909 // Set "v:foldstart" and "v:foldend". |
1911 set_vim_var_nr(VV_FOLDSTART, lnum); | 1910 set_vim_var_nr(VV_FOLDSTART, lnum); |
1912 set_vim_var_nr(VV_FOLDEND, lnume); | 1911 set_vim_var_nr(VV_FOLDEND, lnume); |
1913 | 1912 |
1914 /* Set "v:folddashes" to a string of "level" dashes. */ | 1913 // Set "v:folddashes" to a string of "level" dashes. |
1915 /* Set "v:foldlevel" to "level". */ | 1914 // Set "v:foldlevel" to "level". |
1916 level = foldinfo->fi_level; | 1915 level = foldinfo->fi_level; |
1917 if (level > (int)sizeof(dashes) - 1) | 1916 if (level > (int)sizeof(dashes) - 1) |
1918 level = (int)sizeof(dashes) - 1; | 1917 level = (int)sizeof(dashes) - 1; |
1919 vim_memset(dashes, '-', (size_t)level); | 1918 vim_memset(dashes, '-', (size_t)level); |
1920 dashes[level] = NUL; | 1919 dashes[level] = NUL; |
1921 set_vim_var_string(VV_FOLDDASHES, dashes, -1); | 1920 set_vim_var_string(VV_FOLDDASHES, dashes, -1); |
1922 set_vim_var_nr(VV_FOLDLEVEL, (long)level); | 1921 set_vim_var_nr(VV_FOLDLEVEL, (long)level); |
1923 | 1922 |
1924 /* skip evaluating foldtext on errors */ | 1923 // skip evaluating foldtext on errors |
1925 if (!got_fdt_error) | 1924 if (!got_fdt_error) |
1926 { | 1925 { |
1927 save_curwin = curwin; | 1926 save_curwin = curwin; |
1928 curwin = wp; | 1927 curwin = wp; |
1929 curbuf = wp->w_buffer; | 1928 curbuf = wp->w_buffer; |
1930 | 1929 |
1931 ++emsg_silent; /* handle exceptions, but don't display errors */ | 1930 ++emsg_silent; // handle exceptions, but don't display errors |
1932 text = eval_to_string_safe(wp->w_p_fdt, NULL, | 1931 text = eval_to_string_safe(wp->w_p_fdt, NULL, |
1933 was_set_insecurely((char_u *)"foldtext", OPT_LOCAL)); | 1932 was_set_insecurely((char_u *)"foldtext", OPT_LOCAL)); |
1934 --emsg_silent; | 1933 --emsg_silent; |
1935 | 1934 |
1936 if (text == NULL || did_emsg) | 1935 if (text == NULL || did_emsg) |
1946 if (!did_emsg && save_did_emsg) | 1945 if (!did_emsg && save_did_emsg) |
1947 did_emsg = save_did_emsg; | 1946 did_emsg = save_did_emsg; |
1948 | 1947 |
1949 if (text != NULL) | 1948 if (text != NULL) |
1950 { | 1949 { |
1951 /* Replace unprintable characters, if there are any. But | 1950 // Replace unprintable characters, if there are any. But |
1952 * replace a TAB with a space. */ | 1951 // replace a TAB with a space. |
1953 for (p = text; *p != NUL; ++p) | 1952 for (p = text; *p != NUL; ++p) |
1954 { | 1953 { |
1955 int len; | 1954 int len; |
1956 | 1955 |
1957 if (has_mbyte && (len = (*mb_ptr2len)(p)) > 1) | 1956 if (has_mbyte && (len = (*mb_ptr2len)(p)) > 1) |
1986 text = buf; | 1985 text = buf; |
1987 } | 1986 } |
1988 return text; | 1987 return text; |
1989 } | 1988 } |
1990 | 1989 |
1991 /* foldtext_cleanup() {{{2 */ | 1990 // foldtext_cleanup() {{{2 |
1992 #ifdef FEAT_EVAL | 1991 #ifdef FEAT_EVAL |
1993 /* | 1992 /* |
1994 * Remove 'foldmarker' and 'commentstring' from "str" (in-place). | 1993 * Remove 'foldmarker' and 'commentstring' from "str" (in-place). |
1995 */ | 1994 */ |
1996 static void | 1995 static void |
1997 foldtext_cleanup(char_u *str) | 1996 foldtext_cleanup(char_u *str) |
1998 { | 1997 { |
1999 char_u *cms_start; /* first part or the whole comment */ | 1998 char_u *cms_start; // first part or the whole comment |
2000 int cms_slen = 0; /* length of cms_start */ | 1999 int cms_slen = 0; // length of cms_start |
2001 char_u *cms_end; /* last part of the comment or NULL */ | 2000 char_u *cms_end; // last part of the comment or NULL |
2002 int cms_elen = 0; /* length of cms_end */ | 2001 int cms_elen = 0; // length of cms_end |
2003 char_u *s; | 2002 char_u *s; |
2004 char_u *p; | 2003 char_u *p; |
2005 int len; | 2004 int len; |
2006 int did1 = FALSE; | 2005 int did1 = FALSE; |
2007 int did2 = FALSE; | 2006 int did2 = FALSE; |
2008 | 2007 |
2009 /* Ignore leading and trailing white space in 'commentstring'. */ | 2008 // Ignore leading and trailing white space in 'commentstring'. |
2010 cms_start = skipwhite(curbuf->b_p_cms); | 2009 cms_start = skipwhite(curbuf->b_p_cms); |
2011 cms_slen = (int)STRLEN(cms_start); | 2010 cms_slen = (int)STRLEN(cms_start); |
2012 while (cms_slen > 0 && VIM_ISWHITE(cms_start[cms_slen - 1])) | 2011 while (cms_slen > 0 && VIM_ISWHITE(cms_start[cms_slen - 1])) |
2013 --cms_slen; | 2012 --cms_slen; |
2014 | 2013 |
2015 /* locate "%s" in 'commentstring', use the part before and after it. */ | 2014 // locate "%s" in 'commentstring', use the part before and after it. |
2016 cms_end = (char_u *)strstr((char *)cms_start, "%s"); | 2015 cms_end = (char_u *)strstr((char *)cms_start, "%s"); |
2017 if (cms_end != NULL) | 2016 if (cms_end != NULL) |
2018 { | 2017 { |
2019 cms_elen = cms_slen - (int)(cms_end - cms_start); | 2018 cms_elen = cms_slen - (int)(cms_end - cms_start); |
2020 cms_slen = (int)(cms_end - cms_start); | 2019 cms_slen = (int)(cms_end - cms_start); |
2021 | 2020 |
2022 /* exclude white space before "%s" */ | 2021 // exclude white space before "%s" |
2023 while (cms_slen > 0 && VIM_ISWHITE(cms_start[cms_slen - 1])) | 2022 while (cms_slen > 0 && VIM_ISWHITE(cms_start[cms_slen - 1])) |
2024 --cms_slen; | 2023 --cms_slen; |
2025 | 2024 |
2026 /* skip "%s" and white space after it */ | 2025 // skip "%s" and white space after it |
2027 s = skipwhite(cms_end + 2); | 2026 s = skipwhite(cms_end + 2); |
2028 cms_elen -= (int)(s - cms_end); | 2027 cms_elen -= (int)(s - cms_end); |
2029 cms_end = s; | 2028 cms_end = s; |
2030 } | 2029 } |
2031 parseMarker(curwin); | 2030 parseMarker(curwin); |
2040 if (len > 0) | 2039 if (len > 0) |
2041 { | 2040 { |
2042 if (VIM_ISDIGIT(s[len])) | 2041 if (VIM_ISDIGIT(s[len])) |
2043 ++len; | 2042 ++len; |
2044 | 2043 |
2045 /* May remove 'commentstring' start. Useful when it's a double | 2044 // May remove 'commentstring' start. Useful when it's a double |
2046 * quote and we already removed a double quote. */ | 2045 // quote and we already removed a double quote. |
2047 for (p = s; p > str && VIM_ISWHITE(p[-1]); --p) | 2046 for (p = s; p > str && VIM_ISWHITE(p[-1]); --p) |
2048 ; | 2047 ; |
2049 if (p >= str + cms_slen | 2048 if (p >= str + cms_slen |
2050 && STRNCMP(p - cms_slen, cms_start, cms_slen) == 0) | 2049 && STRNCMP(p - cms_slen, cms_start, cms_slen) == 0) |
2051 { | 2050 { |
2079 } | 2078 } |
2080 } | 2079 } |
2081 } | 2080 } |
2082 #endif | 2081 #endif |
2083 | 2082 |
2084 /* Folding by indent, expr, marker and syntax. {{{1 */ | 2083 // Folding by indent, expr, marker and syntax. {{{1 |
2085 /* Define "fline_T", passed to get fold level for a line. {{{2 */ | 2084 // Define "fline_T", passed to get fold level for a line. {{{2 |
2086 typedef struct | 2085 typedef struct |
2087 { | 2086 { |
2088 win_T *wp; /* window */ | 2087 win_T *wp; // window |
2089 linenr_T lnum; /* current line number */ | 2088 linenr_T lnum; // current line number |
2090 linenr_T off; /* offset between lnum and real line number */ | 2089 linenr_T off; // offset between lnum and real line number |
2091 linenr_T lnum_save; /* line nr used by foldUpdateIEMSRecurse() */ | 2090 linenr_T lnum_save; // line nr used by foldUpdateIEMSRecurse() |
2092 int lvl; /* current level (-1 for undefined) */ | 2091 int lvl; // current level (-1 for undefined) |
2093 int lvl_next; /* level used for next line */ | 2092 int lvl_next; // level used for next line |
2094 int start; /* number of folds that are forced to start at | 2093 int start; // number of folds that are forced to start at |
2095 this line. */ | 2094 // this line. |
2096 int end; /* level of fold that is forced to end below | 2095 int end; // level of fold that is forced to end below |
2097 this line */ | 2096 // this line |
2098 int had_end; /* level of fold that is forced to end above | 2097 int had_end; // level of fold that is forced to end above |
2099 this line (copy of "end" of prev. line) */ | 2098 // this line (copy of "end" of prev. line) |
2100 } fline_T; | 2099 } fline_T; |
2101 | 2100 |
2102 /* Flag is set when redrawing is needed. */ | 2101 // Flag is set when redrawing is needed. |
2103 static int fold_changed; | 2102 static int fold_changed; |
2104 | 2103 |
2105 /* Function declarations. {{{2 */ | 2104 // Function declarations. {{{2 |
2106 static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level, linenr_T startlnum, fline_T *flp, void (*getlevel)(fline_T *), linenr_T bot, int topflags); | 2105 static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level, linenr_T startlnum, fline_T *flp, void (*getlevel)(fline_T *), linenr_T bot, int topflags); |
2107 static int foldInsert(garray_T *gap, int i); | 2106 static int foldInsert(garray_T *gap, int i); |
2108 static void foldSplit(garray_T *gap, int i, linenr_T top, linenr_T bot); | 2107 static void foldSplit(garray_T *gap, int i, linenr_T top, linenr_T bot); |
2109 static void foldRemove(garray_T *gap, linenr_T top, linenr_T bot); | 2108 static void foldRemove(garray_T *gap, linenr_T top, linenr_T bot); |
2110 static void foldMerge(fold_T *fp1, garray_T *gap, fold_T *fp2); | 2109 static void foldMerge(fold_T *fp1, garray_T *gap, fold_T *fp2); |
2114 #endif | 2113 #endif |
2115 static void foldlevelExpr(fline_T *flp); | 2114 static void foldlevelExpr(fline_T *flp); |
2116 static void foldlevelMarker(fline_T *flp); | 2115 static void foldlevelMarker(fline_T *flp); |
2117 static void foldlevelSyntax(fline_T *flp); | 2116 static void foldlevelSyntax(fline_T *flp); |
2118 | 2117 |
2119 /* foldUpdateIEMS() {{{2 */ | 2118 // foldUpdateIEMS() {{{2 |
2120 /* | 2119 /* |
2121 * Update the folding for window "wp", at least from lines "top" to "bot". | 2120 * Update the folding for window "wp", at least from lines "top" to "bot". |
2122 * Return TRUE if any folds did change. | 2121 * Return TRUE if any folds did change. |
2123 */ | 2122 */ |
2124 static void | 2123 static void |
2129 fline_T fline; | 2128 fline_T fline; |
2130 void (*getlevel)(fline_T *); | 2129 void (*getlevel)(fline_T *); |
2131 int level; | 2130 int level; |
2132 fold_T *fp; | 2131 fold_T *fp; |
2133 | 2132 |
2134 /* Avoid problems when being called recursively. */ | 2133 // Avoid problems when being called recursively. |
2135 if (invalid_top != (linenr_T)0) | 2134 if (invalid_top != (linenr_T)0) |
2136 return; | 2135 return; |
2137 | 2136 |
2138 if (wp->w_foldinvalid) | 2137 if (wp->w_foldinvalid) |
2139 { | 2138 { |
2140 /* Need to update all folds. */ | 2139 // Need to update all folds. |
2141 top = 1; | 2140 top = 1; |
2142 bot = wp->w_buffer->b_ml.ml_line_count; | 2141 bot = wp->w_buffer->b_ml.ml_line_count; |
2143 wp->w_foldinvalid = FALSE; | 2142 wp->w_foldinvalid = FALSE; |
2144 | 2143 |
2145 /* Mark all folds a maybe-small. */ | 2144 // Mark all folds a maybe-small. |
2146 setSmallMaybe(&wp->w_folds); | 2145 setSmallMaybe(&wp->w_folds); |
2147 } | 2146 } |
2148 | 2147 |
2149 #ifdef FEAT_DIFF | 2148 #ifdef FEAT_DIFF |
2150 /* add the context for "diff" folding */ | 2149 // add the context for "diff" folding |
2151 if (foldmethodIsDiff(wp)) | 2150 if (foldmethodIsDiff(wp)) |
2152 { | 2151 { |
2153 if (top > diff_context) | 2152 if (top > diff_context) |
2154 top -= diff_context; | 2153 top -= diff_context; |
2155 else | 2154 else |
2156 top = 1; | 2155 top = 1; |
2157 bot += diff_context; | 2156 bot += diff_context; |
2158 } | 2157 } |
2159 #endif | 2158 #endif |
2160 | 2159 |
2161 /* When deleting lines at the end of the buffer "top" can be past the end | 2160 // When deleting lines at the end of the buffer "top" can be past the end |
2162 * of the buffer. */ | 2161 // of the buffer. |
2163 if (top > wp->w_buffer->b_ml.ml_line_count) | 2162 if (top > wp->w_buffer->b_ml.ml_line_count) |
2164 top = wp->w_buffer->b_ml.ml_line_count; | 2163 top = wp->w_buffer->b_ml.ml_line_count; |
2165 | 2164 |
2166 fold_changed = FALSE; | 2165 fold_changed = FALSE; |
2167 fline.wp = wp; | 2166 fline.wp = wp; |
2177 | 2176 |
2178 if (foldmethodIsMarker(wp)) | 2177 if (foldmethodIsMarker(wp)) |
2179 { | 2178 { |
2180 getlevel = foldlevelMarker; | 2179 getlevel = foldlevelMarker; |
2181 | 2180 |
2182 /* Init marker variables to speed up foldlevelMarker(). */ | 2181 // Init marker variables to speed up foldlevelMarker(). |
2183 parseMarker(wp); | 2182 parseMarker(wp); |
2184 | 2183 |
2185 /* Need to get the level of the line above top, it is used if there is | 2184 // Need to get the level of the line above top, it is used if there is |
2186 * no marker at the top. */ | 2185 // no marker at the top. |
2187 if (top > 1) | 2186 if (top > 1) |
2188 { | 2187 { |
2189 /* Get the fold level at top - 1. */ | 2188 // Get the fold level at top - 1. |
2190 level = foldLevelWin(wp, top - 1); | 2189 level = foldLevelWin(wp, top - 1); |
2191 | 2190 |
2192 /* The fold may end just above the top, check for that. */ | 2191 // The fold may end just above the top, check for that. |
2193 fline.lnum = top - 1; | 2192 fline.lnum = top - 1; |
2194 fline.lvl = level; | 2193 fline.lvl = level; |
2195 getlevel(&fline); | 2194 getlevel(&fline); |
2196 | 2195 |
2197 /* If a fold started here, we already had the level, if it stops | 2196 // If a fold started here, we already had the level, if it stops |
2198 * here, we need to use lvl_next. Could also start and end a fold | 2197 // here, we need to use lvl_next. Could also start and end a fold |
2199 * in the same line. */ | 2198 // in the same line. |
2200 if (fline.lvl > level) | 2199 if (fline.lvl > level) |
2201 fline.lvl = level - (fline.lvl - fline.lvl_next); | 2200 fline.lvl = level - (fline.lvl - fline.lvl_next); |
2202 else | 2201 else |
2203 fline.lvl = fline.lvl_next; | 2202 fline.lvl = fline.lvl_next; |
2204 } | 2203 } |
2209 { | 2208 { |
2210 fline.lnum = top; | 2209 fline.lnum = top; |
2211 if (foldmethodIsExpr(wp)) | 2210 if (foldmethodIsExpr(wp)) |
2212 { | 2211 { |
2213 getlevel = foldlevelExpr; | 2212 getlevel = foldlevelExpr; |
2214 /* start one line back, because a "<1" may indicate the end of a | 2213 // start one line back, because a "<1" may indicate the end of a |
2215 * fold in the topline */ | 2214 // fold in the topline |
2216 if (top > 1) | 2215 if (top > 1) |
2217 --fline.lnum; | 2216 --fline.lnum; |
2218 } | 2217 } |
2219 else if (foldmethodIsSyntax(wp)) | 2218 else if (foldmethodIsSyntax(wp)) |
2220 getlevel = foldlevelSyntax; | 2219 getlevel = foldlevelSyntax; |
2223 getlevel = foldlevelDiff; | 2222 getlevel = foldlevelDiff; |
2224 #endif | 2223 #endif |
2225 else | 2224 else |
2226 getlevel = foldlevelIndent; | 2225 getlevel = foldlevelIndent; |
2227 | 2226 |
2228 /* Backup to a line for which the fold level is defined. Since it's | 2227 // Backup to a line for which the fold level is defined. Since it's |
2229 * always defined for line one, we will stop there. */ | 2228 // always defined for line one, we will stop there. |
2230 fline.lvl = -1; | 2229 fline.lvl = -1; |
2231 for ( ; !got_int; --fline.lnum) | 2230 for ( ; !got_int; --fline.lnum) |
2232 { | 2231 { |
2233 /* Reset lvl_next each time, because it will be set to a value for | 2232 // Reset lvl_next each time, because it will be set to a value for |
2234 * the next line, but we search backwards here. */ | 2233 // the next line, but we search backwards here. |
2235 fline.lvl_next = -1; | 2234 fline.lvl_next = -1; |
2236 getlevel(&fline); | 2235 getlevel(&fline); |
2237 if (fline.lvl >= 0) | 2236 if (fline.lvl >= 0) |
2238 break; | 2237 break; |
2239 } | 2238 } |
2273 } | 2272 } |
2274 } | 2273 } |
2275 | 2274 |
2276 start = fline.lnum; | 2275 start = fline.lnum; |
2277 end = bot; | 2276 end = bot; |
2278 /* Do at least one line. */ | 2277 // Do at least one line. |
2279 if (start > end && end < wp->w_buffer->b_ml.ml_line_count) | 2278 if (start > end && end < wp->w_buffer->b_ml.ml_line_count) |
2280 end = start; | 2279 end = start; |
2281 while (!got_int) | 2280 while (!got_int) |
2282 { | 2281 { |
2283 /* Always stop at the end of the file ("end" can be past the end of | 2282 // Always stop at the end of the file ("end" can be past the end of |
2284 * the file). */ | 2283 // the file). |
2285 if (fline.lnum > wp->w_buffer->b_ml.ml_line_count) | 2284 if (fline.lnum > wp->w_buffer->b_ml.ml_line_count) |
2286 break; | 2285 break; |
2287 if (fline.lnum > end) | 2286 if (fline.lnum > end) |
2288 { | 2287 { |
2289 /* For "marker", "expr" and "syntax" methods: If a change caused | 2288 // For "marker", "expr" and "syntax" methods: If a change caused |
2290 * a fold to be removed, we need to continue at least until where | 2289 // a fold to be removed, we need to continue at least until where |
2291 * it ended. */ | 2290 // it ended. |
2292 if (getlevel != foldlevelMarker | 2291 if (getlevel != foldlevelMarker |
2293 && getlevel != foldlevelSyntax | 2292 && getlevel != foldlevelSyntax |
2294 && getlevel != foldlevelExpr) | 2293 && getlevel != foldlevelExpr) |
2295 break; | 2294 break; |
2296 if ((start <= end | 2295 if ((start <= end |
2300 && foldFind(&wp->w_folds, fline.lnum, &fp) | 2299 && foldFind(&wp->w_folds, fline.lnum, &fp) |
2301 && fp->fd_top < fline.lnum)) | 2300 && fp->fd_top < fline.lnum)) |
2302 end = fp->fd_top + fp->fd_len - 1; | 2301 end = fp->fd_top + fp->fd_len - 1; |
2303 else if (getlevel == foldlevelSyntax | 2302 else if (getlevel == foldlevelSyntax |
2304 && foldLevelWin(wp, fline.lnum) != fline.lvl) | 2303 && foldLevelWin(wp, fline.lnum) != fline.lvl) |
2305 /* For "syntax" method: Compare the foldlevel that the syntax | 2304 // For "syntax" method: Compare the foldlevel that the syntax |
2306 * tells us to the foldlevel from the existing folds. If they | 2305 // tells us to the foldlevel from the existing folds. If they |
2307 * don't match continue updating folds. */ | 2306 // don't match continue updating folds. |
2308 end = fline.lnum; | 2307 end = fline.lnum; |
2309 else | 2308 else |
2310 break; | 2309 break; |
2311 } | 2310 } |
2312 | 2311 |
2313 /* A level 1 fold starts at a line with foldlevel > 0. */ | 2312 // A level 1 fold starts at a line with foldlevel > 0. |
2314 if (fline.lvl > 0) | 2313 if (fline.lvl > 0) |
2315 { | 2314 { |
2316 invalid_top = fline.lnum; | 2315 invalid_top = fline.lnum; |
2317 invalid_bot = end; | 2316 invalid_bot = end; |
2318 end = foldUpdateIEMSRecurse(&wp->w_folds, | 2317 end = foldUpdateIEMSRecurse(&wp->w_folds, |
2327 fline.lvl = fline.lvl_next; | 2326 fline.lvl = fline.lvl_next; |
2328 getlevel(&fline); | 2327 getlevel(&fline); |
2329 } | 2328 } |
2330 } | 2329 } |
2331 | 2330 |
2332 /* There can't be any folds from start until end now. */ | 2331 // There can't be any folds from start until end now. |
2333 foldRemove(&wp->w_folds, start, end); | 2332 foldRemove(&wp->w_folds, start, end); |
2334 | 2333 |
2335 /* If some fold changed, need to redraw and position cursor. */ | 2334 // If some fold changed, need to redraw and position cursor. |
2336 if (fold_changed && wp->w_p_fen) | 2335 if (fold_changed && wp->w_p_fen) |
2337 changed_window_setting_win(wp); | 2336 changed_window_setting_win(wp); |
2338 | 2337 |
2339 /* If we updated folds past "bot", need to redraw more lines. Don't do | 2338 // If we updated folds past "bot", need to redraw more lines. Don't do |
2340 * this in other situations, the changed lines will be redrawn anyway and | 2339 // this in other situations, the changed lines will be redrawn anyway and |
2341 * this method can cause the whole window to be updated. */ | 2340 // this method can cause the whole window to be updated. |
2342 if (end != bot) | 2341 if (end != bot) |
2343 { | 2342 { |
2344 if (wp->w_redraw_top == 0 || wp->w_redraw_top > top) | 2343 if (wp->w_redraw_top == 0 || wp->w_redraw_top > top) |
2345 wp->w_redraw_top = top; | 2344 wp->w_redraw_top = top; |
2346 if (wp->w_redraw_bot < end) | 2345 if (wp->w_redraw_bot < end) |
2348 } | 2347 } |
2349 | 2348 |
2350 invalid_top = (linenr_T)0; | 2349 invalid_top = (linenr_T)0; |
2351 } | 2350 } |
2352 | 2351 |
2353 /* foldUpdateIEMSRecurse() {{{2 */ | 2352 // foldUpdateIEMSRecurse() {{{2 |
2354 /* | 2353 /* |
2355 * Update a fold that starts at "flp->lnum". At this line there is always a | 2354 * Update a fold that starts at "flp->lnum". At this line there is always a |
2356 * valid foldlevel, and its level >= "level". | 2355 * valid foldlevel, and its level >= "level". |
2357 * "flp" is valid for "flp->lnum" when called and it's valid when returning. | 2356 * "flp" is valid for "flp->lnum" when called and it's valid when returning. |
2358 * "flp->lnum" is set to the lnum just below the fold, if it ends before | 2357 * "flp->lnum" is set to the lnum just below the fold, if it ends before |
2380 int level, | 2379 int level, |
2381 linenr_T startlnum, | 2380 linenr_T startlnum, |
2382 fline_T *flp, | 2381 fline_T *flp, |
2383 void (*getlevel)(fline_T *), | 2382 void (*getlevel)(fline_T *), |
2384 linenr_T bot, | 2383 linenr_T bot, |
2385 int topflags) /* flags used by containing fold */ | 2384 int topflags) // flags used by containing fold |
2386 { | 2385 { |
2387 linenr_T ll; | 2386 linenr_T ll; |
2388 fold_T *fp = NULL; | 2387 fold_T *fp = NULL; |
2389 fold_T *fp2; | 2388 fold_T *fp2; |
2390 int lvl = level; | 2389 int lvl = level; |
2391 linenr_T startlnum2 = startlnum; | 2390 linenr_T startlnum2 = startlnum; |
2392 linenr_T firstlnum = flp->lnum; /* first lnum we got */ | 2391 linenr_T firstlnum = flp->lnum; // first lnum we got |
2393 int i; | 2392 int i; |
2394 int finish = FALSE; | 2393 int finish = FALSE; |
2395 linenr_T linecount = flp->wp->w_buffer->b_ml.ml_line_count - flp->off; | 2394 linenr_T linecount = flp->wp->w_buffer->b_ml.ml_line_count - flp->off; |
2396 int concat; | 2395 int concat; |
2397 | 2396 |
2422 * valid, thus "flp->lnum_save" is equal to "flp->lnum". | 2421 * valid, thus "flp->lnum_save" is equal to "flp->lnum". |
2423 */ | 2422 */ |
2424 flp->lnum_save = flp->lnum; | 2423 flp->lnum_save = flp->lnum; |
2425 while (!got_int) | 2424 while (!got_int) |
2426 { | 2425 { |
2427 /* Updating folds can be slow, check for CTRL-C. */ | 2426 // Updating folds can be slow, check for CTRL-C. |
2428 line_breakcheck(); | 2427 line_breakcheck(); |
2429 | 2428 |
2430 /* Set "lvl" to the level of line "flp->lnum". When flp->start is set | 2429 // Set "lvl" to the level of line "flp->lnum". When flp->start is set |
2431 * and after the first line of the fold, set the level to zero to | 2430 // and after the first line of the fold, set the level to zero to |
2432 * force the fold to end. Do the same when had_end is set: Previous | 2431 // force the fold to end. Do the same when had_end is set: Previous |
2433 * line was marked as end of a fold. */ | 2432 // line was marked as end of a fold. |
2434 lvl = flp->lvl; | 2433 lvl = flp->lvl; |
2435 if (lvl > MAX_LEVEL) | 2434 if (lvl > MAX_LEVEL) |
2436 lvl = MAX_LEVEL; | 2435 lvl = MAX_LEVEL; |
2437 if (flp->lnum > firstlnum | 2436 if (flp->lnum > firstlnum |
2438 && (level > lvl - flp->start || level >= flp->had_end)) | 2437 && (level > lvl - flp->start || level >= flp->had_end)) |
2439 lvl = 0; | 2438 lvl = 0; |
2440 | 2439 |
2441 if (flp->lnum > bot && !finish && fp != NULL) | 2440 if (flp->lnum > bot && !finish && fp != NULL) |
2442 { | 2441 { |
2443 /* For "marker" and "syntax" methods: | 2442 // For "marker" and "syntax" methods: |
2444 * - If a change caused a nested fold to be removed, we need to | 2443 // - If a change caused a nested fold to be removed, we need to |
2445 * delete it and continue at least until where it ended. | 2444 // delete it and continue at least until where it ended. |
2446 * - If a change caused a nested fold to be created, or this fold | 2445 // - If a change caused a nested fold to be created, or this fold |
2447 * to continue below its original end, need to finish this fold. | 2446 // to continue below its original end, need to finish this fold. |
2448 */ | |
2449 if (getlevel != foldlevelMarker | 2447 if (getlevel != foldlevelMarker |
2450 && getlevel != foldlevelExpr | 2448 && getlevel != foldlevelExpr |
2451 && getlevel != foldlevelSyntax) | 2449 && getlevel != foldlevelSyntax) |
2452 break; | 2450 break; |
2453 i = 0; | 2451 i = 0; |
2454 fp2 = fp; | 2452 fp2 = fp; |
2455 if (lvl >= level) | 2453 if (lvl >= level) |
2456 { | 2454 { |
2457 /* Compute how deep the folds currently are, if it's deeper | 2455 // Compute how deep the folds currently are, if it's deeper |
2458 * than "lvl" then some must be deleted, need to update | 2456 // than "lvl" then some must be deleted, need to update |
2459 * at least one nested fold. */ | 2457 // at least one nested fold. |
2460 ll = flp->lnum - fp->fd_top; | 2458 ll = flp->lnum - fp->fd_top; |
2461 while (foldFind(&fp2->fd_nested, ll, &fp2)) | 2459 while (foldFind(&fp2->fd_nested, ll, &fp2)) |
2462 { | 2460 { |
2463 ++i; | 2461 ++i; |
2464 ll -= fp2->fd_top; | 2462 ll -= fp2->fd_top; |
2474 finish = TRUE; | 2472 finish = TRUE; |
2475 else | 2473 else |
2476 break; | 2474 break; |
2477 } | 2475 } |
2478 | 2476 |
2479 /* At the start of the first nested fold and at the end of the current | 2477 // At the start of the first nested fold and at the end of the current |
2480 * fold: check if existing folds at this level, before the current | 2478 // fold: check if existing folds at this level, before the current |
2481 * one, need to be deleted or truncated. */ | 2479 // one, need to be deleted or truncated. |
2482 if (fp == NULL | 2480 if (fp == NULL |
2483 && (lvl != level | 2481 && (lvl != level |
2484 || flp->lnum_save >= bot | 2482 || flp->lnum_save >= bot |
2485 || flp->start != 0 | 2483 || flp->start != 0 |
2486 || flp->had_end <= MAX_LEVEL | 2484 || flp->had_end <= MAX_LEVEL |
2490 * Remove or update folds that have lines between startlnum and | 2488 * Remove or update folds that have lines between startlnum and |
2491 * firstlnum. | 2489 * firstlnum. |
2492 */ | 2490 */ |
2493 while (!got_int) | 2491 while (!got_int) |
2494 { | 2492 { |
2495 /* set concat to 1 if it's allowed to concatenated this fold | 2493 // set concat to 1 if it's allowed to concatenated this fold |
2496 * with a previous one that touches it. */ | 2494 // with a previous one that touches it. |
2497 if (flp->start != 0 || flp->had_end <= MAX_LEVEL) | 2495 if (flp->start != 0 || flp->had_end <= MAX_LEVEL) |
2498 concat = 0; | 2496 concat = 0; |
2499 else | 2497 else |
2500 concat = 1; | 2498 concat = 1; |
2501 | 2499 |
2502 /* Find an existing fold to re-use. Preferably one that | 2500 // Find an existing fold to re-use. Preferably one that |
2503 * includes startlnum, otherwise one that ends just before | 2501 // includes startlnum, otherwise one that ends just before |
2504 * startlnum or starts after it. */ | 2502 // startlnum or starts after it. |
2505 if (foldFind(gap, startlnum, &fp) | 2503 if (foldFind(gap, startlnum, &fp) |
2506 || (fp < ((fold_T *)gap->ga_data) + gap->ga_len | 2504 || (fp < ((fold_T *)gap->ga_data) + gap->ga_len |
2507 && fp->fd_top <= firstlnum) | 2505 && fp->fd_top <= firstlnum) |
2508 || foldFind(gap, firstlnum - concat, &fp) | 2506 || foldFind(gap, firstlnum - concat, &fp) |
2509 || (fp < ((fold_T *)gap->ga_data) + gap->ga_len | 2507 || (fp < ((fold_T *)gap->ga_data) + gap->ga_len |
2511 || (lvl >= level | 2509 || (lvl >= level |
2512 && fp->fd_top <= flp->lnum_save)))) | 2510 && fp->fd_top <= flp->lnum_save)))) |
2513 { | 2511 { |
2514 if (fp->fd_top + fp->fd_len + concat > firstlnum) | 2512 if (fp->fd_top + fp->fd_len + concat > firstlnum) |
2515 { | 2513 { |
2516 /* Use existing fold for the new fold. If it starts | 2514 // Use existing fold for the new fold. If it starts |
2517 * before where we started looking, extend it. If it | 2515 // before where we started looking, extend it. If it |
2518 * starts at another line, update nested folds to keep | 2516 // starts at another line, update nested folds to keep |
2519 * their position, compensating for the new fd_top. */ | 2517 // their position, compensating for the new fd_top. |
2520 if (fp->fd_top == firstlnum) | 2518 if (fp->fd_top == firstlnum) |
2521 { | 2519 { |
2522 /* have found a fold beginning where we want */ | 2520 // have found a fold beginning where we want |
2523 } | 2521 } |
2524 else if (fp->fd_top >= startlnum) | 2522 else if (fp->fd_top >= startlnum) |
2525 { | 2523 { |
2526 if (fp->fd_top > firstlnum) | 2524 if (fp->fd_top > firstlnum) |
2527 /* like lines are inserted */ | 2525 // like lines are inserted |
2528 foldMarkAdjustRecurse(&fp->fd_nested, | 2526 foldMarkAdjustRecurse(&fp->fd_nested, |
2529 (linenr_T)0, (linenr_T)MAXLNUM, | 2527 (linenr_T)0, (linenr_T)MAXLNUM, |
2530 (long)(fp->fd_top - firstlnum), 0L); | 2528 (long)(fp->fd_top - firstlnum), 0L); |
2531 else | 2529 else |
2532 /* like lines are deleted */ | 2530 // like lines are deleted |
2533 foldMarkAdjustRecurse(&fp->fd_nested, | 2531 foldMarkAdjustRecurse(&fp->fd_nested, |
2534 (linenr_T)0, | 2532 (linenr_T)0, |
2535 (long)(firstlnum - fp->fd_top - 1), | 2533 (long)(firstlnum - fp->fd_top - 1), |
2536 (linenr_T)MAXLNUM, | 2534 (linenr_T)MAXLNUM, |
2537 (long)(fp->fd_top - firstlnum)); | 2535 (long)(fp->fd_top - firstlnum)); |
2575 breakend - fp->fd_top); | 2573 breakend - fp->fd_top); |
2576 i = (int)(fp - (fold_T *)gap->ga_data); | 2574 i = (int)(fp - (fold_T *)gap->ga_data); |
2577 foldSplit(gap, i, breakstart, breakend - 1); | 2575 foldSplit(gap, i, breakstart, breakend - 1); |
2578 fp = (fold_T *)gap->ga_data + i + 1; | 2576 fp = (fold_T *)gap->ga_data + i + 1; |
2579 | 2577 |
2580 /* If using the "marker" or "syntax" method, we | 2578 // If using the "marker" or "syntax" method, we |
2581 * need to continue until the end of the fold is | 2579 // need to continue until the end of the fold is |
2582 * found. */ | 2580 // found. |
2583 if (getlevel == foldlevelMarker | 2581 if (getlevel == foldlevelMarker |
2584 || getlevel == foldlevelExpr | 2582 || getlevel == foldlevelExpr |
2585 || getlevel == foldlevelSyntax) | 2583 || getlevel == foldlevelSyntax) |
2586 finish = TRUE; | 2584 finish = TRUE; |
2587 } | 2585 } |
2601 } | 2599 } |
2602 break; | 2600 break; |
2603 } | 2601 } |
2604 if (fp->fd_top >= startlnum) | 2602 if (fp->fd_top >= startlnum) |
2605 { | 2603 { |
2606 /* A fold that starts at or after startlnum and stops | 2604 // A fold that starts at or after startlnum and stops |
2607 * before the new fold must be deleted. Continue | 2605 // before the new fold must be deleted. Continue |
2608 * looking for the next one. */ | 2606 // looking for the next one. |
2609 deleteFoldEntry(gap, | 2607 deleteFoldEntry(gap, |
2610 (int)(fp - (fold_T *)gap->ga_data), TRUE); | 2608 (int)(fp - (fold_T *)gap->ga_data), TRUE); |
2611 } | 2609 } |
2612 else | 2610 else |
2613 { | 2611 { |
2614 /* A fold has some lines above startlnum, truncate it | 2612 // A fold has some lines above startlnum, truncate it |
2615 * to stop just above startlnum. */ | 2613 // to stop just above startlnum. |
2616 fp->fd_len = startlnum - fp->fd_top; | 2614 fp->fd_len = startlnum - fp->fd_top; |
2617 foldMarkAdjustRecurse(&fp->fd_nested, | 2615 foldMarkAdjustRecurse(&fp->fd_nested, |
2618 (linenr_T)fp->fd_len, (linenr_T)MAXLNUM, | 2616 (linenr_T)fp->fd_len, (linenr_T)MAXLNUM, |
2619 (linenr_T)MAXLNUM, 0L); | 2617 (linenr_T)MAXLNUM, 0L); |
2620 fold_changed = TRUE; | 2618 fold_changed = TRUE; |
2621 } | 2619 } |
2622 } | 2620 } |
2623 else | 2621 else |
2624 { | 2622 { |
2625 /* Insert new fold. Careful: ga_data may be NULL and it | 2623 // Insert new fold. Careful: ga_data may be NULL and it |
2626 * may change! */ | 2624 // may change! |
2627 i = (int)(fp - (fold_T *)gap->ga_data); | 2625 i = (int)(fp - (fold_T *)gap->ga_data); |
2628 if (foldInsert(gap, i) != OK) | 2626 if (foldInsert(gap, i) != OK) |
2629 return bot; | 2627 return bot; |
2630 fp = (fold_T *)gap->ga_data + i; | 2628 fp = (fold_T *)gap->ga_data + i; |
2631 /* The new fold continues until bot, unless we find the | 2629 // The new fold continues until bot, unless we find the |
2632 * end earlier. */ | 2630 // end earlier. |
2633 fp->fd_top = firstlnum; | 2631 fp->fd_top = firstlnum; |
2634 fp->fd_len = bot - firstlnum + 1; | 2632 fp->fd_len = bot - firstlnum + 1; |
2635 /* When the containing fold is open, the new fold is open. | 2633 // When the containing fold is open, the new fold is open. |
2636 * The new fold is closed if the fold above it is closed. | 2634 // The new fold is closed if the fold above it is closed. |
2637 * The first fold depends on the containing fold. */ | 2635 // The first fold depends on the containing fold. |
2638 if (topflags == FD_OPEN) | 2636 if (topflags == FD_OPEN) |
2639 { | 2637 { |
2640 flp->wp->w_fold_manual = TRUE; | 2638 flp->wp->w_fold_manual = TRUE; |
2641 fp->fd_flags = FD_OPEN; | 2639 fp->fd_flags = FD_OPEN; |
2642 } | 2640 } |
2647 flp->wp->w_fold_manual = TRUE; | 2645 flp->wp->w_fold_manual = TRUE; |
2648 } | 2646 } |
2649 else | 2647 else |
2650 fp->fd_flags = (fp - 1)->fd_flags; | 2648 fp->fd_flags = (fp - 1)->fd_flags; |
2651 fp->fd_small = MAYBE; | 2649 fp->fd_small = MAYBE; |
2652 /* If using the "marker", "expr" or "syntax" method, we | 2650 // If using the "marker", "expr" or "syntax" method, we |
2653 * need to continue until the end of the fold is found. */ | 2651 // need to continue until the end of the fold is found. |
2654 if (getlevel == foldlevelMarker | 2652 if (getlevel == foldlevelMarker |
2655 || getlevel == foldlevelExpr | 2653 || getlevel == foldlevelExpr |
2656 || getlevel == foldlevelSyntax) | 2654 || getlevel == foldlevelSyntax) |
2657 finish = TRUE; | 2655 finish = TRUE; |
2658 fold_changed = TRUE; | 2656 fold_changed = TRUE; |
2677 if (lvl > level && fp != NULL) | 2675 if (lvl > level && fp != NULL) |
2678 { | 2676 { |
2679 /* | 2677 /* |
2680 * There is a nested fold, handle it recursively. | 2678 * There is a nested fold, handle it recursively. |
2681 */ | 2679 */ |
2682 /* At least do one line (can happen when finish is TRUE). */ | 2680 // At least do one line (can happen when finish is TRUE). |
2683 if (bot < flp->lnum) | 2681 if (bot < flp->lnum) |
2684 bot = flp->lnum; | 2682 bot = flp->lnum; |
2685 | 2683 |
2686 /* Line numbers in the nested fold are relative to the start of | 2684 // Line numbers in the nested fold are relative to the start of |
2687 * this fold. */ | 2685 // this fold. |
2688 flp->lnum = flp->lnum_save - fp->fd_top; | 2686 flp->lnum = flp->lnum_save - fp->fd_top; |
2689 flp->off += fp->fd_top; | 2687 flp->off += fp->fd_top; |
2690 i = (int)(fp - (fold_T *)gap->ga_data); | 2688 i = (int)(fp - (fold_T *)gap->ga_data); |
2691 bot = foldUpdateIEMSRecurse(&fp->fd_nested, level + 1, | 2689 bot = foldUpdateIEMSRecurse(&fp->fd_nested, level + 1, |
2692 startlnum2 - fp->fd_top, flp, getlevel, | 2690 startlnum2 - fp->fd_top, flp, getlevel, |
2696 flp->lnum_save += fp->fd_top; | 2694 flp->lnum_save += fp->fd_top; |
2697 flp->off -= fp->fd_top; | 2695 flp->off -= fp->fd_top; |
2698 bot += fp->fd_top; | 2696 bot += fp->fd_top; |
2699 startlnum2 = flp->lnum; | 2697 startlnum2 = flp->lnum; |
2700 | 2698 |
2701 /* This fold may end at the same line, don't incr. flp->lnum. */ | 2699 // This fold may end at the same line, don't incr. flp->lnum. |
2702 } | 2700 } |
2703 else | 2701 else |
2704 { | 2702 { |
2705 /* | 2703 /* |
2706 * Get the level of the next line, then continue the loop to check | 2704 * Get the level of the next line, then continue the loop to check |
2710 */ | 2708 */ |
2711 flp->lnum = flp->lnum_save; | 2709 flp->lnum = flp->lnum_save; |
2712 ll = flp->lnum + 1; | 2710 ll = flp->lnum + 1; |
2713 while (!got_int) | 2711 while (!got_int) |
2714 { | 2712 { |
2715 /* Make the previous level available to foldlevel(). */ | 2713 // Make the previous level available to foldlevel(). |
2716 prev_lnum = flp->lnum; | 2714 prev_lnum = flp->lnum; |
2717 prev_lnum_lvl = flp->lvl; | 2715 prev_lnum_lvl = flp->lvl; |
2718 | 2716 |
2719 if (++flp->lnum > linecount) | 2717 if (++flp->lnum > linecount) |
2720 break; | 2718 break; |
2725 } | 2723 } |
2726 prev_lnum = 0; | 2724 prev_lnum = 0; |
2727 if (flp->lnum > linecount) | 2725 if (flp->lnum > linecount) |
2728 break; | 2726 break; |
2729 | 2727 |
2730 /* leave flp->lnum_save to lnum of the line that was used to get | 2728 // leave flp->lnum_save to lnum of the line that was used to get |
2731 * the level, flp->lnum to the lnum of the next line. */ | 2729 // the level, flp->lnum to the lnum of the next line. |
2732 flp->lnum_save = flp->lnum; | 2730 flp->lnum_save = flp->lnum; |
2733 flp->lnum = ll; | 2731 flp->lnum = ll; |
2734 } | 2732 } |
2735 } | 2733 } |
2736 | 2734 |
2737 if (fp == NULL) /* only happens when got_int is set */ | 2735 if (fp == NULL) // only happens when got_int is set |
2738 return bot; | 2736 return bot; |
2739 | 2737 |
2740 /* | 2738 /* |
2741 * Get here when: | 2739 * Get here when: |
2742 * lvl < level: the folds ends just above "flp->lnum" | 2740 * lvl < level: the folds ends just above "flp->lnum" |
2759 foldRemove(&fp->fd_nested, startlnum2 - fp->fd_top, | 2757 foldRemove(&fp->fd_nested, startlnum2 - fp->fd_top, |
2760 flp->lnum - 1 - fp->fd_top); | 2758 flp->lnum - 1 - fp->fd_top); |
2761 | 2759 |
2762 if (lvl < level) | 2760 if (lvl < level) |
2763 { | 2761 { |
2764 /* End of fold found, update the length when it got shorter. */ | 2762 // End of fold found, update the length when it got shorter. |
2765 if (fp->fd_len != flp->lnum - fp->fd_top) | 2763 if (fp->fd_len != flp->lnum - fp->fd_top) |
2766 { | 2764 { |
2767 if (fp->fd_top + fp->fd_len - 1 > bot) | 2765 if (fp->fd_top + fp->fd_len - 1 > bot) |
2768 { | 2766 { |
2769 /* fold continued below bot */ | 2767 // fold continued below bot |
2770 if (getlevel == foldlevelMarker | 2768 if (getlevel == foldlevelMarker |
2771 || getlevel == foldlevelExpr | 2769 || getlevel == foldlevelExpr |
2772 || getlevel == foldlevelSyntax) | 2770 || getlevel == foldlevelSyntax) |
2773 { | 2771 { |
2774 /* marker method: truncate the fold and make sure the | 2772 // marker method: truncate the fold and make sure the |
2775 * previously included lines are processed again */ | 2773 // previously included lines are processed again |
2776 bot = fp->fd_top + fp->fd_len - 1; | 2774 bot = fp->fd_top + fp->fd_len - 1; |
2777 fp->fd_len = flp->lnum - fp->fd_top; | 2775 fp->fd_len = flp->lnum - fp->fd_top; |
2778 } | 2776 } |
2779 else | 2777 else |
2780 { | 2778 { |
2781 /* indent or expr method: split fold to create a new one | 2779 // indent or expr method: split fold to create a new one |
2782 * below bot */ | 2780 // below bot |
2783 i = (int)(fp - (fold_T *)gap->ga_data); | 2781 i = (int)(fp - (fold_T *)gap->ga_data); |
2784 foldSplit(gap, i, flp->lnum, bot); | 2782 foldSplit(gap, i, flp->lnum, bot); |
2785 fp = (fold_T *)gap->ga_data + i; | 2783 fp = (fold_T *)gap->ga_data + i; |
2786 } | 2784 } |
2787 } | 2785 } |
2789 fp->fd_len = flp->lnum - fp->fd_top; | 2787 fp->fd_len = flp->lnum - fp->fd_top; |
2790 fold_changed = TRUE; | 2788 fold_changed = TRUE; |
2791 } | 2789 } |
2792 } | 2790 } |
2793 | 2791 |
2794 /* delete following folds that end before the current line */ | 2792 // delete following folds that end before the current line |
2795 for (;;) | 2793 for (;;) |
2796 { | 2794 { |
2797 fp2 = fp + 1; | 2795 fp2 = fp + 1; |
2798 if (fp2 >= (fold_T *)gap->ga_data + gap->ga_len | 2796 if (fp2 >= (fold_T *)gap->ga_data + gap->ga_len |
2799 || fp2->fd_top > flp->lnum) | 2797 || fp2->fd_top > flp->lnum) |
2800 break; | 2798 break; |
2801 if (fp2->fd_top + fp2->fd_len > flp->lnum) | 2799 if (fp2->fd_top + fp2->fd_len > flp->lnum) |
2802 { | 2800 { |
2803 if (fp2->fd_top < flp->lnum) | 2801 if (fp2->fd_top < flp->lnum) |
2804 { | 2802 { |
2805 /* Make fold that includes lnum start at lnum. */ | 2803 // Make fold that includes lnum start at lnum. |
2806 foldMarkAdjustRecurse(&fp2->fd_nested, | 2804 foldMarkAdjustRecurse(&fp2->fd_nested, |
2807 (linenr_T)0, (long)(flp->lnum - fp2->fd_top - 1), | 2805 (linenr_T)0, (long)(flp->lnum - fp2->fd_top - 1), |
2808 (linenr_T)MAXLNUM, (long)(fp2->fd_top - flp->lnum)); | 2806 (linenr_T)MAXLNUM, (long)(fp2->fd_top - flp->lnum)); |
2809 fp2->fd_len -= flp->lnum - fp2->fd_top; | 2807 fp2->fd_len -= flp->lnum - fp2->fd_top; |
2810 fp2->fd_top = flp->lnum; | 2808 fp2->fd_top = flp->lnum; |
2811 fold_changed = TRUE; | 2809 fold_changed = TRUE; |
2812 } | 2810 } |
2813 | 2811 |
2814 if (lvl >= level) | 2812 if (lvl >= level) |
2815 { | 2813 { |
2816 /* merge new fold with existing fold that follows */ | 2814 // merge new fold with existing fold that follows |
2817 foldMerge(fp, gap, fp2); | 2815 foldMerge(fp, gap, fp2); |
2818 } | 2816 } |
2819 break; | 2817 break; |
2820 } | 2818 } |
2821 fold_changed = TRUE; | 2819 fold_changed = TRUE; |
2822 deleteFoldEntry(gap, (int)(fp2 - (fold_T *)gap->ga_data), TRUE); | 2820 deleteFoldEntry(gap, (int)(fp2 - (fold_T *)gap->ga_data), TRUE); |
2823 } | 2821 } |
2824 | 2822 |
2825 /* Need to redraw the lines we inspected, which might be further down than | 2823 // Need to redraw the lines we inspected, which might be further down than |
2826 * was asked for. */ | 2824 // was asked for. |
2827 if (bot < flp->lnum - 1) | 2825 if (bot < flp->lnum - 1) |
2828 bot = flp->lnum - 1; | 2826 bot = flp->lnum - 1; |
2829 | 2827 |
2830 return bot; | 2828 return bot; |
2831 } | 2829 } |
2832 | 2830 |
2833 /* foldInsert() {{{2 */ | 2831 // foldInsert() {{{2 |
2834 /* | 2832 /* |
2835 * Insert a new fold in "gap" at position "i". | 2833 * Insert a new fold in "gap" at position "i". |
2836 * Returns OK for success, FAIL for failure. | 2834 * Returns OK for success, FAIL for failure. |
2837 */ | 2835 */ |
2838 static int | 2836 static int |
2848 ++gap->ga_len; | 2846 ++gap->ga_len; |
2849 ga_init2(&fp->fd_nested, (int)sizeof(fold_T), 10); | 2847 ga_init2(&fp->fd_nested, (int)sizeof(fold_T), 10); |
2850 return OK; | 2848 return OK; |
2851 } | 2849 } |
2852 | 2850 |
2853 /* foldSplit() {{{2 */ | 2851 // foldSplit() {{{2 |
2854 /* | 2852 /* |
2855 * Split the "i"th fold in "gap", which starts before "top" and ends below | 2853 * Split the "i"th fold in "gap", which starts before "top" and ends below |
2856 * "bot" in two pieces, one ending above "top" and the other starting below | 2854 * "bot" in two pieces, one ending above "top" and the other starting below |
2857 * "bot". | 2855 * "bot". |
2858 * The caller must first have taken care of any nested folds from "top" to | 2856 * The caller must first have taken care of any nested folds from "top" to |
2870 garray_T *gap1; | 2868 garray_T *gap1; |
2871 garray_T *gap2; | 2869 garray_T *gap2; |
2872 int idx; | 2870 int idx; |
2873 int len; | 2871 int len; |
2874 | 2872 |
2875 /* The fold continues below bot, need to split it. */ | 2873 // The fold continues below bot, need to split it. |
2876 if (foldInsert(gap, i + 1) == FAIL) | 2874 if (foldInsert(gap, i + 1) == FAIL) |
2877 return; | 2875 return; |
2878 fp = (fold_T *)gap->ga_data + i; | 2876 fp = (fold_T *)gap->ga_data + i; |
2879 fp[1].fd_top = bot + 1; | 2877 fp[1].fd_top = bot + 1; |
2880 fp[1].fd_len = fp->fd_len - (fp[1].fd_top - fp->fd_top); | 2878 fp[1].fd_len = fp->fd_len - (fp[1].fd_top - fp->fd_top); |
2881 fp[1].fd_flags = fp->fd_flags; | 2879 fp[1].fd_flags = fp->fd_flags; |
2882 fp[1].fd_small = MAYBE; | 2880 fp[1].fd_small = MAYBE; |
2883 fp->fd_small = MAYBE; | 2881 fp->fd_small = MAYBE; |
2884 | 2882 |
2885 /* Move nested folds below bot to new fold. There can't be | 2883 // Move nested folds below bot to new fold. There can't be |
2886 * any between top and bot, they have been removed by the caller. */ | 2884 // any between top and bot, they have been removed by the caller. |
2887 gap1 = &fp->fd_nested; | 2885 gap1 = &fp->fd_nested; |
2888 gap2 = &fp[1].fd_nested; | 2886 gap2 = &fp[1].fd_nested; |
2889 (void)(foldFind(gap1, bot + 1 - fp->fd_top, &fp2)); | 2887 (void)(foldFind(gap1, bot + 1 - fp->fd_top, &fp2)); |
2890 len = (int)((fold_T *)gap1->ga_data + gap1->ga_len - fp2); | 2888 len = (int)((fold_T *)gap1->ga_data + gap1->ga_len - fp2); |
2891 if (len > 0 && ga_grow(gap2, len) == OK) | 2889 if (len > 0 && ga_grow(gap2, len) == OK) |
2901 } | 2899 } |
2902 fp->fd_len = top - fp->fd_top; | 2900 fp->fd_len = top - fp->fd_top; |
2903 fold_changed = TRUE; | 2901 fold_changed = TRUE; |
2904 } | 2902 } |
2905 | 2903 |
2906 /* foldRemove() {{{2 */ | 2904 // foldRemove() {{{2 |
2907 /* | 2905 /* |
2908 * Remove folds within the range "top" to and including "bot". | 2906 * Remove folds within the range "top" to and including "bot". |
2909 * Check for these situations: | 2907 * Check for these situations: |
2910 * 1 2 3 | 2908 * 1 2 3 |
2911 * 1 2 3 | 2909 * 1 2 3 |
2926 foldRemove(garray_T *gap, linenr_T top, linenr_T bot) | 2924 foldRemove(garray_T *gap, linenr_T top, linenr_T bot) |
2927 { | 2925 { |
2928 fold_T *fp = NULL; | 2926 fold_T *fp = NULL; |
2929 | 2927 |
2930 if (bot < top) | 2928 if (bot < top) |
2931 return; /* nothing to do */ | 2929 return; // nothing to do |
2932 | 2930 |
2933 for (;;) | 2931 for (;;) |
2934 { | 2932 { |
2935 /* Find fold that includes top or a following one. */ | 2933 // Find fold that includes top or a following one. |
2936 if (foldFind(gap, top, &fp) && fp->fd_top < top) | 2934 if (foldFind(gap, top, &fp) && fp->fd_top < top) |
2937 { | 2935 { |
2938 /* 2: or 3: need to delete nested folds */ | 2936 // 2: or 3: need to delete nested folds |
2939 foldRemove(&fp->fd_nested, top - fp->fd_top, bot - fp->fd_top); | 2937 foldRemove(&fp->fd_nested, top - fp->fd_top, bot - fp->fd_top); |
2940 if (fp->fd_top + fp->fd_len - 1 > bot) | 2938 if (fp->fd_top + fp->fd_len - 1 > bot) |
2941 { | 2939 { |
2942 /* 3: need to split it. */ | 2940 // 3: need to split it. |
2943 foldSplit(gap, (int)(fp - (fold_T *)gap->ga_data), top, bot); | 2941 foldSplit(gap, (int)(fp - (fold_T *)gap->ga_data), top, bot); |
2944 } | 2942 } |
2945 else | 2943 else |
2946 { | 2944 { |
2947 /* 2: truncate fold at "top". */ | 2945 // 2: truncate fold at "top". |
2948 fp->fd_len = top - fp->fd_top; | 2946 fp->fd_len = top - fp->fd_top; |
2949 } | 2947 } |
2950 fold_changed = TRUE; | 2948 fold_changed = TRUE; |
2951 continue; | 2949 continue; |
2952 } | 2950 } |
2953 if (fp >= (fold_T *)(gap->ga_data) + gap->ga_len | 2951 if (fp >= (fold_T *)(gap->ga_data) + gap->ga_len |
2954 || fp->fd_top > bot) | 2952 || fp->fd_top > bot) |
2955 { | 2953 { |
2956 /* 6: Found a fold below bot, can stop looking. */ | 2954 // 6: Found a fold below bot, can stop looking. |
2957 break; | 2955 break; |
2958 } | 2956 } |
2959 if (fp->fd_top >= top) | 2957 if (fp->fd_top >= top) |
2960 { | 2958 { |
2961 /* Found an entry below top. */ | 2959 // Found an entry below top. |
2962 fold_changed = TRUE; | 2960 fold_changed = TRUE; |
2963 if (fp->fd_top + fp->fd_len - 1 > bot) | 2961 if (fp->fd_top + fp->fd_len - 1 > bot) |
2964 { | 2962 { |
2965 /* 5: Make fold that includes bot start below bot. */ | 2963 // 5: Make fold that includes bot start below bot. |
2966 foldMarkAdjustRecurse(&fp->fd_nested, | 2964 foldMarkAdjustRecurse(&fp->fd_nested, |
2967 (linenr_T)0, (long)(bot - fp->fd_top), | 2965 (linenr_T)0, (long)(bot - fp->fd_top), |
2968 (linenr_T)MAXLNUM, (long)(fp->fd_top - bot - 1)); | 2966 (linenr_T)MAXLNUM, (long)(fp->fd_top - bot - 1)); |
2969 fp->fd_len -= bot - fp->fd_top + 1; | 2967 fp->fd_len -= bot - fp->fd_top + 1; |
2970 fp->fd_top = bot + 1; | 2968 fp->fd_top = bot + 1; |
2971 break; | 2969 break; |
2972 } | 2970 } |
2973 | 2971 |
2974 /* 4: Delete completely contained fold. */ | 2972 // 4: Delete completely contained fold. |
2975 deleteFoldEntry(gap, (int)(fp - (fold_T *)gap->ga_data), TRUE); | 2973 deleteFoldEntry(gap, (int)(fp - (fold_T *)gap->ga_data), TRUE); |
2976 } | 2974 } |
2977 } | 2975 } |
2978 } | 2976 } |
2979 | 2977 |
2980 /* foldReverseOrder() {{{2 */ | 2978 // foldReverseOrder() {{{2 |
2981 static void | 2979 static void |
2982 foldReverseOrder(garray_T *gap, linenr_T start_arg, linenr_T end_arg) | 2980 foldReverseOrder(garray_T *gap, linenr_T start_arg, linenr_T end_arg) |
2983 { | 2981 { |
2984 fold_T *left, *right; | 2982 fold_T *left, *right; |
2985 fold_T tmp; | 2983 fold_T tmp; |
2994 *left = *right; | 2992 *left = *right; |
2995 *right = tmp; | 2993 *right = tmp; |
2996 } | 2994 } |
2997 } | 2995 } |
2998 | 2996 |
2999 /* foldMoveRange() {{{2 */ | 2997 // foldMoveRange() {{{2 |
3000 /* | 2998 /* |
3001 * Move folds within the inclusive range "line1" to "line2" to after "dest" | 2999 * Move folds within the inclusive range "line1" to "line2" to after "dest" |
3002 * requires "line1" <= "line2" <= "dest" | 3000 * requires "line1" <= "line2" <= "dest" |
3003 * | 3001 * |
3004 * There are the following situations for the first fold at or below line1 - 1. | 3002 * There are the following situations for the first fold at or below line1 - 1. |
3052 | 3050 |
3053 if (at_start) | 3051 if (at_start) |
3054 { | 3052 { |
3055 if (fold_end(fp) > dest) | 3053 if (fold_end(fp) > dest) |
3056 { | 3054 { |
3057 /* Case 4 | 3055 // Case 4 |
3058 * don't have to change this fold, but have to move nested folds. | 3056 // don't have to change this fold, but have to move nested folds. |
3059 */ | |
3060 foldMoveRange(&fp->fd_nested, line1 - fp->fd_top, line2 - | 3057 foldMoveRange(&fp->fd_nested, line1 - fp->fd_top, line2 - |
3061 fp->fd_top, dest - fp->fd_top); | 3058 fp->fd_top, dest - fp->fd_top); |
3062 return; | 3059 return; |
3063 } | 3060 } |
3064 else if (fold_end(fp) > line2) | 3061 else if (fold_end(fp) > line2) |
3065 { | 3062 { |
3066 /* Case 3 | 3063 // Case 3 |
3067 * Remove nested folds between line1 and line2 & reduce the | 3064 // Remove nested folds between line1 and line2 & reduce the |
3068 * length of fold by "range_len". | 3065 // length of fold by "range_len". |
3069 * Folds after this one must be dealt with. | 3066 // Folds after this one must be dealt with. |
3070 */ | |
3071 foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top, line2 - | 3067 foldMarkAdjustRecurse(&fp->fd_nested, line1 - fp->fd_top, line2 - |
3072 fp->fd_top, MAXLNUM, -range_len); | 3068 fp->fd_top, MAXLNUM, -range_len); |
3073 fp->fd_len -= range_len; | 3069 fp->fd_len -= range_len; |
3074 } | 3070 } |
3075 else | 3071 else |
3076 /* Case 2 truncate fold, folds after this one must be dealt with. */ | 3072 // Case 2 truncate fold, folds after this one must be dealt with. |
3077 truncate_fold(fp, line1 - 1); | 3073 truncate_fold(fp, line1 - 1); |
3078 | 3074 |
3079 /* Look at the next fold, and treat that one as if it were the first | 3075 // Look at the next fold, and treat that one as if it were the first |
3080 * after "line1" (because now it is). */ | 3076 // after "line1" (because now it is). |
3081 fp = fp + 1; | 3077 fp = fp + 1; |
3082 } | 3078 } |
3083 | 3079 |
3084 if (!valid_fold(fp, gap) || fp->fd_top > dest) | 3080 if (!valid_fold(fp, gap) || fp->fd_top > dest) |
3085 { | 3081 { |
3086 /* Case 10 | 3082 // Case 10 |
3087 * No folds after "line1" and before "dest" | 3083 // No folds after "line1" and before "dest" |
3088 */ | |
3089 return; | 3084 return; |
3090 } | 3085 } |
3091 else if (fp->fd_top > line2) | 3086 else if (fp->fd_top > line2) |
3092 { | 3087 { |
3093 for (; valid_fold(fp, gap) && fold_end(fp) <= dest; fp++) | 3088 for (; valid_fold(fp, gap) && fold_end(fp) <= dest; fp++) |
3094 /* Case 9. (for all case 9's) -- shift up. */ | 3089 // Case 9. (for all case 9's) -- shift up. |
3095 fp->fd_top -= range_len; | 3090 fp->fd_top -= range_len; |
3096 | 3091 |
3097 if (valid_fold(fp, gap) && fp->fd_top <= dest) | 3092 if (valid_fold(fp, gap) && fp->fd_top <= dest) |
3098 { | 3093 { |
3099 /* Case 8. -- ensure truncated at dest, shift up */ | 3094 // Case 8. -- ensure truncated at dest, shift up |
3100 truncate_fold(fp, dest); | 3095 truncate_fold(fp, dest); |
3101 fp->fd_top -= range_len; | 3096 fp->fd_top -= range_len; |
3102 } | 3097 } |
3103 return; | 3098 return; |
3104 } | 3099 } |
3105 else if (fold_end(fp) > dest) | 3100 else if (fold_end(fp) > dest) |
3106 { | 3101 { |
3107 /* Case 7 -- remove nested folds and shrink */ | 3102 // Case 7 -- remove nested folds and shrink |
3108 foldMarkAdjustRecurse(&fp->fd_nested, line2 + 1 - fp->fd_top, dest - | 3103 foldMarkAdjustRecurse(&fp->fd_nested, line2 + 1 - fp->fd_top, dest - |
3109 fp->fd_top, MAXLNUM, -move_len); | 3104 fp->fd_top, MAXLNUM, -move_len); |
3110 fp->fd_len -= move_len; | 3105 fp->fd_len -= move_len; |
3111 fp->fd_top += move_len; | 3106 fp->fd_top += move_len; |
3112 return; | 3107 return; |
3113 } | 3108 } |
3114 | 3109 |
3115 /* Case 5 or 6 | 3110 // Case 5 or 6 |
3116 * changes rely on whether there are folds between the end of | 3111 // changes rely on whether there are folds between the end of |
3117 * this fold and "dest". | 3112 // this fold and "dest". |
3118 */ | |
3119 move_start = fold_index(fp, gap); | 3113 move_start = fold_index(fp, gap); |
3120 | 3114 |
3121 for (; valid_fold(fp, gap) && fp->fd_top <= dest; fp++) | 3115 for (; valid_fold(fp, gap) && fp->fd_top <= dest; fp++) |
3122 { | 3116 { |
3123 if (fp->fd_top <= line2) | 3117 if (fp->fd_top <= line2) |
3124 { | 3118 { |
3125 /* 1. 2. or 3. */ | 3119 // 1. 2. or 3. |
3126 if (fold_end(fp) > line2) | 3120 if (fold_end(fp) > line2) |
3127 /* 2. or 3., truncate before moving */ | 3121 // 2. or 3., truncate before moving |
3128 truncate_fold(fp, line2); | 3122 truncate_fold(fp, line2); |
3129 | 3123 |
3130 fp->fd_top += move_len; | 3124 fp->fd_top += move_len; |
3131 continue; | 3125 continue; |
3132 } | 3126 } |
3133 | 3127 |
3134 /* Record index of the first fold after the moved range. */ | 3128 // Record index of the first fold after the moved range. |
3135 if (move_end == 0) | 3129 if (move_end == 0) |
3136 move_end = fold_index(fp, gap); | 3130 move_end = fold_index(fp, gap); |
3137 | 3131 |
3138 if (fold_end(fp) > dest) | 3132 if (fold_end(fp) > dest) |
3139 truncate_fold(fp, dest); | 3133 truncate_fold(fp, dest); |
3147 * All folds are now correct, but not necessarily in the correct order. We | 3141 * All folds are now correct, but not necessarily in the correct order. We |
3148 * must swap folds in the range [move_end, dest_index) with those in the | 3142 * must swap folds in the range [move_end, dest_index) with those in the |
3149 * range [move_start, move_end). | 3143 * range [move_start, move_end). |
3150 */ | 3144 */ |
3151 if (move_end == 0) | 3145 if (move_end == 0) |
3152 /* There are no folds after those moved, hence no folds have been moved | 3146 // There are no folds after those moved, hence no folds have been moved |
3153 * out of order. */ | 3147 // out of order. |
3154 return; | 3148 return; |
3155 foldReverseOrder(gap, (linenr_T)move_start, (linenr_T)dest_index - 1); | 3149 foldReverseOrder(gap, (linenr_T)move_start, (linenr_T)dest_index - 1); |
3156 foldReverseOrder(gap, (linenr_T)move_start, | 3150 foldReverseOrder(gap, (linenr_T)move_start, |
3157 (linenr_T)(move_start + dest_index - move_end - 1)); | 3151 (linenr_T)(move_start + dest_index - move_end - 1)); |
3158 foldReverseOrder(gap, (linenr_T)(move_start + dest_index - move_end), | 3152 foldReverseOrder(gap, (linenr_T)(move_start + dest_index - move_end), |
3160 } | 3154 } |
3161 #undef fold_end | 3155 #undef fold_end |
3162 #undef valid_fold | 3156 #undef valid_fold |
3163 #undef fold_index | 3157 #undef fold_index |
3164 | 3158 |
3165 /* foldMerge() {{{2 */ | 3159 // foldMerge() {{{2 |
3166 /* | 3160 /* |
3167 * Merge two adjacent folds (and the nested ones in them). | 3161 * Merge two adjacent folds (and the nested ones in them). |
3168 * This only works correctly when the folds are really adjacent! Thus "fp1" | 3162 * This only works correctly when the folds are really adjacent! Thus "fp1" |
3169 * must end just above "fp2". | 3163 * must end just above "fp2". |
3170 * The resulting fold is "fp1", nested folds are moved from "fp2" to "fp1". | 3164 * The resulting fold is "fp1", nested folds are moved from "fp2" to "fp1". |
3177 fold_T *fp4; | 3171 fold_T *fp4; |
3178 int idx; | 3172 int idx; |
3179 garray_T *gap1 = &fp1->fd_nested; | 3173 garray_T *gap1 = &fp1->fd_nested; |
3180 garray_T *gap2 = &fp2->fd_nested; | 3174 garray_T *gap2 = &fp2->fd_nested; |
3181 | 3175 |
3182 /* If the last nested fold in fp1 touches the first nested fold in fp2, | 3176 // If the last nested fold in fp1 touches the first nested fold in fp2, |
3183 * merge them recursively. */ | 3177 // merge them recursively. |
3184 if (foldFind(gap1, fp1->fd_len - 1L, &fp3) && foldFind(gap2, 0L, &fp4)) | 3178 if (foldFind(gap1, fp1->fd_len - 1L, &fp3) && foldFind(gap2, 0L, &fp4)) |
3185 foldMerge(fp3, gap2, fp4); | 3179 foldMerge(fp3, gap2, fp4); |
3186 | 3180 |
3187 /* Move nested folds in fp2 to the end of fp1. */ | 3181 // Move nested folds in fp2 to the end of fp1. |
3188 if (gap2->ga_len > 0 && ga_grow(gap1, gap2->ga_len) == OK) | 3182 if (gap2->ga_len > 0 && ga_grow(gap1, gap2->ga_len) == OK) |
3189 { | 3183 { |
3190 for (idx = 0; idx < gap2->ga_len; ++idx) | 3184 for (idx = 0; idx < gap2->ga_len; ++idx) |
3191 { | 3185 { |
3192 ((fold_T *)gap1->ga_data)[gap1->ga_len] | 3186 ((fold_T *)gap1->ga_data)[gap1->ga_len] |
3200 fp1->fd_len += fp2->fd_len; | 3194 fp1->fd_len += fp2->fd_len; |
3201 deleteFoldEntry(gap, (int)(fp2 - (fold_T *)gap->ga_data), TRUE); | 3195 deleteFoldEntry(gap, (int)(fp2 - (fold_T *)gap->ga_data), TRUE); |
3202 fold_changed = TRUE; | 3196 fold_changed = TRUE; |
3203 } | 3197 } |
3204 | 3198 |
3205 /* foldlevelIndent() {{{2 */ | 3199 // foldlevelIndent() {{{2 |
3206 /* | 3200 /* |
3207 * Low level function to get the foldlevel for the "indent" method. | 3201 * Low level function to get the foldlevel for the "indent" method. |
3208 * Doesn't use any caching. | 3202 * Doesn't use any caching. |
3209 * Returns a level of -1 if the foldlevel depends on surrounding lines. | 3203 * Returns a level of -1 if the foldlevel depends on surrounding lines. |
3210 */ | 3204 */ |
3216 linenr_T lnum = flp->lnum + flp->off; | 3210 linenr_T lnum = flp->lnum + flp->off; |
3217 | 3211 |
3218 buf = flp->wp->w_buffer; | 3212 buf = flp->wp->w_buffer; |
3219 s = skipwhite(ml_get_buf(buf, lnum, FALSE)); | 3213 s = skipwhite(ml_get_buf(buf, lnum, FALSE)); |
3220 | 3214 |
3221 /* empty line or lines starting with a character in 'foldignore': level | 3215 // empty line or lines starting with a character in 'foldignore': level |
3222 * depends on surrounding lines */ | 3216 // depends on surrounding lines |
3223 if (*s == NUL || vim_strchr(flp->wp->w_p_fdi, *s) != NULL) | 3217 if (*s == NUL || vim_strchr(flp->wp->w_p_fdi, *s) != NULL) |
3224 { | 3218 { |
3225 /* first and last line can't be undefined, use level 0 */ | 3219 // first and last line can't be undefined, use level 0 |
3226 if (lnum == 1 || lnum == buf->b_ml.ml_line_count) | 3220 if (lnum == 1 || lnum == buf->b_ml.ml_line_count) |
3227 flp->lvl = 0; | 3221 flp->lvl = 0; |
3228 else | 3222 else |
3229 flp->lvl = -1; | 3223 flp->lvl = -1; |
3230 } | 3224 } |
3236 if (flp->lvl < 0) | 3230 if (flp->lvl < 0) |
3237 flp->lvl = 0; | 3231 flp->lvl = 0; |
3238 } | 3232 } |
3239 } | 3233 } |
3240 | 3234 |
3241 /* foldlevelDiff() {{{2 */ | 3235 // foldlevelDiff() {{{2 |
3242 #ifdef FEAT_DIFF | 3236 #ifdef FEAT_DIFF |
3243 /* | 3237 /* |
3244 * Low level function to get the foldlevel for the "diff" method. | 3238 * Low level function to get the foldlevel for the "diff" method. |
3245 * Doesn't use any caching. | 3239 * Doesn't use any caching. |
3246 */ | 3240 */ |
3252 else | 3246 else |
3253 flp->lvl = 0; | 3247 flp->lvl = 0; |
3254 } | 3248 } |
3255 #endif | 3249 #endif |
3256 | 3250 |
3257 /* foldlevelExpr() {{{2 */ | 3251 // foldlevelExpr() {{{2 |
3258 /* | 3252 /* |
3259 * Low level function to get the foldlevel for the "expr" method. | 3253 * Low level function to get the foldlevel for the "expr" method. |
3260 * Doesn't use any caching. | 3254 * Doesn't use any caching. |
3261 * Returns a level of -1 if the foldlevel depends on surrounding lines. | 3255 * Returns a level of -1 if the foldlevel depends on surrounding lines. |
3262 */ | 3256 */ |
3282 flp->had_end = flp->end; | 3276 flp->had_end = flp->end; |
3283 flp->end = MAX_LEVEL + 1; | 3277 flp->end = MAX_LEVEL + 1; |
3284 if (lnum <= 1) | 3278 if (lnum <= 1) |
3285 flp->lvl = 0; | 3279 flp->lvl = 0; |
3286 | 3280 |
3287 /* KeyTyped may be reset to 0 when calling a function which invokes | 3281 // KeyTyped may be reset to 0 when calling a function which invokes |
3288 * do_cmdline(). To make 'foldopen' work correctly restore KeyTyped. */ | 3282 // do_cmdline(). To make 'foldopen' work correctly restore KeyTyped. |
3289 save_keytyped = KeyTyped; | 3283 save_keytyped = KeyTyped; |
3290 n = (int)eval_foldexpr(flp->wp->w_p_fde, &c); | 3284 n = (int)eval_foldexpr(flp->wp->w_p_fde, &c); |
3291 KeyTyped = save_keytyped; | 3285 KeyTyped = save_keytyped; |
3292 | 3286 |
3293 switch (c) | 3287 switch (c) |
3294 { | 3288 { |
3295 /* "a1", "a2", .. : add to the fold level */ | 3289 // "a1", "a2", .. : add to the fold level |
3296 case 'a': if (flp->lvl >= 0) | 3290 case 'a': if (flp->lvl >= 0) |
3297 { | 3291 { |
3298 flp->lvl += n; | 3292 flp->lvl += n; |
3299 flp->lvl_next = flp->lvl; | 3293 flp->lvl_next = flp->lvl; |
3300 } | 3294 } |
3301 flp->start = n; | 3295 flp->start = n; |
3302 break; | 3296 break; |
3303 | 3297 |
3304 /* "s1", "s2", .. : subtract from the fold level */ | 3298 // "s1", "s2", .. : subtract from the fold level |
3305 case 's': if (flp->lvl >= 0) | 3299 case 's': if (flp->lvl >= 0) |
3306 { | 3300 { |
3307 if (n > flp->lvl) | 3301 if (n > flp->lvl) |
3308 flp->lvl_next = 0; | 3302 flp->lvl_next = 0; |
3309 else | 3303 else |
3310 flp->lvl_next = flp->lvl - n; | 3304 flp->lvl_next = flp->lvl - n; |
3311 flp->end = flp->lvl_next + 1; | 3305 flp->end = flp->lvl_next + 1; |
3312 } | 3306 } |
3313 break; | 3307 break; |
3314 | 3308 |
3315 /* ">1", ">2", .. : start a fold with a certain level */ | 3309 // ">1", ">2", .. : start a fold with a certain level |
3316 case '>': flp->lvl = n; | 3310 case '>': flp->lvl = n; |
3317 flp->lvl_next = n; | 3311 flp->lvl_next = n; |
3318 flp->start = 1; | 3312 flp->start = 1; |
3319 break; | 3313 break; |
3320 | 3314 |
3321 /* "<1", "<2", .. : end a fold with a certain level */ | 3315 // "<1", "<2", .. : end a fold with a certain level |
3322 case '<': flp->lvl_next = n - 1; | 3316 case '<': flp->lvl_next = n - 1; |
3323 flp->end = n; | 3317 flp->end = n; |
3324 break; | 3318 break; |
3325 | 3319 |
3326 /* "=": No change in level */ | 3320 // "=": No change in level |
3327 case '=': flp->lvl_next = flp->lvl; | 3321 case '=': flp->lvl_next = flp->lvl; |
3328 break; | 3322 break; |
3329 | 3323 |
3330 /* "-1", "0", "1", ..: set fold level */ | 3324 // "-1", "0", "1", ..: set fold level |
3331 default: if (n < 0) | 3325 default: if (n < 0) |
3332 /* Use the current level for the next line, so that "a1" | 3326 // Use the current level for the next line, so that "a1" |
3333 * will work there. */ | 3327 // will work there. |
3334 flp->lvl_next = flp->lvl; | 3328 flp->lvl_next = flp->lvl; |
3335 else | 3329 else |
3336 flp->lvl_next = n; | 3330 flp->lvl_next = n; |
3337 flp->lvl = n; | 3331 flp->lvl = n; |
3338 break; | 3332 break; |
3339 } | 3333 } |
3340 | 3334 |
3341 /* If the level is unknown for the first or the last line in the file, use | 3335 // If the level is unknown for the first or the last line in the file, use |
3342 * level 0. */ | 3336 // level 0. |
3343 if (flp->lvl < 0) | 3337 if (flp->lvl < 0) |
3344 { | 3338 { |
3345 if (lnum <= 1) | 3339 if (lnum <= 1) |
3346 { | 3340 { |
3347 flp->lvl = 0; | 3341 flp->lvl = 0; |
3354 curwin = win; | 3348 curwin = win; |
3355 curbuf = curwin->w_buffer; | 3349 curbuf = curwin->w_buffer; |
3356 #endif | 3350 #endif |
3357 } | 3351 } |
3358 | 3352 |
3359 /* parseMarker() {{{2 */ | 3353 // parseMarker() {{{2 |
3360 /* | 3354 /* |
3361 * Parse 'foldmarker' and set "foldendmarker", "foldstartmarkerlen" and | 3355 * Parse 'foldmarker' and set "foldendmarker", "foldstartmarkerlen" and |
3362 * "foldendmarkerlen". | 3356 * "foldendmarkerlen". |
3363 * Relies on the option value to have been checked for correctness already. | 3357 * Relies on the option value to have been checked for correctness already. |
3364 */ | 3358 */ |
3368 foldendmarker = vim_strchr(wp->w_p_fmr, ','); | 3362 foldendmarker = vim_strchr(wp->w_p_fmr, ','); |
3369 foldstartmarkerlen = (int)(foldendmarker++ - wp->w_p_fmr); | 3363 foldstartmarkerlen = (int)(foldendmarker++ - wp->w_p_fmr); |
3370 foldendmarkerlen = (int)STRLEN(foldendmarker); | 3364 foldendmarkerlen = (int)STRLEN(foldendmarker); |
3371 } | 3365 } |
3372 | 3366 |
3373 /* foldlevelMarker() {{{2 */ | 3367 // foldlevelMarker() {{{2 |
3374 /* | 3368 /* |
3375 * Low level function to get the foldlevel for the "marker" method. | 3369 * Low level function to get the foldlevel for the "marker" method. |
3376 * "foldendmarker", "foldstartmarkerlen" and "foldendmarkerlen" must have been | 3370 * "foldendmarker", "foldstartmarkerlen" and "foldendmarkerlen" must have been |
3377 * set before calling this. | 3371 * set before calling this. |
3378 * Requires that flp->lvl is set to the fold level of the previous line! | 3372 * Requires that flp->lvl is set to the fold level of the previous line! |
3388 int cend; | 3382 int cend; |
3389 int start_lvl = flp->lvl; | 3383 int start_lvl = flp->lvl; |
3390 char_u *s; | 3384 char_u *s; |
3391 int n; | 3385 int n; |
3392 | 3386 |
3393 /* cache a few values for speed */ | 3387 // cache a few values for speed |
3394 startmarker = flp->wp->w_p_fmr; | 3388 startmarker = flp->wp->w_p_fmr; |
3395 cstart = *startmarker; | 3389 cstart = *startmarker; |
3396 ++startmarker; | 3390 ++startmarker; |
3397 cend = *foldendmarker; | 3391 cend = *foldendmarker; |
3398 | 3392 |
3399 /* Default: no start found, next level is same as current level */ | 3393 // Default: no start found, next level is same as current level |
3400 flp->start = 0; | 3394 flp->start = 0; |
3401 flp->lvl_next = flp->lvl; | 3395 flp->lvl_next = flp->lvl; |
3402 | 3396 |
3403 s = ml_get_buf(flp->wp->w_buffer, flp->lnum + flp->off, FALSE); | 3397 s = ml_get_buf(flp->wp->w_buffer, flp->lnum + flp->off, FALSE); |
3404 while (*s) | 3398 while (*s) |
3405 { | 3399 { |
3406 if (*s == cstart | 3400 if (*s == cstart |
3407 && STRNCMP(s + 1, startmarker, foldstartmarkerlen - 1) == 0) | 3401 && STRNCMP(s + 1, startmarker, foldstartmarkerlen - 1) == 0) |
3408 { | 3402 { |
3409 /* found startmarker: set flp->lvl */ | 3403 // found startmarker: set flp->lvl |
3410 s += foldstartmarkerlen; | 3404 s += foldstartmarkerlen; |
3411 if (VIM_ISDIGIT(*s)) | 3405 if (VIM_ISDIGIT(*s)) |
3412 { | 3406 { |
3413 n = atoi((char *)s); | 3407 n = atoi((char *)s); |
3414 if (n > 0) | 3408 if (n > 0) |
3429 } | 3423 } |
3430 } | 3424 } |
3431 else if (*s == cend | 3425 else if (*s == cend |
3432 && STRNCMP(s + 1, foldendmarker + 1, foldendmarkerlen - 1) == 0) | 3426 && STRNCMP(s + 1, foldendmarker + 1, foldendmarkerlen - 1) == 0) |
3433 { | 3427 { |
3434 /* found endmarker: set flp->lvl_next */ | 3428 // found endmarker: set flp->lvl_next |
3435 s += foldendmarkerlen; | 3429 s += foldendmarkerlen; |
3436 if (VIM_ISDIGIT(*s)) | 3430 if (VIM_ISDIGIT(*s)) |
3437 { | 3431 { |
3438 n = atoi((char *)s); | 3432 n = atoi((char *)s); |
3439 if (n > 0) | 3433 if (n > 0) |
3440 { | 3434 { |
3441 flp->lvl = n; | 3435 flp->lvl = n; |
3442 flp->lvl_next = n - 1; | 3436 flp->lvl_next = n - 1; |
3443 /* never start a fold with an end marker */ | 3437 // never start a fold with an end marker |
3444 if (flp->lvl_next > start_lvl) | 3438 if (flp->lvl_next > start_lvl) |
3445 flp->lvl_next = start_lvl; | 3439 flp->lvl_next = start_lvl; |
3446 } | 3440 } |
3447 } | 3441 } |
3448 else | 3442 else |
3450 } | 3444 } |
3451 else | 3445 else |
3452 MB_PTR_ADV(s); | 3446 MB_PTR_ADV(s); |
3453 } | 3447 } |
3454 | 3448 |
3455 /* The level can't go negative, must be missing a start marker. */ | 3449 // The level can't go negative, must be missing a start marker. |
3456 if (flp->lvl_next < 0) | 3450 if (flp->lvl_next < 0) |
3457 flp->lvl_next = 0; | 3451 flp->lvl_next = 0; |
3458 } | 3452 } |
3459 | 3453 |
3460 /* foldlevelSyntax() {{{2 */ | 3454 // foldlevelSyntax() {{{2 |
3461 /* | 3455 /* |
3462 * Low level function to get the foldlevel for the "syntax" method. | 3456 * Low level function to get the foldlevel for the "syntax" method. |
3463 * Doesn't use any caching. | 3457 * Doesn't use any caching. |
3464 */ | 3458 */ |
3465 static void | 3459 static void |
3470 flp->lvl = 0; | 3464 flp->lvl = 0; |
3471 #else | 3465 #else |
3472 linenr_T lnum = flp->lnum + flp->off; | 3466 linenr_T lnum = flp->lnum + flp->off; |
3473 int n; | 3467 int n; |
3474 | 3468 |
3475 /* Use the maximum fold level at the start of this line and the next. */ | 3469 // Use the maximum fold level at the start of this line and the next. |
3476 flp->lvl = syn_get_foldlevel(flp->wp, lnum); | 3470 flp->lvl = syn_get_foldlevel(flp->wp, lnum); |
3477 flp->start = 0; | 3471 flp->start = 0; |
3478 if (lnum < flp->wp->w_buffer->b_ml.ml_line_count) | 3472 if (lnum < flp->wp->w_buffer->b_ml.ml_line_count) |
3479 { | 3473 { |
3480 n = syn_get_foldlevel(flp->wp, lnum + 1); | 3474 n = syn_get_foldlevel(flp->wp, lnum + 1); |
3481 if (n > flp->lvl) | 3475 if (n > flp->lvl) |
3482 { | 3476 { |
3483 flp->start = n - flp->lvl; /* fold(s) start here */ | 3477 flp->start = n - flp->lvl; // fold(s) start here |
3484 flp->lvl = n; | 3478 flp->lvl = n; |
3485 } | 3479 } |
3486 } | 3480 } |
3487 #endif | 3481 #endif |
3488 } | 3482 } |
3489 | 3483 |
3490 /* functions for storing the fold state in a View {{{1 */ | 3484 // functions for storing the fold state in a View {{{1 |
3491 /* put_folds() {{{2 */ | 3485 // put_folds() {{{2 |
3492 #if defined(FEAT_SESSION) || defined(PROTO) | 3486 #if defined(FEAT_SESSION) || defined(PROTO) |
3493 static int put_folds_recurse(FILE *fd, garray_T *gap, linenr_T off); | 3487 static int put_folds_recurse(FILE *fd, garray_T *gap, linenr_T off); |
3494 static int put_foldopen_recurse(FILE *fd, win_T *wp, garray_T *gap, linenr_T off); | 3488 static int put_foldopen_recurse(FILE *fd, win_T *wp, garray_T *gap, linenr_T off); |
3495 static int put_fold_open_close(FILE *fd, fold_T *fp, linenr_T off); | 3489 static int put_fold_open_close(FILE *fd, fold_T *fp, linenr_T off); |
3496 | 3490 |
3506 if (put_line(fd, "silent! normal! zE") == FAIL | 3500 if (put_line(fd, "silent! normal! zE") == FAIL |
3507 || put_folds_recurse(fd, &wp->w_folds, (linenr_T)0) == FAIL) | 3501 || put_folds_recurse(fd, &wp->w_folds, (linenr_T)0) == FAIL) |
3508 return FAIL; | 3502 return FAIL; |
3509 } | 3503 } |
3510 | 3504 |
3511 /* If some folds are manually opened/closed, need to restore that. */ | 3505 // If some folds are manually opened/closed, need to restore that. |
3512 if (wp->w_fold_manual) | 3506 if (wp->w_fold_manual) |
3513 return put_foldopen_recurse(fd, wp, &wp->w_folds, (linenr_T)0); | 3507 return put_foldopen_recurse(fd, wp, &wp->w_folds, (linenr_T)0); |
3514 | 3508 |
3515 return OK; | 3509 return OK; |
3516 } | 3510 } |
3517 | 3511 |
3518 /* put_folds_recurse() {{{2 */ | 3512 // put_folds_recurse() {{{2 |
3519 /* | 3513 /* |
3520 * Write commands to "fd" to recreate manually created folds. | 3514 * Write commands to "fd" to recreate manually created folds. |
3521 * Returns FAIL when writing failed. | 3515 * Returns FAIL when writing failed. |
3522 */ | 3516 */ |
3523 static int | 3517 static int |
3527 fold_T *fp; | 3521 fold_T *fp; |
3528 | 3522 |
3529 fp = (fold_T *)gap->ga_data; | 3523 fp = (fold_T *)gap->ga_data; |
3530 for (i = 0; i < gap->ga_len; i++) | 3524 for (i = 0; i < gap->ga_len; i++) |
3531 { | 3525 { |
3532 /* Do nested folds first, they will be created closed. */ | 3526 // Do nested folds first, they will be created closed. |
3533 if (put_folds_recurse(fd, &fp->fd_nested, off + fp->fd_top) == FAIL) | 3527 if (put_folds_recurse(fd, &fp->fd_nested, off + fp->fd_top) == FAIL) |
3534 return FAIL; | 3528 return FAIL; |
3535 if (fprintf(fd, "%ld,%ldfold", fp->fd_top + off, | 3529 if (fprintf(fd, "%ld,%ldfold", fp->fd_top + off, |
3536 fp->fd_top + off + fp->fd_len - 1) < 0 | 3530 fp->fd_top + off + fp->fd_len - 1) < 0 |
3537 || put_eol(fd) == FAIL) | 3531 || put_eol(fd) == FAIL) |
3539 ++fp; | 3533 ++fp; |
3540 } | 3534 } |
3541 return OK; | 3535 return OK; |
3542 } | 3536 } |
3543 | 3537 |
3544 /* put_foldopen_recurse() {{{2 */ | 3538 // put_foldopen_recurse() {{{2 |
3545 /* | 3539 /* |
3546 * Write commands to "fd" to open and close manually opened/closed folds. | 3540 * Write commands to "fd" to open and close manually opened/closed folds. |
3547 * Returns FAIL when writing failed. | 3541 * Returns FAIL when writing failed. |
3548 */ | 3542 */ |
3549 static int | 3543 static int |
3562 { | 3556 { |
3563 if (fp->fd_flags != FD_LEVEL) | 3557 if (fp->fd_flags != FD_LEVEL) |
3564 { | 3558 { |
3565 if (fp->fd_nested.ga_len > 0) | 3559 if (fp->fd_nested.ga_len > 0) |
3566 { | 3560 { |
3567 /* open nested folds while this fold is open */ | 3561 // open nested folds while this fold is open |
3568 if (fprintf(fd, "%ld", fp->fd_top + off) < 0 | 3562 if (fprintf(fd, "%ld", fp->fd_top + off) < 0 |
3569 || put_eol(fd) == FAIL | 3563 || put_eol(fd) == FAIL |
3570 || put_line(fd, "normal! zo") == FAIL) | 3564 || put_line(fd, "normal! zo") == FAIL) |
3571 return FAIL; | 3565 return FAIL; |
3572 if (put_foldopen_recurse(fd, wp, &fp->fd_nested, | 3566 if (put_foldopen_recurse(fd, wp, &fp->fd_nested, |
3573 off + fp->fd_top) | 3567 off + fp->fd_top) |
3574 == FAIL) | 3568 == FAIL) |
3575 return FAIL; | 3569 return FAIL; |
3576 /* close the parent when needed */ | 3570 // close the parent when needed |
3577 if (fp->fd_flags == FD_CLOSED) | 3571 if (fp->fd_flags == FD_CLOSED) |
3578 { | 3572 { |
3579 if (put_fold_open_close(fd, fp, off) == FAIL) | 3573 if (put_fold_open_close(fd, fp, off) == FAIL) |
3580 return FAIL; | 3574 return FAIL; |
3581 } | 3575 } |
3582 } | 3576 } |
3583 else | 3577 else |
3584 { | 3578 { |
3585 /* Open or close the leaf according to the window foldlevel. | 3579 // Open or close the leaf according to the window foldlevel. |
3586 * Do not close a leaf that is already closed, as it will close | 3580 // Do not close a leaf that is already closed, as it will close |
3587 * the parent. */ | 3581 // the parent. |
3588 level = foldLevelWin(wp, off + fp->fd_top); | 3582 level = foldLevelWin(wp, off + fp->fd_top); |
3589 if ((fp->fd_flags == FD_CLOSED && wp->w_p_fdl >= level) | 3583 if ((fp->fd_flags == FD_CLOSED && wp->w_p_fdl >= level) |
3590 || (fp->fd_flags != FD_CLOSED && wp->w_p_fdl < level)) | 3584 || (fp->fd_flags != FD_CLOSED && wp->w_p_fdl < level)) |
3591 if (put_fold_open_close(fd, fp, off) == FAIL) | 3585 if (put_fold_open_close(fd, fp, off) == FAIL) |
3592 return FAIL; | 3586 return FAIL; |
3596 } | 3590 } |
3597 | 3591 |
3598 return OK; | 3592 return OK; |
3599 } | 3593 } |
3600 | 3594 |
3601 /* put_fold_open_close() {{{2 */ | 3595 // put_fold_open_close() {{{2 |
3602 /* | 3596 /* |
3603 * Write the open or close command to "fd". | 3597 * Write the open or close command to "fd". |
3604 * Returns FAIL when writing failed. | 3598 * Returns FAIL when writing failed. |
3605 */ | 3599 */ |
3606 static int | 3600 static int |
3613 || put_eol(fd) == FAIL) | 3607 || put_eol(fd) == FAIL) |
3614 return FAIL; | 3608 return FAIL; |
3615 | 3609 |
3616 return OK; | 3610 return OK; |
3617 } | 3611 } |
3618 #endif /* FEAT_SESSION */ | 3612 #endif // FEAT_SESSION |
3619 | 3613 |
3620 /* }}}1 */ | 3614 // }}}1 |
3621 #endif // defined(FEAT_FOLDING) || defined(PROTO) | 3615 #endif // defined(FEAT_FOLDING) || defined(PROTO) |
3622 | 3616 |
3623 #if defined(FEAT_EVAL) || defined(PROTO) | 3617 #if defined(FEAT_EVAL) || defined(PROTO) |
3624 | 3618 |
3625 /* | 3619 /* |