aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/fold.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/fold.c')
-rw-r--r--src/nvim/fold.c326
1 files changed, 190 insertions, 136 deletions
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index 61a85171e8..197aedabec 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -153,14 +153,22 @@ bool hasFolding(linenr_T lnum, linenr_T *firstp, linenr_T *lastp)
return hasFoldingWin(curwin, lnum, firstp, lastp, true, NULL);
}
-/* hasFoldingWin() {{{2 */
+// hasFoldingWin() {{{2
+/// Search folds starting at lnum
+/// @param lnum first line to search
+/// @param[out] first first line of fold containing lnum
+/// @param[out] lastp last line with a fold
+/// @param cache when true: use cached values of window
+/// @param[out] infop where to store fold info
+///
+/// @return true if range contains folds
bool hasFoldingWin(
win_T *const win,
const linenr_T lnum,
linenr_T *const firstp,
linenr_T *const lastp,
- const bool cache, // when true: use cached values of window
- foldinfo_T *const infop // where to store fold info
+ const bool cache,
+ foldinfo_T *const infop
)
{
bool had_folded = false;
@@ -280,26 +288,31 @@ int foldLevel(linenr_T lnum)
// Return false if line is not folded.
bool lineFolded(win_T *const win, const linenr_T lnum)
{
- return foldedCount(win, lnum, NULL) != 0;
+ return fold_info(win, lnum).fi_lines != 0;
}
-/* foldedCount() {{{2 */
-/*
- * Count the number of lines that are folded at line number "lnum".
- * Normally "lnum" is the first line of a possible fold, and the returned
- * number is the number of lines in the fold.
- * Doesn't use caching from the displayed window.
- * Returns number of folded lines from "lnum", or 0 if line is not folded.
- * When "infop" is not NULL, fills *infop with the fold level info.
- */
-long foldedCount(win_T *win, linenr_T lnum, foldinfo_T *infop)
+/// fold_info() {{{2
+///
+/// Count the number of lines that are folded at line number "lnum".
+/// Normally "lnum" is the first line of a possible fold, and the returned
+/// number is the number of lines in the fold.
+/// Doesn't use caching from the displayed window.
+///
+/// @return with the fold level info.
+/// fi_lines = number of folded lines from "lnum",
+/// or 0 if line is not folded.
+foldinfo_T fold_info(win_T *win, linenr_T lnum)
{
+ foldinfo_T info;
linenr_T last;
- if (hasFoldingWin(win, lnum, NULL, &last, false, infop)) {
- return (long)(last - lnum + 1);
+ if (hasFoldingWin(win, lnum, NULL, &last, false, &info)) {
+ info.fi_lines = (long)(last - lnum + 1);
+ } else {
+ info.fi_lines = 0;
}
- return 0;
+
+ return info;
}
/* foldmethodIsManual() {{{2 */
@@ -356,23 +369,21 @@ int foldmethodIsDiff(win_T *wp)
return wp->w_p_fdm[0] == 'd';
}
-/* closeFold() {{{2 */
-/*
- * Close fold for current window at line "lnum".
- * Repeat "count" times.
- */
-void closeFold(linenr_T lnum, long count)
+// closeFold() {{{2
+/// Close fold for current window at line "lnum".
+/// Repeat "count" times.
+void closeFold(pos_T pos, long count)
{
- setFoldRepeat(lnum, count, FALSE);
+ setFoldRepeat(pos, count, false);
}
/* closeFoldRecurse() {{{2 */
/*
* Close fold for current window at line "lnum" recursively.
*/
-void closeFoldRecurse(linenr_T lnum)
+void closeFoldRecurse(pos_T pos)
{
- (void)setManualFold(lnum, FALSE, TRUE, NULL);
+ (void)setManualFold(pos, false, true, NULL);
}
/* opFoldRange() {{{2 */
@@ -382,28 +393,32 @@ void closeFoldRecurse(linenr_T lnum)
*/
void
opFoldRange(
- linenr_T first,
- linenr_T last,
+ pos_T firstpos,
+ pos_T lastpos,
int opening, // TRUE to open, FALSE to close
int recurse, // TRUE to do it recursively
int had_visual // TRUE when Visual selection used
)
{
- int done = DONE_NOTHING; /* avoid error messages */
+ int done = DONE_NOTHING; // avoid error messages
+ linenr_T first = firstpos.lnum;
+ linenr_T last = lastpos.lnum;
linenr_T lnum;
linenr_T lnum_next;
for (lnum = first; lnum <= last; lnum = lnum_next + 1) {
+ pos_T temp = { lnum, 0, 0 };
lnum_next = lnum;
/* Opening one level only: next fold to open is after the one going to
* be opened. */
if (opening && !recurse)
(void)hasFolding(lnum, NULL, &lnum_next);
- (void)setManualFold(lnum, opening, recurse, &done);
- /* Closing one level only: next line to close a fold is after just
- * closed fold. */
- if (!opening && !recurse)
+ (void)setManualFold(temp, opening, recurse, &done);
+ // Closing one level only: next line to close a fold is after just
+ // closed fold.
+ if (!opening && !recurse) {
(void)hasFolding(lnum, NULL, &lnum_next);
+ }
}
if (done == DONE_NOTHING)
EMSG(_(e_nofold));
@@ -417,18 +432,18 @@ opFoldRange(
* Open fold for current window at line "lnum".
* Repeat "count" times.
*/
-void openFold(linenr_T lnum, long count)
+void openFold(pos_T pos, long count)
{
- setFoldRepeat(lnum, count, TRUE);
+ setFoldRepeat(pos, count, true);
}
/* openFoldRecurse() {{{2 */
/*
* Open fold for current window at line "lnum" recursively.
*/
-void openFoldRecurse(linenr_T lnum)
+void openFoldRecurse(pos_T pos)
{
- (void)setManualFold(lnum, TRUE, TRUE, NULL);
+ (void)setManualFold(pos, true, true, NULL);
}
/* foldOpenCursor() {{{2 */
@@ -443,9 +458,10 @@ void foldOpenCursor(void)
if (hasAnyFolding(curwin))
for (;; ) {
done = DONE_NOTHING;
- (void)setManualFold(curwin->w_cursor.lnum, TRUE, FALSE, &done);
- if (!(done & DONE_ACTION))
+ (void)setManualFold(curwin->w_cursor, true, false, &done);
+ if (!(done & DONE_ACTION)) {
break;
+ }
}
}
@@ -542,21 +558,21 @@ int foldManualAllowed(int create)
// foldCreate() {{{2
/// Create a fold from line "start" to line "end" (inclusive) in the current
/// window.
-void foldCreate(win_T *wp, linenr_T start, linenr_T end)
+void foldCreate(win_T *wp, pos_T start, pos_T end)
{
fold_T *fp;
garray_T *gap;
garray_T fold_ga;
- int i, j;
+ int i;
int cont;
int use_level = FALSE;
int closed = FALSE;
int level = 0;
- linenr_T start_rel = start;
- linenr_T end_rel = end;
+ pos_T start_rel = start;
+ pos_T end_rel = end;
- if (start > end) {
- /* reverse the range */
+ if (start.lnum > end.lnum) {
+ // reverse the range
end = start_rel;
start = end_rel;
start_rel = start;
@@ -573,60 +589,70 @@ void foldCreate(win_T *wp, linenr_T start, linenr_T end)
// Find the place to insert the new fold
gap = &wp->w_folds;
- for (;; ) {
- if (!foldFind(gap, start_rel, &fp))
- break;
- if (fp->fd_top + fp->fd_len > end_rel) {
- /* New fold is completely inside this fold: Go one level deeper. */
- gap = &fp->fd_nested;
- start_rel -= fp->fd_top;
- end_rel -= fp->fd_top;
- if (use_level || fp->fd_flags == FD_LEVEL) {
- use_level = true;
- if (level >= wp->w_p_fdl) {
+ if (gap->ga_len == 0) {
+ i = 0;
+ } else {
+ for (;;) {
+ if (!foldFind(gap, start_rel.lnum, &fp)) {
+ break;
+ }
+ if (fp->fd_top + fp->fd_len > end_rel.lnum) {
+ // New fold is completely inside this fold: Go one level deeper.
+ gap = &fp->fd_nested;
+ start_rel.lnum -= fp->fd_top;
+ end_rel.lnum -= fp->fd_top;
+ if (use_level || fp->fd_flags == FD_LEVEL) {
+ use_level = true;
+ if (level >= wp->w_p_fdl) {
+ closed = true;
+ }
+ } else if (fp->fd_flags == FD_CLOSED) {
closed = true;
}
- } else if (fp->fd_flags == FD_CLOSED) {
- closed = true;
+ level++;
+ } else {
+ // This fold and new fold overlap: Insert here and move some folds
+ // inside the new fold.
+ break;
}
- level++;
- } else {
- /* This fold and new fold overlap: Insert here and move some folds
- * inside the new fold. */
- break;
}
+ i = (int)(fp - (fold_T *)gap->ga_data);
}
- i = (int)(fp - (fold_T *)gap->ga_data);
ga_grow(gap, 1);
{
fp = (fold_T *)gap->ga_data + i;
ga_init(&fold_ga, (int)sizeof(fold_T), 10);
- /* Count number of folds that will be contained in the new fold. */
- for (cont = 0; i + cont < gap->ga_len; ++cont)
- if (fp[cont].fd_top > end_rel)
+ // Count number of folds that will be contained in the new fold.
+ for (cont = 0; i + cont < gap->ga_len; cont++) {
+ if (fp[cont].fd_top > end_rel.lnum) {
break;
+ }
+ }
if (cont > 0) {
ga_grow(&fold_ga, cont);
/* If the first fold starts before the new fold, let the new fold
* start there. Otherwise the existing fold would change. */
- if (start_rel > fp->fd_top)
- start_rel = fp->fd_top;
-
- /* When last contained fold isn't completely contained, adjust end
- * of new fold. */
- if (end_rel < fp[cont - 1].fd_top + fp[cont - 1].fd_len - 1)
- end_rel = fp[cont - 1].fd_top + fp[cont - 1].fd_len - 1;
- /* Move contained folds to inside new fold. */
+ if (start_rel.lnum > fp->fd_top) {
+ start_rel.lnum = fp->fd_top;
+ }
+
+ // When last contained fold isn't completely contained, adjust end
+ // of new fold.
+ if (end_rel.lnum < fp[cont - 1].fd_top + fp[cont - 1].fd_len - 1) {
+ end_rel.lnum = fp[cont - 1].fd_top + fp[cont - 1].fd_len - 1;
+ }
+ // Move contained folds to inside new fold
memmove(fold_ga.ga_data, fp, sizeof(fold_T) * (size_t)cont);
fold_ga.ga_len += cont;
i += cont;
/* Adjust line numbers in contained folds to be relative to the
* new fold. */
- for (j = 0; j < cont; ++j)
- ((fold_T *)fold_ga.ga_data)[j].fd_top -= start_rel;
+ for (int j = 0; j < cont; j++) {
+ ((fold_T *)fold_ga.ga_data)[j].fd_top -= start_rel.lnum;
+ }
}
/* Move remaining entries to after the new fold. */
if (i < gap->ga_len)
@@ -636,8 +662,8 @@ void foldCreate(win_T *wp, linenr_T start, linenr_T end)
/* insert new fold */
fp->fd_nested = fold_ga;
- fp->fd_top = start_rel;
- fp->fd_len = end_rel - start_rel + 1;
+ fp->fd_top = start_rel.lnum;
+ fp->fd_len = end_rel.lnum - start_rel.lnum + 1;
/* We want the new fold to be closed. If it would remain open because
* of using 'foldlevel', need to adjust fd_flags of containing folds.
@@ -766,7 +792,7 @@ void deleteFold(
*/
void clearFolding(win_T *win)
{
- deleteFoldRecurse(&win->w_folds);
+ deleteFoldRecurse(win->w_buffer, &win->w_folds);
win->w_foldinvalid = false;
}
@@ -788,13 +814,15 @@ void foldUpdate(win_T *wp, linenr_T top, linenr_T bot)
return;
}
- // Mark all folds from top to bot as maybe-small.
- fold_T *fp;
- (void)foldFind(&wp->w_folds, top, &fp);
- while (fp < (fold_T *)wp->w_folds.ga_data + wp->w_folds.ga_len
- && fp->fd_top < bot) {
- fp->fd_small = kNone;
- fp++;
+ if (wp->w_folds.ga_len > 0) {
+ // Mark all folds from top to bot as maybe-small.
+ fold_T *fp;
+ (void)foldFind(&wp->w_folds, top, &fp);
+ while (fp < (fold_T *)wp->w_folds.ga_data + wp->w_folds.ga_len
+ && fp->fd_top < bot) {
+ fp->fd_small = kNone;
+ fp++;
+ }
}
if (foldmethodIsIndent(wp)
@@ -1058,11 +1086,16 @@ void cloneFoldGrowArray(garray_T *from, garray_T *to)
* the first fold below it (careful: it can be beyond the end of the array!).
* Returns FALSE when there is no fold that contains "lnum".
*/
-static int foldFind(const garray_T *gap, linenr_T lnum, fold_T **fpp)
+static bool foldFind(const garray_T *gap, linenr_T lnum, fold_T **fpp)
{
linenr_T low, high;
fold_T *fp;
+ if (gap->ga_len == 0) {
+ *fpp = NULL;
+ return false;
+ }
+
/*
* Perform a binary search.
* "low" is lowest index of possible match.
@@ -1086,7 +1119,7 @@ static int foldFind(const garray_T *gap, linenr_T lnum, fold_T **fpp)
}
}
*fpp = fp + low;
- return FALSE;
+ return false;
}
/* foldLevelWin() {{{2 */
@@ -1131,14 +1164,14 @@ static void checkupdate(win_T *wp)
* Open or close fold for current window at line "lnum".
* Repeat "count" times.
*/
-static void setFoldRepeat(linenr_T lnum, long count, int do_open)
+static void setFoldRepeat(pos_T pos, long count, int do_open)
{
int done;
long n;
for (n = 0; n < count; ++n) {
done = DONE_NOTHING;
- (void)setManualFold(lnum, do_open, FALSE, &done);
+ (void)setManualFold(pos, do_open, false, &done);
if (!(done & DONE_ACTION)) {
/* Only give an error message when no fold could be opened. */
if (n == 0 && !(done & DONE_FOLD))
@@ -1155,12 +1188,13 @@ static void setFoldRepeat(linenr_T lnum, long count, int do_open)
*/
static linenr_T
setManualFold(
- linenr_T lnum,
+ pos_T pos,
int opening, // TRUE when opening, FALSE when closing
int recurse, // TRUE when closing/opening recursive
int *donep
)
{
+ linenr_T lnum = pos.lnum;
if (foldmethodIsDiff(curwin) && curwin->w_p_scb) {
linenr_T dlnum;
@@ -1220,9 +1254,10 @@ setManualFoldWin(
gap = &wp->w_folds;
for (;; ) {
if (!foldFind(gap, lnum, &fp)) {
- /* If there is a following fold, continue there next time. */
- if (fp < (fold_T *)gap->ga_data + gap->ga_len)
+ // If there is a following fold, continue there next time.
+ if (fp != NULL && fp < (fold_T *)gap->ga_data + gap->ga_len) {
next = fp->fd_top + off;
+ }
break;
}
@@ -1313,7 +1348,7 @@ static void deleteFoldEntry(win_T *const wp, garray_T *const gap, const int idx,
fold_T *fp = (fold_T *)gap->ga_data + idx;
if (recursive || GA_EMPTY(&fp->fd_nested)) {
// recursively delete the contained folds
- deleteFoldRecurse(&fp->fd_nested);
+ deleteFoldRecurse(wp->w_buffer, &fp->fd_nested);
gap->ga_len--;
if (idx < gap->ga_len) {
memmove(fp, fp + 1, sizeof(*fp) * (size_t)(gap->ga_len - idx));
@@ -1355,9 +1390,9 @@ static void deleteFoldEntry(win_T *const wp, garray_T *const gap, const int idx,
/*
* Delete nested folds in a fold.
*/
-void deleteFoldRecurse(garray_T *gap)
+void deleteFoldRecurse(buf_T *bp, garray_T *gap)
{
-# define DELETE_FOLD_NESTED(fd) deleteFoldRecurse(&((fd)->fd_nested))
+# define DELETE_FOLD_NESTED(fd) deleteFoldRecurse(bp, &((fd)->fd_nested))
GA_DEEP_CLEAR(gap, fold_T, DELETE_FOLD_NESTED);
}
@@ -1389,6 +1424,10 @@ static void foldMarkAdjustRecurse(
linenr_T last;
linenr_T top;
+ if (gap->ga_len == 0) {
+ return;
+ }
+
/* In Insert mode an inserted line at the top of a fold is considered part
* of the fold, otherwise it isn't. */
if ((State & INSERT) && amount == (linenr_T)1 && line2 == MAXLNUM)
@@ -1593,7 +1632,7 @@ static void setSmallMaybe(garray_T *gap)
* Create a fold from line "start" to line "end" (inclusive) in the current
* window by adding markers.
*/
-static void foldCreateMarkers(win_T *wp, linenr_T start, linenr_T end)
+static void foldCreateMarkers(win_T *wp, pos_T start, pos_T end)
{
buf_T *buf = wp->w_buffer;
if (!MODIFIABLE(buf)) {
@@ -1608,13 +1647,13 @@ static void foldCreateMarkers(win_T *wp, linenr_T start, linenr_T end)
/* Update both changes here, to avoid all folds after the start are
* changed when the start marker is inserted and the end isn't. */
// TODO(teto): pass the buffer
- changed_lines(start, (colnr_T)0, end, 0L, false);
+ changed_lines(start.lnum, (colnr_T)0, end.lnum, 0L, false);
// Note: foldAddMarker() may not actually change start and/or end if
// u_save() is unable to save the buffer line, but we send the
// nvim_buf_lines_event anyway since it won't do any harm.
- int64_t num_changed = 1 + end - start;
- buf_updates_send_changes(buf, start, num_changed, num_changed, true);
+ int64_t num_changed = 1 + end.lnum - start.lnum;
+ buf_updates_send_changes(buf, start.lnum, num_changed, num_changed, true);
}
/* foldAddMarker() {{{2 */
@@ -1622,13 +1661,14 @@ static void foldCreateMarkers(win_T *wp, linenr_T start, linenr_T end)
* Add "marker[markerlen]" in 'commentstring' to line "lnum".
*/
static void foldAddMarker(
- buf_T *buf, linenr_T lnum, const char_u *marker, size_t markerlen)
+ buf_T *buf, pos_T pos, const char_u *marker, size_t markerlen)
{
char_u *cms = buf->b_p_cms;
char_u *line;
char_u *newline;
char_u *p = (char_u *)strstr((char *)buf->b_p_cms, "%s");
bool line_is_comment = false;
+ linenr_T lnum = pos.lnum;
// Allocate a new line: old-line + 'cms'-start + marker + 'cms'-end
line = ml_get_buf(buf, lnum, false);
@@ -1727,19 +1767,23 @@ static void foldDelMarker(
STRCPY(newline + (p - line), p + len);
ml_replace_buf(buf, lnum, newline, false);
extmark_splice_cols(buf, (int)lnum-1, (int)(p - line),
- (int)len,
- 0, kExtmarkUndo);
+ (int)len, 0, kExtmarkUndo);
}
break;
}
}
// get_foldtext() {{{2
-/// Return the text for a closed fold at line "lnum", with last line "lnume".
-/// When 'foldtext' isn't set puts the result in "buf[FOLD_TEXT_LEN]".
+/// Generates text to display
+///
+/// @param buf allocated memory of length FOLD_TEXT_LEN. Used when 'foldtext'
+/// isn't set puts the result in "buf[FOLD_TEXT_LEN]".
+/// @param at line "lnum", with last line "lnume".
+/// @return the text for a closed fold
+///
/// Otherwise the result is in allocated memory.
char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume,
- foldinfo_T *foldinfo, char_u *buf)
+ foldinfo_T foldinfo, char_u *buf)
FUNC_ATTR_NONNULL_ARG(1)
{
char_u *text = NULL;
@@ -1767,11 +1811,12 @@ char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume,
set_vim_var_nr(VV_FOLDSTART, (varnumber_T) lnum);
set_vim_var_nr(VV_FOLDEND, (varnumber_T) lnume);
- /* Set "v:folddashes" to a string of "level" dashes. */
- /* Set "v:foldlevel" to "level". */
- level = foldinfo->fi_level;
- if (level > (int)sizeof(dashes) - 1)
+ // Set "v:folddashes" to a string of "level" dashes.
+ // Set "v:foldlevel" to "level".
+ level = foldinfo.fi_level;
+ if (level > (int)sizeof(dashes) - 1) {
level = (int)sizeof(dashes) - 1;
+ }
memset(dashes, '-', (size_t)level);
dashes[level] = NUL;
set_vim_var_string(VV_FOLDDASHES, dashes, -1);
@@ -2265,14 +2310,15 @@ static linenr_T foldUpdateIEMSRecurse(
/* Find an existing fold to re-use. Preferably one that
* includes startlnum, otherwise one that ends just before
* startlnum or starts after it. */
- if (foldFind(gap, startlnum, &fp)
- || (fp < ((fold_T *)gap->ga_data) + gap->ga_len
- && fp->fd_top <= firstlnum)
- || foldFind(gap, firstlnum - concat, &fp)
- || (fp < ((fold_T *)gap->ga_data) + gap->ga_len
- && ((lvl < level && fp->fd_top < flp->lnum)
- || (lvl >= level
- && fp->fd_top <= flp->lnum_save)))) {
+ if (gap->ga_len > 0
+ && (foldFind(gap, startlnum, &fp)
+ || (fp < ((fold_T *)gap->ga_data) + gap->ga_len
+ && fp->fd_top <= firstlnum)
+ || foldFind(gap, firstlnum - concat, &fp)
+ || (fp < ((fold_T *)gap->ga_data) + gap->ga_len
+ && ((lvl < level && fp->fd_top < flp->lnum)
+ || (lvl >= level
+ && fp->fd_top <= flp->lnum_save))))) {
if (fp->fd_top + fp->fd_len + concat > firstlnum) {
/* Use existing fold for the new fold. If it starts
* before where we started looking, extend it. If it
@@ -2363,7 +2409,11 @@ static linenr_T foldUpdateIEMSRecurse(
} else {
/* Insert new fold. Careful: ga_data may be NULL and it
* may change! */
- i = (int)(fp - (fold_T *)gap->ga_data);
+ if (gap->ga_len == 0) {
+ i = 0;
+ } else {
+ i = (int)(fp - (fold_T *)gap->ga_data);
+ }
foldInsert(gap, i);
fp = (fold_T *)gap->ga_data + i;
/* The new fold continues until bot, unless we find the
@@ -2559,9 +2609,10 @@ static void foldInsert(garray_T *gap, int i)
ga_grow(gap, 1);
fp = (fold_T *)gap->ga_data + i;
- if (i < gap->ga_len)
+ if (gap->ga_len > 0 && i < gap->ga_len) {
memmove(fp + 1, fp, sizeof(fold_T) * (size_t)(gap->ga_len - i));
- ++gap->ga_len;
+ }
+ gap->ga_len++;
ga_init(&fp->fd_nested, (int)sizeof(fold_T), 10);
}
@@ -2596,17 +2647,18 @@ static void foldSplit(buf_T *buf, garray_T *const gap,
* any between top and bot, they have been removed by the caller. */
garray_T *const gap1 = &fp->fd_nested;
garray_T *const gap2 = &fp[1].fd_nested;
- (void)(foldFind(gap1, bot + 1 - fp->fd_top, &fp2));
- const int len = (int)((fold_T *)gap1->ga_data + gap1->ga_len - fp2);
- if (len > 0) {
- ga_grow(gap2, len);
- for (int idx = 0; idx < len; idx++) {
- ((fold_T *)gap2->ga_data)[idx] = fp2[idx];
- ((fold_T *)gap2->ga_data)[idx].fd_top
- -= fp[1].fd_top - fp->fd_top;
- }
- gap2->ga_len = len;
- gap1->ga_len -= len;
+ if (foldFind(gap1, bot + 1 - fp->fd_top, &fp2)) {
+ const int len = (int)((fold_T *)gap1->ga_data + gap1->ga_len - fp2);
+ if (len > 0) {
+ ga_grow(gap2, len);
+ for (int idx = 0; idx < len; idx++) {
+ ((fold_T *)gap2->ga_data)[idx] = fp2[idx];
+ ((fold_T *)gap2->ga_data)[idx].fd_top
+ -= fp[1].fd_top - fp->fd_top;
+ }
+ gap2->ga_len = len;
+ gap1->ga_len -= len;
+ }
}
fp->fd_len = top - fp->fd_top;
fold_changed = true;
@@ -2641,7 +2693,7 @@ static void foldRemove(
return; // nothing to do
}
- for (;; ) {
+ while (gap->ga_len > 0) {
// Find fold that includes top or a following one.
if (foldFind(gap, top, &fp) && fp->fd_top < top) {
// 2: or 3: need to delete nested folds
@@ -2657,7 +2709,8 @@ static void foldRemove(
fold_changed = true;
continue;
}
- if (fp >= (fold_T *)(gap->ga_data) + gap->ga_len
+ if (gap->ga_data == NULL
+ || fp >= (fold_T *)(gap->ga_data) + gap->ga_len
|| fp->fd_top > bot) {
// 6: Found a fold below bot, can stop looking.
break;
@@ -2738,7 +2791,8 @@ static void truncate_fold(win_T *const wp, fold_T *fp, linenr_T end)
}
#define FOLD_END(fp) ((fp)->fd_top + (fp)->fd_len - 1)
-#define VALID_FOLD(fp, gap) ((fp) < ((fold_T *)(gap)->ga_data + (gap)->ga_len))
+#define VALID_FOLD(fp, gap) \
+ ((gap)->ga_len > 0 && (fp) < ((fold_T *)(gap)->ga_data + (gap)->ga_len))
#define FOLD_INDEX(fp, gap) ((size_t)(fp - ((fold_T *)(gap)->ga_data)))
void foldMoveRange(
win_T *const wp, garray_T *gap,