0
0
mirror of https://github.com/vim/vim.git synced 2025-07-25 10:54:51 -04:00

updated for version 7.0200

This commit is contained in:
Bram Moolenaar 2006-02-17 21:45:41 +00:00
parent f740b29ae2
commit 49d7bf13e0
6 changed files with 356 additions and 214 deletions

View File

@ -1353,7 +1353,8 @@ enter_buffer(buf)
++curbuf->b_nwindows; ++curbuf->b_nwindows;
#ifdef FEAT_DIFF #ifdef FEAT_DIFF
diff_new_buffer(); if (curwin->w_p_diff)
diff_buf_add(curbuf);
#endif #endif
/* Cursor on first line by default. */ /* Cursor on first line by default. */
@ -4175,7 +4176,7 @@ do_arg_all(count, forceit)
#endif #endif
} }
#ifdef FEAT_WINDOWS #ifdef FEAT_WINDOWS
if (firstwin == lastwin) /* can't close last window */ if (firstwin == lastwin) /* don't close last window */
#endif #endif
use_firstwin = TRUE; use_firstwin = TRUE;
#ifdef FEAT_WINDOWS #ifdef FEAT_WINDOWS

View File

@ -15,36 +15,6 @@
#if defined(FEAT_DIFF) || defined(PROTO) #if defined(FEAT_DIFF) || defined(PROTO)
#define DB_COUNT 4 /* up to four buffers can be diff'ed */
/*
* Each diffblock defines where a block of lines starts in each of the buffers
* and how many lines it occupies in that buffer. When the lines are missing
* in the buffer the df_count[] is zero. This is all counted in
* buffer lines.
* There is always at least one unchanged line in between the diffs.
* Otherwise it would have been included in the diff above or below it.
* df_lnum[] + df_count[] is the lnum below the change. When in one buffer
* lines have been inserted, in the other buffer df_lnum[] is the line below
* the insertion and df_count[] is zero. When appending lines at the end of
* the buffer, df_lnum[] is one beyond the end!
* This is using a linked list, because the number of differences is expected
* to be reasonable small. The list is sorted on lnum.
*/
typedef struct diffblock diff_T;
struct diffblock
{
diff_T *df_next;
linenr_T df_lnum[DB_COUNT]; /* line number in buffer */
linenr_T df_count[DB_COUNT]; /* nr of inserted/changed lines */
};
static diff_T *first_diff = NULL;
static buf_T *(diffbuf[DB_COUNT]);
static int diff_invalid = TRUE; /* list of diffs is outdated */
static int diff_busy = FALSE; /* ex_diffgetput() is busy */ static int diff_busy = FALSE; /* ex_diffgetput() is busy */
/* flags obtained from the 'diffopt' option */ /* flags obtained from the 'diffopt' option */
@ -64,8 +34,10 @@ static int diff_bin_works = MAYBE; /* TRUE when "diff --binary" works, FALSE
#endif #endif
static int diff_buf_idx __ARGS((buf_T *buf)); static int diff_buf_idx __ARGS((buf_T *buf));
static void diff_check_unchanged __ARGS((diff_T *dp)); static int diff_buf_idx_tp __ARGS((buf_T *buf, tabpage_T *tp));
static int diff_check_sanity __ARGS((diff_T *dp)); static void diff_mark_adjust_tp __ARGS((tabpage_T *tp, int idx, linenr_T line1, linenr_T line2, long amount, long amount_after));
static void diff_check_unchanged __ARGS((tabpage_T *tp, diff_T *dp));
static int diff_check_sanity __ARGS((tabpage_T *tp, diff_T *dp));
static void diff_redraw __ARGS((int dofold)); static void diff_redraw __ARGS((int dofold));
static int diff_write __ARGS((buf_T *buf, char_u *fname)); static int diff_write __ARGS((buf_T *buf, char_u *fname));
static void diff_file __ARGS((char_u *tmp_orig, char_u *tmp_new, char_u *tmp_diff)); static void diff_file __ARGS((char_u *tmp_orig, char_u *tmp_new, char_u *tmp_diff));
@ -76,42 +48,30 @@ static void diff_fold_update __ARGS((diff_T *dp, int skip_idx));
#endif #endif
static void diff_read __ARGS((int idx_orig, int idx_new, char_u *fname)); static void diff_read __ARGS((int idx_orig, int idx_new, char_u *fname));
static void diff_copy_entry __ARGS((diff_T *dprev, diff_T *dp, int idx_orig, int idx_new)); static void diff_copy_entry __ARGS((diff_T *dprev, diff_T *dp, int idx_orig, int idx_new));
static diff_T *diff_alloc_new __ARGS((diff_T *dprev, diff_T *dp)); static diff_T *diff_alloc_new __ARGS((tabpage_T *tp, diff_T *dprev, diff_T *dp));
#ifndef USE_CR #ifndef USE_CR
# define tag_fgets vim_fgets # define tag_fgets vim_fgets
#endif #endif
/*
* Call this when a new buffer is being edited in the current window. curbuf
* must already have been set.
* Marks the current buffer as being part of the diff and requireing updating.
* This must be done before any autocmd, because a command the uses info
* about the screen contents.
*/
void
diff_new_buffer()
{
if (curwin->w_p_diff)
diff_buf_add(curbuf);
}
/* /*
* Called when deleting or unloading a buffer: No longer make a diff with it. * Called when deleting or unloading a buffer: No longer make a diff with it.
* Also called when 'diff' is reset in the last window showing a diff for a
* buffer.
*/ */
void void
diff_buf_delete(buf) diff_buf_delete(buf)
buf_T *buf; buf_T *buf;
{ {
int i; int i;
tabpage_T *tp;
i = diff_buf_idx(buf); for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
if (i != DB_COUNT)
{ {
diffbuf[i] = NULL; i = diff_buf_idx_tp(buf, tp);
diff_invalid = TRUE; if (i != DB_COUNT)
{
tp->tp_diffbuf[i] = NULL;
tp->tp_diff_invalid = TRUE;
}
} }
} }
@ -124,6 +84,7 @@ diff_buf_adjust(win)
win_T *win; win_T *win;
{ {
win_T *wp; win_T *wp;
int i;
if (!win->w_p_diff) if (!win->w_p_diff)
{ {
@ -133,7 +94,14 @@ diff_buf_adjust(win)
if (wp->w_buffer == win->w_buffer && wp->w_p_diff) if (wp->w_buffer == win->w_buffer && wp->w_p_diff)
break; break;
if (wp == NULL) if (wp == NULL)
diff_buf_delete(win->w_buffer); {
i = diff_buf_idx(win->w_buffer);
if (i != DB_COUNT)
{
curtab->tp_diffbuf[i] = NULL;
curtab->tp_diff_invalid = TRUE;
}
}
} }
else else
diff_buf_add(win->w_buffer); diff_buf_add(win->w_buffer);
@ -141,6 +109,11 @@ diff_buf_adjust(win)
/* /*
* Add a buffer to make diffs for. * Add a buffer to make diffs for.
* Call this when a new buffer is being edited in the current window where
* 'diff' is set.
* Marks the current buffer as being part of the diff and requireing updating.
* This must be done before any autocmd, because a command may use info
* about the screen contents.
*/ */
void void
diff_buf_add(buf) diff_buf_add(buf)
@ -152,10 +125,10 @@ diff_buf_add(buf)
return; /* It's already there. */ return; /* It's already there. */
for (i = 0; i < DB_COUNT; ++i) for (i = 0; i < DB_COUNT; ++i)
if (diffbuf[i] == NULL) if (curtab->tp_diffbuf[i] == NULL)
{ {
diffbuf[i] = buf; curtab->tp_diffbuf[i] = buf;
diff_invalid = TRUE; curtab->tp_diff_invalid = TRUE;
return; return;
} }
@ -163,7 +136,7 @@ diff_buf_add(buf)
} }
/* /*
* Find buffer "buf" in the list of diff buffers. * Find buffer "buf" in the list of diff buffers for the current tab page.
* Return its index or DB_COUNT if not found. * Return its index or DB_COUNT if not found.
*/ */
static int static int
@ -173,30 +146,53 @@ diff_buf_idx(buf)
int idx; int idx;
for (idx = 0; idx < DB_COUNT; ++idx) for (idx = 0; idx < DB_COUNT; ++idx)
if (diffbuf[idx] == buf) if (curtab->tp_diffbuf[idx] == buf)
break; break;
return idx; return idx;
} }
/* /*
* Mark the diff info as invalid, it will be updated when info is requested. * Find buffer "buf" in the list of diff buffers for tab page "tp".
* Return its index or DB_COUNT if not found.
*/
static int
diff_buf_idx_tp(buf, tp)
buf_T *buf;
tabpage_T *tp;
{
int idx;
for (idx = 0; idx < DB_COUNT; ++idx)
if (tp->tp_diffbuf[idx] == buf)
break;
return idx;
}
/*
* Mark the diff info involving buffer "buf" as invalid, it will be updated
* when info is requested.
*/ */
void void
diff_invalidate() diff_invalidate(buf)
buf_T *buf;
{ {
if (curwin->w_p_diff) tabpage_T *tp;
int i;
for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
{ {
diff_invalid = TRUE; i = diff_buf_idx_tp(buf, tp);
diff_redraw(TRUE); if (i != DB_COUNT)
{
tp->tp_diff_invalid = TRUE;
if (tp == curtab)
diff_redraw(TRUE);
}
} }
} }
/* /*
* Called by mark_adjust(): update line numbers. * Called by mark_adjust(): update line numbers in "curbuf".
* This attempts to update the changes as much as possible:
* When inserting/deleting lines outside of existing change blocks, create a
* new change block and update the line numbers in following blocks.
* When inserting/deleting lines in existing change blocks, update them.
*/ */
void void
diff_mark_adjust(line1, line2, amount, amount_after) diff_mark_adjust(line1, line2, amount, amount_after)
@ -204,11 +200,38 @@ diff_mark_adjust(line1, line2, amount, amount_after)
linenr_T line2; linenr_T line2;
long amount; long amount;
long amount_after; long amount_after;
{
int idx;
tabpage_T *tp;
/* Handle all tab pages that use the current buffer in a diff. */
for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
{
idx = diff_buf_idx_tp(curbuf, tp);
if (idx != DB_COUNT)
diff_mark_adjust_tp(tp, idx, line1, line2, amount, amount_after);
}
}
/*
* Update line numbers in tab page "tp" for "curbuf" with index "idx".
* This attempts to update the changes as much as possible:
* When inserting/deleting lines outside of existing change blocks, create a
* new change block and update the line numbers in following blocks.
* When inserting/deleting lines in existing change blocks, update them.
*/
static void
diff_mark_adjust_tp(tp, idx, line1, line2, amount, amount_after)
tabpage_T *tp;
int idx;
linenr_T line1;
linenr_T line2;
long amount;
long amount_after;
{ {
diff_T *dp; diff_T *dp;
diff_T *dprev; diff_T *dprev;
diff_T *dnext; diff_T *dnext;
int idx;
int i; int i;
int inserted, deleted; int inserted, deleted;
int n, off; int n, off;
@ -216,11 +239,6 @@ diff_mark_adjust(line1, line2, amount, amount_after)
linenr_T lnum_deleted = line1; /* lnum of remaining deletion */ linenr_T lnum_deleted = line1; /* lnum of remaining deletion */
int check_unchanged; int check_unchanged;
/* Find the index for the current buffer. */
idx = diff_buf_idx(curbuf);
if (idx == DB_COUNT)
return; /* This buffer doesn't have diffs. */
if (line2 == MAXLNUM) if (line2 == MAXLNUM)
{ {
/* mark_adjust(99, MAXLNUM, 9, 0): insert lines */ /* mark_adjust(99, MAXLNUM, 9, 0): insert lines */
@ -241,7 +259,7 @@ diff_mark_adjust(line1, line2, amount, amount_after)
} }
dprev = NULL; dprev = NULL;
dp = first_diff; dp = tp->tp_first_diff;
for (;;) for (;;)
{ {
/* If the change is after the previous diff block and before the next /* If the change is after the previous diff block and before the next
@ -253,14 +271,14 @@ diff_mark_adjust(line1, line2, amount, amount_after)
|| dprev->df_lnum[idx] + dprev->df_count[idx] < line1) || dprev->df_lnum[idx] + dprev->df_count[idx] < line1)
&& !diff_busy) && !diff_busy)
{ {
dnext = diff_alloc_new(dprev, dp); dnext = diff_alloc_new(tp, dprev, dp);
if (dnext == NULL) if (dnext == NULL)
return; return;
dnext->df_lnum[idx] = line1; dnext->df_lnum[idx] = line1;
dnext->df_count[idx] = inserted; dnext->df_count[idx] = inserted;
for (i = 0; i < DB_COUNT; ++i) for (i = 0; i < DB_COUNT; ++i)
if (diffbuf[i] != NULL && i != idx) if (tp->tp_diffbuf[i] != NULL && i != idx)
{ {
if (dprev == NULL) if (dprev == NULL)
dnext->df_lnum[i] = line1; dnext->df_lnum[i] = line1;
@ -367,7 +385,7 @@ diff_mark_adjust(line1, line2, amount, amount_after)
} }
for (i = 0; i < DB_COUNT; ++i) for (i = 0; i < DB_COUNT; ++i)
if (diffbuf[i] != NULL && i != idx) if (tp->tp_diffbuf[i] != NULL && i != idx)
{ {
dp->df_lnum[i] -= off; dp->df_lnum[i] -= off;
dp->df_count[i] += n; dp->df_count[i] += n;
@ -390,7 +408,7 @@ diff_mark_adjust(line1, line2, amount, amount_after)
/* Check if inserted lines are equal, may reduce the /* Check if inserted lines are equal, may reduce the
* size of the diff. TODO: also check for equal lines * size of the diff. TODO: also check for equal lines
* in the middle and perhaps split the block. */ * in the middle and perhaps split the block. */
diff_check_unchanged(dp); diff_check_unchanged(tp, dp);
} }
} }
@ -399,7 +417,7 @@ diff_mark_adjust(line1, line2, amount, amount_after)
== dp->df_lnum[idx]) == dp->df_lnum[idx])
{ {
for (i = 0; i < DB_COUNT; ++i) for (i = 0; i < DB_COUNT; ++i)
if (diffbuf[i] != NULL) if (tp->tp_diffbuf[i] != NULL)
dprev->df_count[i] += dp->df_count[i]; dprev->df_count[i] += dp->df_count[i];
dprev->df_next = dp->df_next; dprev->df_next = dp->df_next;
vim_free(dp); vim_free(dp);
@ -414,12 +432,12 @@ diff_mark_adjust(line1, line2, amount, amount_after)
} }
dprev = NULL; dprev = NULL;
dp = first_diff; dp = tp->tp_first_diff;
while (dp != NULL) while (dp != NULL)
{ {
/* All counts are zero, remove this entry. */ /* All counts are zero, remove this entry. */
for (i = 0; i < DB_COUNT; ++i) for (i = 0; i < DB_COUNT; ++i)
if (diffbuf[i] != NULL && dp->df_count[i] != 0) if (tp->tp_diffbuf[i] != NULL && dp->df_count[i] != 0)
break; break;
if (i == DB_COUNT) if (i == DB_COUNT)
{ {
@ -427,7 +445,7 @@ diff_mark_adjust(line1, line2, amount, amount_after)
vim_free(dp); vim_free(dp);
dp = dnext; dp = dnext;
if (dprev == NULL) if (dprev == NULL)
first_diff = dnext; tp->tp_first_diff = dnext;
else else
dprev->df_next = dnext; dprev->df_next = dnext;
} }
@ -439,19 +457,24 @@ diff_mark_adjust(line1, line2, amount, amount_after)
} }
} }
diff_redraw(TRUE);
/* Need to recompute the scroll binding, may remove or add filler lines if (tp == curtab)
* (e.g., when adding lines above w_topline). But it's slow when making {
* many changes, postpone until redrawing. */ diff_redraw(TRUE);
diff_need_scrollbind = TRUE;
/* Need to recompute the scroll binding, may remove or add filler
* lines (e.g., when adding lines above w_topline). But it's slow when
* making many changes, postpone until redrawing. */
diff_need_scrollbind = TRUE;
}
} }
/* /*
* Allocate a new diff block and link it between "dprev" and "dp". * Allocate a new diff block and link it between "dprev" and "dp".
*/ */
static diff_T * static diff_T *
diff_alloc_new(dprev, dp) diff_alloc_new(tp, dprev, dp)
tabpage_T *tp;
diff_T *dprev; diff_T *dprev;
diff_T *dp; diff_T *dp;
{ {
@ -462,7 +485,7 @@ diff_alloc_new(dprev, dp)
{ {
dnew->df_next = dp; dnew->df_next = dp;
if (dprev == NULL) if (dprev == NULL)
first_diff = dnew; tp->tp_first_diff = dnew;
else else
dprev->df_next = dnew; dprev->df_next = dnew;
} }
@ -476,7 +499,8 @@ diff_alloc_new(dprev, dp)
* must take care of removing it. * must take care of removing it.
*/ */
static void static void
diff_check_unchanged(dp) diff_check_unchanged(tp, dp)
tabpage_T *tp;
diff_T *dp; diff_T *dp;
{ {
int i_org; int i_org;
@ -488,12 +512,12 @@ diff_check_unchanged(dp)
/* Find the first buffers, use it as the original, compare the other /* Find the first buffers, use it as the original, compare the other
* buffer lines against this one. */ * buffer lines against this one. */
for (i_org = 0; i_org < DB_COUNT; ++i_org) for (i_org = 0; i_org < DB_COUNT; ++i_org)
if (diffbuf[i_org] != NULL) if (tp->tp_diffbuf[i_org] != NULL)
break; break;
if (i_org == DB_COUNT) /* safety check */ if (i_org == DB_COUNT) /* safety check */
return; return;
if (diff_check_sanity(dp) == FAIL) if (diff_check_sanity(tp, dp) == FAIL)
return; return;
/* First check lines at the top, then at the bottom. */ /* First check lines at the top, then at the bottom. */
@ -508,20 +532,20 @@ diff_check_unchanged(dp)
/* Copy the line, the next ml_get() will invalidate it. */ /* Copy the line, the next ml_get() will invalidate it. */
if (dir == BACKWARD) if (dir == BACKWARD)
off_org = dp->df_count[i_org] - 1; off_org = dp->df_count[i_org] - 1;
line_org = vim_strsave(ml_get_buf(diffbuf[i_org], line_org = vim_strsave(ml_get_buf(tp->tp_diffbuf[i_org],
dp->df_lnum[i_org] + off_org, FALSE)); dp->df_lnum[i_org] + off_org, FALSE));
if (line_org == NULL) if (line_org == NULL)
return; return;
for (i_new = i_org + 1; i_new < DB_COUNT; ++i_new) for (i_new = i_org + 1; i_new < DB_COUNT; ++i_new)
{ {
if (diffbuf[i_new] == NULL) if (tp->tp_diffbuf[i_new] == NULL)
continue; continue;
if (dir == BACKWARD) if (dir == BACKWARD)
off_new = dp->df_count[i_new] - 1; off_new = dp->df_count[i_new] - 1;
/* if other buffer doesn't have this line, it was inserted */ /* if other buffer doesn't have this line, it was inserted */
if (off_new < 0 || off_new >= dp->df_count[i_new]) if (off_new < 0 || off_new >= dp->df_count[i_new])
break; break;
if (diff_cmp(line_org, ml_get_buf(diffbuf[i_new], if (diff_cmp(line_org, ml_get_buf(tp->tp_diffbuf[i_new],
dp->df_lnum[i_new] + off_new, FALSE)) != 0) dp->df_lnum[i_new] + off_new, FALSE)) != 0)
break; break;
} }
@ -533,7 +557,7 @@ diff_check_unchanged(dp)
/* Line matched in all buffers, remove it from the diff. */ /* Line matched in all buffers, remove it from the diff. */
for (i_new = i_org; i_new < DB_COUNT; ++i_new) for (i_new = i_org; i_new < DB_COUNT; ++i_new)
if (diffbuf[i_new] != NULL) if (tp->tp_diffbuf[i_new] != NULL)
{ {
if (dir == FORWARD) if (dir == FORWARD)
++dp->df_lnum[i_new]; ++dp->df_lnum[i_new];
@ -551,21 +575,22 @@ diff_check_unchanged(dp)
* This can happen when the diff program returns invalid results. * This can happen when the diff program returns invalid results.
*/ */
static int static int
diff_check_sanity(dp) diff_check_sanity(tp, dp)
tabpage_T *tp;
diff_T *dp; diff_T *dp;
{ {
int i; int i;
for (i = 0; i < DB_COUNT; ++i) for (i = 0; i < DB_COUNT; ++i)
if (diffbuf[i] != NULL) if (tp->tp_diffbuf[i] != NULL)
if (dp->df_lnum[i] + dp->df_count[i] - 1 if (dp->df_lnum[i] + dp->df_count[i] - 1
> diffbuf[i]->b_ml.ml_line_count) > tp->tp_diffbuf[i]->b_ml.ml_line_count)
return FAIL; return FAIL;
return OK; return OK;
} }
/* /*
* Mark all diff buffers for redraw. * Mark all diff buffers in the current tab page for redraw.
*/ */
static void static void
diff_redraw(dofold) diff_redraw(dofold)
@ -624,7 +649,7 @@ diff_write(buf, fname)
/*ARGSUSED*/ /*ARGSUSED*/
void void
ex_diffupdate(eap) ex_diffupdate(eap)
exarg_T *eap; exarg_T *eap; /* can be NULL, it's not used */
{ {
buf_T *buf; buf_T *buf;
int idx_orig; int idx_orig;
@ -636,19 +661,19 @@ ex_diffupdate(eap)
int ok; int ok;
/* Delete all diffblocks. */ /* Delete all diffblocks. */
diff_clear(); diff_clear(curtab);
diff_invalid = FALSE; curtab->tp_diff_invalid = FALSE;
/* Use the first buffer as the original text. */ /* Use the first buffer as the original text. */
for (idx_orig = 0; idx_orig < DB_COUNT; ++idx_orig) for (idx_orig = 0; idx_orig < DB_COUNT; ++idx_orig)
if (diffbuf[idx_orig] != NULL) if (curtab->tp_diffbuf[idx_orig] != NULL)
break; break;
if (idx_orig == DB_COUNT) if (idx_orig == DB_COUNT)
return; return;
/* Only need to do something when there is another buffer. */ /* Only need to do something when there is another buffer. */
for (idx_new = idx_orig + 1; idx_new < DB_COUNT; ++idx_new) for (idx_new = idx_orig + 1; idx_new < DB_COUNT; ++idx_new)
if (diffbuf[idx_new] != NULL) if (curtab->tp_diffbuf[idx_new] != NULL)
break; break;
if (idx_new == DB_COUNT) if (idx_new == DB_COUNT)
return; return;
@ -743,14 +768,14 @@ ex_diffupdate(eap)
} }
/* Write the first buffer to a tempfile. */ /* Write the first buffer to a tempfile. */
buf = diffbuf[idx_orig]; buf = curtab->tp_diffbuf[idx_orig];
if (diff_write(buf, tmp_orig) == FAIL) if (diff_write(buf, tmp_orig) == FAIL)
goto theend; goto theend;
/* Make a difference between the first buffer and every other. */ /* Make a difference between the first buffer and every other. */
for (idx_new = idx_orig + 1; idx_new < DB_COUNT; ++idx_new) for (idx_new = idx_orig + 1; idx_new < DB_COUNT; ++idx_new)
{ {
buf = diffbuf[idx_new]; buf = curtab->tp_diffbuf[idx_new];
if (buf == NULL) if (buf == NULL)
continue; continue;
if (diff_write(buf, tmp_new) == FAIL) if (diff_write(buf, tmp_new) == FAIL)
@ -1134,7 +1159,7 @@ diff_read(idx_orig, idx_new, fname)
{ {
FILE *fd; FILE *fd;
diff_T *dprev = NULL; diff_T *dprev = NULL;
diff_T *dp = first_diff; diff_T *dp = curtab->tp_first_diff;
diff_T *dn, *dpl; diff_T *dn, *dpl;
long f1, l1, f2, l2; long f1, l1, f2, l2;
char_u linebuf[LBUFLEN]; /* only need to hold the diff line */ char_u linebuf[LBUFLEN]; /* only need to hold the diff line */
@ -1237,7 +1262,7 @@ diff_read(idx_orig, idx_new, fname)
if (off > 0) if (off > 0)
{ {
for (i = idx_orig; i < idx_new; ++i) for (i = idx_orig; i < idx_new; ++i)
if (diffbuf[i] != NULL) if (curtab->tp_diffbuf[i] != NULL)
dp->df_lnum[i] -= off; dp->df_lnum[i] -= off;
dp->df_lnum[idx_new] = lnum_new; dp->df_lnum[idx_new] = lnum_new;
dp->df_count[idx_new] = count_new; dp->df_count[idx_new] = count_new;
@ -1265,7 +1290,7 @@ diff_read(idx_orig, idx_new, fname)
off = 0; off = 0;
} }
for (i = idx_orig; i < idx_new + !notset; ++i) for (i = idx_orig; i < idx_new + !notset; ++i)
if (diffbuf[i] != NULL) if (curtab->tp_diffbuf[i] != NULL)
dp->df_count[i] = dpl->df_lnum[i] + dpl->df_count[i] dp->df_count[i] = dpl->df_lnum[i] + dpl->df_count[i]
- dp->df_lnum[i] + off; - dp->df_lnum[i] + off;
@ -1282,7 +1307,7 @@ diff_read(idx_orig, idx_new, fname)
else else
{ {
/* Allocate a new diffblock. */ /* Allocate a new diffblock. */
dp = diff_alloc_new(dprev, dp); dp = diff_alloc_new(curtab, dprev, dp);
if (dp == NULL) if (dp == NULL)
return; return;
@ -1295,7 +1320,7 @@ diff_read(idx_orig, idx_new, fname)
* original buffer, otherwise there would have been a change * original buffer, otherwise there would have been a change
* already. */ * already. */
for (i = idx_orig + 1; i < idx_new; ++i) for (i = idx_orig + 1; i < idx_new; ++i)
if (diffbuf[i] != NULL) if (curtab->tp_diffbuf[i] != NULL)
diff_copy_entry(dprev, dp, idx_orig, i); diff_copy_entry(dprev, dp, idx_orig, i);
} }
notset = FALSE; /* "*dp" has been set */ notset = FALSE; /* "*dp" has been set */
@ -1336,19 +1361,20 @@ diff_copy_entry(dprev, dp, idx_orig, idx_new)
} }
/* /*
* Clear the list of diffblocks. * Clear the list of diffblocks for tab page "tp".
*/ */
void void
diff_clear() diff_clear(tp)
tabpage_T *tp;
{ {
diff_T *p, *next_p; diff_T *p, *next_p;
for (p = first_diff; p != NULL; p = next_p) for (p = tp->tp_first_diff; p != NULL; p = next_p)
{ {
next_p = p->df_next; next_p = p->df_next;
vim_free(p); vim_free(p);
} }
first_diff = NULL; tp->tp_first_diff = NULL;
} }
/* /*
@ -1365,17 +1391,17 @@ diff_check(wp, lnum)
win_T *wp; win_T *wp;
linenr_T lnum; linenr_T lnum;
{ {
int idx; /* index in diffbuf[] for this buffer */ int idx; /* index in tp_diffbuf[] for this buffer */
diff_T *dp; diff_T *dp;
int maxcount; int maxcount;
int i; int i;
buf_T *buf = wp->w_buffer; buf_T *buf = wp->w_buffer;
int cmp; int cmp;
if (diff_invalid) if (curtab->tp_diff_invalid)
ex_diffupdate(NULL); /* update after a big change */ ex_diffupdate(NULL); /* update after a big change */
if (first_diff == NULL || !wp->w_p_diff) /* no diffs at all */ if (curtab->tp_first_diff == NULL || !wp->w_p_diff) /* no diffs at all */
return 0; return 0;
/* safety check: "lnum" must be a buffer line */ /* safety check: "lnum" must be a buffer line */
@ -1393,7 +1419,7 @@ diff_check(wp, lnum)
#endif #endif
/* search for a change that includes "lnum" in the list of diffblocks. */ /* search for a change that includes "lnum" in the list of diffblocks. */
for (dp = first_diff; dp != NULL; dp = dp->df_next) for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next)
if (lnum <= dp->df_lnum[idx] + dp->df_count[idx]) if (lnum <= dp->df_lnum[idx] + dp->df_count[idx])
break; break;
if (dp == NULL || lnum < dp->df_lnum[idx]) if (dp == NULL || lnum < dp->df_lnum[idx])
@ -1408,7 +1434,7 @@ diff_check(wp, lnum)
* count, check if the lines are identical. */ * count, check if the lines are identical. */
cmp = FALSE; cmp = FALSE;
for (i = 0; i < DB_COUNT; ++i) for (i = 0; i < DB_COUNT; ++i)
if (i != idx && diffbuf[i] != NULL) if (i != idx && curtab->tp_diffbuf[i] != NULL)
{ {
if (dp->df_count[i] == 0) if (dp->df_count[i] == 0)
zero = TRUE; zero = TRUE;
@ -1424,7 +1450,7 @@ diff_check(wp, lnum)
/* Compare all lines. If they are equal the lines were inserted /* Compare all lines. If they are equal the lines were inserted
* in some buffers, deleted in others, but not changed. */ * in some buffers, deleted in others, but not changed. */
for (i = 0; i < DB_COUNT; ++i) for (i = 0; i < DB_COUNT; ++i)
if (i != idx && diffbuf[i] != NULL && dp->df_count[i] != 0) if (i != idx && curtab->tp_diffbuf[i] != NULL && dp->df_count[i] != 0)
if (!diff_equal_entry(dp, idx, i)) if (!diff_equal_entry(dp, idx, i))
return -1; return -1;
} }
@ -1446,7 +1472,7 @@ diff_check(wp, lnum)
* 0 when this buf had the max count. */ * 0 when this buf had the max count. */
maxcount = 0; maxcount = 0;
for (i = 0; i < DB_COUNT; ++i) for (i = 0; i < DB_COUNT; ++i)
if (diffbuf[i] != NULL && dp->df_count[i] > maxcount) if (curtab->tp_diffbuf[i] != NULL && dp->df_count[i] > maxcount)
maxcount = dp->df_count[i]; maxcount = dp->df_count[i];
return maxcount - dp->df_count[idx]; return maxcount - dp->df_count[idx];
} }
@ -1466,15 +1492,15 @@ diff_equal_entry(dp, idx1, idx2)
if (dp->df_count[idx1] != dp->df_count[idx2]) if (dp->df_count[idx1] != dp->df_count[idx2])
return FALSE; return FALSE;
if (diff_check_sanity(dp) == FAIL) if (diff_check_sanity(curtab, dp) == FAIL)
return FALSE; return FALSE;
for (i = 0; i < dp->df_count[idx1]; ++i) for (i = 0; i < dp->df_count[idx1]; ++i)
{ {
line = vim_strsave(ml_get_buf(diffbuf[idx1], line = vim_strsave(ml_get_buf(curtab->tp_diffbuf[idx1],
dp->df_lnum[idx1] + i, FALSE)); dp->df_lnum[idx1] + i, FALSE));
if (line == NULL) if (line == NULL)
return FALSE; return FALSE;
cmp = diff_cmp(line, ml_get_buf(diffbuf[idx2], cmp = diff_cmp(line, ml_get_buf(curtab->tp_diffbuf[idx2],
dp->df_lnum[idx2] + i, FALSE)); dp->df_lnum[idx2] + i, FALSE));
vim_free(line); vim_free(line);
if (cmp != 0) if (cmp != 0)
@ -1587,13 +1613,13 @@ diff_set_topline(fromwin, towin)
if (idx == DB_COUNT) if (idx == DB_COUNT)
return; /* safety check */ return; /* safety check */
if (diff_invalid) if (curtab->tp_diff_invalid)
ex_diffupdate(NULL); /* update after a big change */ ex_diffupdate(NULL); /* update after a big change */
towin->w_topfill = 0; towin->w_topfill = 0;
/* search for a change that includes "lnum" in the list of diffblocks. */ /* search for a change that includes "lnum" in the list of diffblocks. */
for (dp = first_diff; dp != NULL; dp = dp->df_next) for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next)
if (lnum <= dp->df_lnum[idx] + dp->df_count[idx]) if (lnum <= dp->df_lnum[idx] + dp->df_count[idx])
break; break;
if (dp == NULL) if (dp == NULL)
@ -1668,6 +1694,7 @@ diffopt_changed()
char_u *p; char_u *p;
int diff_context_new = 6; int diff_context_new = 6;
int diff_flags_new = 0; int diff_flags_new = 0;
tabpage_T *tp;
p = p_dip; p = p_dip;
while (*p != NUL) while (*p != NUL)
@ -1700,7 +1727,8 @@ diffopt_changed()
/* If "icase" or "iwhite" was added or removed, need to update the diff. */ /* If "icase" or "iwhite" was added or removed, need to update the diff. */
if (diff_flags != diff_flags_new) if (diff_flags != diff_flags_new)
diff_invalid = TRUE; for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
tp->tp_diff_invalid = TRUE;
diff_flags = diff_flags_new; diff_flags = diff_flags_new;
diff_context = diff_context_new; diff_context = diff_context_new;
@ -1744,22 +1772,22 @@ diff_find_change(wp, lnum, startp, endp)
return FALSE; return FALSE;
/* search for a change that includes "lnum" in the list of diffblocks. */ /* search for a change that includes "lnum" in the list of diffblocks. */
for (dp = first_diff; dp != NULL; dp = dp->df_next) for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next)
if (lnum <= dp->df_lnum[idx] + dp->df_count[idx]) if (lnum <= dp->df_lnum[idx] + dp->df_count[idx])
break; break;
if (dp == NULL || diff_check_sanity(dp) == FAIL) if (dp == NULL || diff_check_sanity(curtab, dp) == FAIL)
return FALSE; return FALSE;
off = lnum - dp->df_lnum[idx]; off = lnum - dp->df_lnum[idx];
for (i = 0; i < DB_COUNT; ++i) for (i = 0; i < DB_COUNT; ++i)
if (diffbuf[i] != NULL && i != idx) if (curtab->tp_diffbuf[i] != NULL && i != idx)
{ {
/* Skip lines that are not in the other change (filler lines). */ /* Skip lines that are not in the other change (filler lines). */
if (off >= dp->df_count[i]) if (off >= dp->df_count[i])
continue; continue;
added = FALSE; added = FALSE;
line_new = ml_get_buf(diffbuf[i], dp->df_lnum[i] + off, FALSE); line_new = ml_get_buf(curtab->tp_diffbuf[i], dp->df_lnum[i] + off, FALSE);
/* Search for start of difference */ /* Search for start of difference */
for (si = 0; line_org[si] != NUL && line_org[si] == line_new[si]; ) for (si = 0; line_org[si] != NUL && line_org[si] == line_new[si]; )
@ -1819,9 +1847,9 @@ diff_infold(wp, lnum)
for (i = 0; i < DB_COUNT; ++i) for (i = 0; i < DB_COUNT; ++i)
{ {
if (diffbuf[i] == wp->w_buffer) if (curtab->tp_diffbuf[i] == wp->w_buffer)
idx = i; idx = i;
else if (diffbuf[i] != NULL) else if (curtab->tp_diffbuf[i] != NULL)
other = TRUE; other = TRUE;
} }
@ -1829,14 +1857,14 @@ diff_infold(wp, lnum)
if (idx == -1 || !other) if (idx == -1 || !other)
return FALSE; return FALSE;
if (diff_invalid) if (curtab->tp_diff_invalid)
ex_diffupdate(NULL); /* update after a big change */ ex_diffupdate(NULL); /* update after a big change */
/* Return if there are no diff blocks. All lines will be folded. */ /* Return if there are no diff blocks. All lines will be folded. */
if (first_diff == NULL) if (curtab->tp_first_diff == NULL)
return TRUE; return TRUE;
for (dp = first_diff; dp != NULL; dp = dp->df_next) for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next)
{ {
/* If this change is below the line there can't be any further match. */ /* If this change is below the line there can't be any further match. */
if (dp->df_lnum[idx] - diff_context > lnum) if (dp->df_lnum[idx] - diff_context > lnum)
@ -1908,10 +1936,10 @@ ex_diffgetput(eap)
{ {
/* No argument: Find the other buffer in the list of diff buffers. */ /* No argument: Find the other buffer in the list of diff buffers. */
for (idx_other = 0; idx_other < DB_COUNT; ++idx_other) for (idx_other = 0; idx_other < DB_COUNT; ++idx_other)
if (diffbuf[idx_other] != curbuf if (curtab->tp_diffbuf[idx_other] != curbuf
&& diffbuf[idx_other] != NULL && curtab->tp_diffbuf[idx_other] != NULL
&& (eap->cmdidx != CMD_diffput && (eap->cmdidx != CMD_diffput
|| diffbuf[idx_other]->b_p_ma)) || curtab->tp_diffbuf[idx_other]->b_p_ma))
break; break;
if (idx_other == DB_COUNT) if (idx_other == DB_COUNT)
{ {
@ -1921,9 +1949,9 @@ ex_diffgetput(eap)
/* Check that there isn't a third buffer in the list */ /* Check that there isn't a third buffer in the list */
for (i = idx_other + 1; i < DB_COUNT; ++i) for (i = idx_other + 1; i < DB_COUNT; ++i)
if (diffbuf[i] != curbuf if (curtab->tp_diffbuf[i] != curbuf
&& diffbuf[i] != NULL && curtab->tp_diffbuf[i] != NULL
&& (eap->cmdidx != CMD_diffput || diffbuf[i]->b_p_ma)) && (eap->cmdidx != CMD_diffput || curtab->tp_diffbuf[i]->b_p_ma))
{ {
EMSG(_("E101: More than two buffers in diff mode, don't know which one to use")); EMSG(_("E101: More than two buffers in diff mode, don't know which one to use"));
return; return;
@ -1987,11 +2015,11 @@ ex_diffgetput(eap)
/* Need to make the other buffer the current buffer to be able to make /* Need to make the other buffer the current buffer to be able to make
* changes in it. */ * changes in it. */
/* set curwin/curbuf to buf and save a few things */ /* set curwin/curbuf to buf and save a few things */
aucmd_prepbuf(&aco, diffbuf[idx_other]); aucmd_prepbuf(&aco, curtab->tp_diffbuf[idx_other]);
} }
dprev = NULL; dprev = NULL;
for (dp = first_diff; dp != NULL; ) for (dp = curtab->tp_first_diff; dp != NULL; )
{ {
if (dp->df_lnum[idx_cur] > eap->line2 + off) if (dp->df_lnum[idx_cur] > eap->line2 + off)
break; /* past the range that was specified */ break; /* past the range that was specified */
@ -2063,9 +2091,9 @@ ex_diffgetput(eap)
linenr_T nr; linenr_T nr;
nr = dp->df_lnum[idx_from] + start_skip + i; nr = dp->df_lnum[idx_from] + start_skip + i;
if (nr > diffbuf[idx_from]->b_ml.ml_line_count) if (nr > curtab->tp_diffbuf[idx_from]->b_ml.ml_line_count)
break; break;
p = vim_strsave(ml_get_buf(diffbuf[idx_from], nr, FALSE)); p = vim_strsave(ml_get_buf(curtab->tp_diffbuf[idx_from], nr, FALSE));
if (p != NULL) if (p != NULL)
{ {
ml_append(lnum + i - 1, p, 0, FALSE); ml_append(lnum + i - 1, p, 0, FALSE);
@ -2088,7 +2116,7 @@ ex_diffgetput(eap)
/* Check if there are any other buffers and if the diff is /* Check if there are any other buffers and if the diff is
* equal in them. */ * equal in them. */
for (i = 0; i < DB_COUNT; ++i) for (i = 0; i < DB_COUNT; ++i)
if (diffbuf[i] != NULL && i != idx_from && i != idx_to if (curtab->tp_diffbuf[i] != NULL && i != idx_from && i != idx_to
&& !diff_equal_entry(dp, idx_from, i)) && !diff_equal_entry(dp, idx_from, i))
break; break;
if (i == DB_COUNT) if (i == DB_COUNT)
@ -2097,7 +2125,7 @@ ex_diffgetput(eap)
dfree = dp; dfree = dp;
dp = dp->df_next; dp = dp->df_next;
if (dprev == NULL) if (dprev == NULL)
first_diff = dp; curtab->tp_first_diff = dp;
else else
dprev->df_next = dp; dprev->df_next = dp;
} }
@ -2182,7 +2210,7 @@ diff_fold_update(dp, skip_idx)
for (wp = firstwin; wp != NULL; wp = wp->w_next) for (wp = firstwin; wp != NULL; wp = wp->w_next)
for (i = 0; i < DB_COUNT; ++i) for (i = 0; i < DB_COUNT; ++i)
if (diffbuf[i] == wp->w_buffer && i != skip_idx) if (curtab->tp_diffbuf[i] == wp->w_buffer && i != skip_idx)
foldUpdate(wp, dp->df_lnum[i], foldUpdate(wp, dp->df_lnum[i],
dp->df_lnum[i] + dp->df_count[i]); dp->df_lnum[i] + dp->df_count[i]);
} }
@ -2195,7 +2223,12 @@ diff_fold_update(dp, skip_idx)
diff_mode_buf(buf) diff_mode_buf(buf)
buf_T *buf; buf_T *buf;
{ {
return diff_buf_idx(buf) != DB_COUNT; tabpage_T *tp;
for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
if (diff_buf_idx_tp(buf, tp) != DB_COUNT)
return TRUE;
return FALSE;
} }
/* /*
@ -2212,22 +2245,22 @@ diff_move_to(dir, count)
diff_T *dp; diff_T *dp;
idx = diff_buf_idx(curbuf); idx = diff_buf_idx(curbuf);
if (idx == DB_COUNT || first_diff == NULL) if (idx == DB_COUNT || curtab->tp_first_diff == NULL)
return FAIL; return FAIL;
if (diff_invalid) if (curtab->tp_diff_invalid)
ex_diffupdate(NULL); /* update after a big change */ ex_diffupdate(NULL); /* update after a big change */
if (first_diff == NULL) /* no diffs today */ if (curtab->tp_first_diff == NULL) /* no diffs today */
return FAIL; return FAIL;
while (--count >= 0) while (--count >= 0)
{ {
/* Check if already before first diff. */ /* Check if already before first diff. */
if (dir == BACKWARD && lnum <= first_diff->df_lnum[idx]) if (dir == BACKWARD && lnum <= curtab->tp_first_diff->df_lnum[idx])
break; break;
for (dp = first_diff; ; dp = dp->df_next) for (dp = curtab->tp_first_diff; ; dp = dp->df_next)
{ {
if (dp == NULL) if (dp == NULL)
break; break;
@ -2276,11 +2309,11 @@ diff_lnum_win(lnum, wp)
if (idx == DB_COUNT) /* safety check */ if (idx == DB_COUNT) /* safety check */
return (linenr_T)0; return (linenr_T)0;
if (diff_invalid) if (curtab->tp_diff_invalid)
ex_diffupdate(NULL); /* update after a big change */ ex_diffupdate(NULL); /* update after a big change */
/* search for a change that includes "lnum" in the list of diffblocks. */ /* search for a change that includes "lnum" in the list of diffblocks. */
for (dp = first_diff; dp != NULL; dp = dp->df_next) for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next)
if (lnum <= dp->df_lnum[idx] + dp->df_count[idx]) if (lnum <= dp->df_lnum[idx] + dp->df_count[idx])
break; break;

View File

@ -154,6 +154,7 @@ static void ex_all __ARGS((exarg_T *eap));
static void ex_resize __ARGS((exarg_T *eap)); static void ex_resize __ARGS((exarg_T *eap));
static void ex_stag __ARGS((exarg_T *eap)); static void ex_stag __ARGS((exarg_T *eap));
static void ex_tabclose __ARGS((exarg_T *eap)); static void ex_tabclose __ARGS((exarg_T *eap));
static void ex_tabonly __ARGS((exarg_T *eap));
static void ex_tabs __ARGS((exarg_T *eap)); static void ex_tabs __ARGS((exarg_T *eap));
#else #else
# define ex_close ex_ni # define ex_close ex_ni
@ -166,6 +167,7 @@ static void ex_tabs __ARGS((exarg_T *eap));
# define ex_tab ex_ni # define ex_tab ex_ni
# define ex_tabs ex_ni # define ex_tabs ex_ni
# define ex_tabclose ex_ni # define ex_tabclose ex_ni
# define ex_tabonly ex_ni
#endif #endif
#if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX) #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
static void ex_pclose __ARGS((exarg_T *eap)); static void ex_pclose __ARGS((exarg_T *eap));
@ -4872,8 +4874,8 @@ check_more(message, forceit)
{ {
int n = ARGCOUNT - curwin->w_arg_idx - 1; int n = ARGCOUNT - curwin->w_arg_idx - 1;
if (!forceit && only_one_window() && ARGCOUNT > 1 && !arg_had_last if (!forceit && only_one_window()
&& n >= 0 && quitmore == 0) && ARGCOUNT > 1 && !arg_had_last && n >= 0 && quitmore == 0)
{ {
if (message) if (message)
{ {
@ -6218,6 +6220,7 @@ ex_tabclose(eap)
exarg_T *eap; exarg_T *eap;
{ {
tabpage_T *tp; tabpage_T *tp;
int h = tabpageline_height();
# ifdef FEAT_CMDWIN # ifdef FEAT_CMDWIN
if (cmdwin_type != 0) if (cmdwin_type != 0)
@ -6245,6 +6248,52 @@ ex_tabclose(eap)
if (!text_locked()) if (!text_locked())
tabpage_close(eap->forceit); tabpage_close(eap->forceit);
} }
if (h != tabpageline_height())
shell_new_rows();
}
/*
* ":tabonly": close all tab pages except the current one
*/
static void
ex_tabonly(eap)
exarg_T *eap;
{
tabpage_T *tp;
int done;
int h = tabpageline_height();
# ifdef FEAT_CMDWIN
if (cmdwin_type != 0)
cmdwin_result = K_IGNORE;
else
# endif
if (first_tabpage->tp_next == NULL)
MSG(_("Already only one tab page"));
else
{
/* Repeat this up to a 1000 times, because autocommands may mess
* up the lists. */
for (done = 0; done < 1000; ++done)
{
for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
if (tp->tp_topframe != topframe)
{
tabpage_close_other(tp, eap->forceit);
/* if we failed to close it quit */
if (valid_tabpage(tp))
done = 1000;
/* start over, "tp" is now invalid */
break;
}
if (first_tabpage->tp_next == NULL)
break;
}
}
if (h != tabpageline_height())
shell_new_rows();
} }
/* /*
@ -6274,17 +6323,21 @@ tabpage_close_other(tp, forceit)
int forceit; int forceit;
{ {
int done = 0; int done = 0;
win_T *wp;
/* Limit to 1000 windows, autocommands may add a window while we close /* Limit to 1000 windows, autocommands may add a window while we close
* one. OK, so I'm paranoid... */ * one. OK, so I'm paranoid... */
while (++done < 1000) while (++done < 1000)
{ {
ex_win_close(forceit, tp->tp_firstwin, tp); wp = tp->tp_firstwin;
ex_win_close(forceit, wp, tp);
/* Autocommands may delete the tab page under our fingers. */ /* Autocommands may delete the tab page under our fingers and we may
if (!valid_tabpage(tp)) * fail to close a window with a modified buffer. */
if (!valid_tabpage(tp) || tp->tp_firstwin == wp)
break; break;
} }
redraw_tabline = TRUE;
} }
/* /*
@ -7037,7 +7090,9 @@ ex_tabs(eap)
wp = tp->tp_firstwin; wp = tp->tp_firstwin;
for ( ; wp != NULL && !got_int; wp = wp->w_next) for ( ; wp != NULL && !got_int; wp = wp->w_next)
{ {
msg_puts((char_u *)"\n "); msg_puts((char_u *)"\n ");
msg_putchar(bufIsChanged(wp->w_buffer) ? '+' : ' ');
msg_putchar(' ');
if (buf_spname(wp->w_buffer) != NULL) if (buf_spname(wp->w_buffer) != NULL)
STRCPY(IObuff, buf_spname(wp->w_buffer)); STRCPY(IObuff, buf_spname(wp->w_buffer));
else else

View File

@ -2166,8 +2166,8 @@ failed:
#ifdef FEAT_DIFF #ifdef FEAT_DIFF
/* After reading the text into the buffer the diff info needs to be /* After reading the text into the buffer the diff info needs to be
* updated. */ * updated. */
if ((newfile || read_buffer)) if (newfile || read_buffer)
diff_invalidate(); diff_invalidate(curbuf);
#endif #endif
#ifndef ALWAYS_USE_GUI #ifndef ALWAYS_USE_GUI
/* /*
@ -5524,6 +5524,7 @@ shorten_fnames(force)
} }
#ifdef FEAT_WINDOWS #ifdef FEAT_WINDOWS
status_redraw_all(); status_redraw_all();
redraw_tabline = TRUE;
#endif #endif
} }
@ -6497,7 +6498,7 @@ buf_reload(buf, orig_mode)
#ifdef FEAT_DIFF #ifdef FEAT_DIFF
/* Invalidate diff info if necessary. */ /* Invalidate diff info if necessary. */
diff_invalidate(); diff_invalidate(buf);
#endif #endif
/* Restore the topline and cursor position and check it (lines may /* Restore the topline and cursor position and check it (lines may

View File

@ -1,9 +1,8 @@
/* diff.c */ /* diff.c */
void diff_new_buffer __ARGS((void));
void diff_buf_delete __ARGS((buf_T *buf)); void diff_buf_delete __ARGS((buf_T *buf));
void diff_buf_adjust __ARGS((win_T *win)); void diff_buf_adjust __ARGS((win_T *win));
void diff_buf_add __ARGS((buf_T *buf)); void diff_buf_add __ARGS((buf_T *buf));
void diff_invalidate __ARGS((void)); void diff_invalidate __ARGS((buf_T *buf));
void diff_mark_adjust __ARGS((linenr_T line1, linenr_T line2, long amount, long amount_after)); void diff_mark_adjust __ARGS((linenr_T line1, linenr_T line2, long amount, long amount_after));
void ex_diffupdate __ARGS((exarg_T *eap)); void ex_diffupdate __ARGS((exarg_T *eap));
void ex_diffpatch __ARGS((exarg_T *eap)); void ex_diffpatch __ARGS((exarg_T *eap));
@ -11,7 +10,7 @@ void ex_diffsplit __ARGS((exarg_T *eap));
void ex_diffthis __ARGS((exarg_T *eap)); void ex_diffthis __ARGS((exarg_T *eap));
void diff_win_options __ARGS((win_T *wp, int addbuf)); void diff_win_options __ARGS((win_T *wp, int addbuf));
void ex_diffoff __ARGS((exarg_T *eap)); void ex_diffoff __ARGS((exarg_T *eap));
void diff_clear __ARGS((void)); void diff_clear __ARGS((tabpage_T *tp));
int diff_check __ARGS((win_T *wp, linenr_T lnum)); int diff_check __ARGS((win_T *wp, linenr_T lnum));
int diff_check_fill __ARGS((win_T *wp, linenr_T lnum)); int diff_check_fill __ARGS((win_T *wp, linenr_T lnum));
void diff_set_topline __ARGS((win_T *fromwin, win_T *towin)); void diff_set_topline __ARGS((win_T *fromwin, win_T *towin));

View File

@ -25,6 +25,7 @@ static void win_exchange __ARGS((long));
static void win_rotate __ARGS((int, int)); static void win_rotate __ARGS((int, int));
static void win_totop __ARGS((int size, int flags)); static void win_totop __ARGS((int size, int flags));
static void win_equal_rec __ARGS((win_T *next_curwin, int current, frame_T *topfr, int dir, int col, int row, int width, int height)); static void win_equal_rec __ARGS((win_T *next_curwin, int current, frame_T *topfr, int dir, int col, int row, int width, int height));
static int last_window __ARGS((void));
static win_T *win_free_mem __ARGS((win_T *win, int *dirp, tabpage_T *tp)); static win_T *win_free_mem __ARGS((win_T *win, int *dirp, tabpage_T *tp));
static win_T *winframe_remove __ARGS((win_T *win, int *dirp, tabpage_T *tp)); static win_T *winframe_remove __ARGS((win_T *win, int *dirp, tabpage_T *tp));
static frame_T *win_altframe __ARGS((win_T *win, tabpage_T *tp)); static frame_T *win_altframe __ARGS((win_T *win, tabpage_T *tp));
@ -43,7 +44,8 @@ static void frame_fix_width __ARGS((win_T *wp));
#endif #endif
static int win_alloc_firstwin __ARGS((void)); static int win_alloc_firstwin __ARGS((void));
#if defined(FEAT_WINDOWS) || defined(PROTO) #if defined(FEAT_WINDOWS) || defined(PROTO)
static tabpage_T *current_tabpage __ARGS((void)); static tabpage_T *alloc_tabpage __ARGS((void));
static void free_tabpage __ARGS((tabpage_T *tp));
static void leave_tabpage __ARGS((tabpage_T *tp)); static void leave_tabpage __ARGS((tabpage_T *tp));
static void enter_tabpage __ARGS((tabpage_T *tp, buf_T *old_curbuf)); static void enter_tabpage __ARGS((tabpage_T *tp, buf_T *old_curbuf));
static void frame_fix_height __ARGS((win_T *wp)); static void frame_fix_height __ARGS((win_T *wp));
@ -1824,7 +1826,7 @@ close_windows(buf, keep_curwin)
for (tp = first_tabpage; tp != NULL; tp = nexttp) for (tp = first_tabpage; tp != NULL; tp = nexttp)
{ {
nexttp = tp->tp_next; nexttp = tp->tp_next;
if (tp->tp_topframe != topframe) if (tp != curtab)
for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next) for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next)
if (wp->w_buffer == buf) if (wp->w_buffer == buf)
{ {
@ -1845,9 +1847,9 @@ close_windows(buf, keep_curwin)
/* /*
* Return TRUE if the current window is the only window that exists. * Return TRUE if the current window is the only window that exists.
* Returns FALSE if there is a window in another tab page. * Returns FALSE if there is a window, possibly in another tab page.
*/ */
int static int
last_window() last_window()
{ {
return (lastwin == firstwin && first_tabpage->tp_next == NULL); return (lastwin == firstwin && first_tabpage->tp_next == NULL);
@ -1935,7 +1937,7 @@ win_close(win, free_buf)
tabpage_T *tp; tabpage_T *tp;
tabpage_T *atp = alt_tabpage(); tabpage_T *atp = alt_tabpage();
for (tp = first_tabpage; tp->tp_topframe != topframe; tp = tp->tp_next) for (tp = first_tabpage; tp != curtab; tp = tp->tp_next)
ptp = tp; ptp = tp;
if (tp == NULL) if (tp == NULL)
{ {
@ -1946,7 +1948,7 @@ win_close(win, free_buf)
first_tabpage = tp->tp_next; first_tabpage = tp->tp_next;
else else
ptp->tp_next = tp->tp_next; ptp->tp_next = tp->tp_next;
vim_free(tp); free_tabpage(tp);
/* We don't do the window resizing stuff, let enter_tabpage() take /* We don't do the window resizing stuff, let enter_tabpage() take
* care of entering a window in another tab page. */ * care of entering a window in another tab page. */
@ -2053,7 +2055,7 @@ win_close_othertab(win, free_buf, tp)
* current tab page. */ * current tab page. */
for (ptp = first_tabpage; ptp != NULL && ptp != tp; ptp = ptp->tp_next) for (ptp = first_tabpage; ptp != NULL && ptp != tp; ptp = ptp->tp_next)
; ;
if (ptp == NULL || tp->tp_topframe == topframe) if (ptp == NULL || tp == curtab)
return; return;
/* Autocommands may have closed the window already. */ /* Autocommands may have closed the window already. */
@ -2278,19 +2280,16 @@ win_altframe(win, tp)
static tabpage_T * static tabpage_T *
alt_tabpage() alt_tabpage()
{ {
tabpage_T *tp = current_tabpage(); tabpage_T *tp;
if (tp != NULL) /* Use the next tab page if it exists. */
{ if (curtab->tp_next != NULL)
/* Use the next tab page if it exists. */ return curtab->tp_next;
if (tp->tp_next != NULL)
return tp->tp_next;
/* Find the previous tab page. */ /* Find the previous tab page. */
for (tp = first_tabpage; tp->tp_next != NULL; tp = tp->tp_next) for (tp = first_tabpage; tp->tp_next != NULL; tp = tp->tp_next)
if (tp->tp_next == current_tabpage()) if (tp->tp_next == curtab)
return tp; return tp;
}
return first_tabpage; return first_tabpage;
} }
@ -2858,11 +2857,11 @@ win_alloc_first()
return FAIL; return FAIL;
#ifdef FEAT_WINDOWS #ifdef FEAT_WINDOWS
first_tabpage = (tabpage_T *)alloc((unsigned)sizeof(tabpage_T)); first_tabpage = alloc_tabpage();
if (first_tabpage == NULL) if (first_tabpage == NULL)
return FAIL; return FAIL;
first_tabpage->tp_topframe = topframe; first_tabpage->tp_topframe = topframe;
first_tabpage->tp_next = NULL; curtab = first_tabpage;
#endif #endif
return OK; return OK;
} }
@ -2918,6 +2917,36 @@ win_init_size()
} }
#if defined(FEAT_WINDOWS) || defined(PROTO) #if defined(FEAT_WINDOWS) || defined(PROTO)
/*
* Allocate a new tabpage_T and init the values.
* Returns NULL when out of memory.
*/
static tabpage_T *
alloc_tabpage()
{
tabpage_T *tp;
tp = (tabpage_T *)alloc_clear((unsigned)sizeof(tabpage_T));
if (tp != NULL)
{
# ifdef FEAT_DIFF
tp->tp_diff_invalid = TRUE;
# endif
}
return tp;
}
static void
free_tabpage(tp)
tabpage_T *tp;
{
# ifdef FEAT_DIFF
diff_clear(tp);
# endif
vim_free(tp);
}
/* /*
* Create a new Tab page with one empty window. * Create a new Tab page with one empty window.
* Put it just after the current Tab page. * Put it just after the current Tab page.
@ -2926,17 +2955,16 @@ win_init_size()
int int
win_new_tabpage() win_new_tabpage()
{ {
tabpage_T *tp; tabpage_T *tp = curtab;
tabpage_T *newtp; tabpage_T *newtp;
newtp = (tabpage_T *)alloc((unsigned)sizeof(tabpage_T)); newtp = alloc_tabpage();
if (newtp == NULL) if (newtp == NULL)
return FAIL; return FAIL;
tp = current_tabpage();
/* Remember the current windows in this Tab page. */ /* Remember the current windows in this Tab page. */
leave_tabpage(tp); leave_tabpage(curtab);
curtab = newtp;
/* Create a new empty window. */ /* Create a new empty window. */
if (win_alloc_firstwin() == OK) if (win_alloc_firstwin() == OK)
@ -2962,23 +2990,43 @@ win_new_tabpage()
prevwin = tp->tp_prevwin; prevwin = tp->tp_prevwin;
firstwin = tp->tp_firstwin; firstwin = tp->tp_firstwin;
lastwin = tp->tp_lastwin; lastwin = tp->tp_lastwin;
curtab = tp;
return FAIL; return FAIL;
} }
/* /*
* Return a pointer to the current tab page. * Create up to "maxcount" tabpages with empty windows.
* Returns the number of resulting tab pages.
*/ */
static tabpage_T * int
current_tabpage() make_tabpages(maxcount)
int maxcount;
{ {
tabpage_T *tp; int count = maxcount;
int todo;
for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) /* Limit to 10 tabs. */
if (tp->tp_topframe == topframe) if (count > 10)
count = 10;
#ifdef FEAT_AUTOCMD
/*
* Don't execute autocommands while creating the tab pages. Must do that
* when putting the buffers in the windows.
*/
++autocmd_block;
#endif
for (todo = count - 1; todo > 0; --todo)
if (win_new_tabpage() == FAIL)
break; break;
if (tp == NULL)
EMSG2(_(e_intern2), "current_tabpage()"); #ifdef FEAT_AUTOCMD
return tp; --autocmd_block;
#endif
/* return actual number of tab pages */
return (count - todo);
} }
/* /*
@ -3044,6 +3092,7 @@ enter_tabpage(tp, old_curbuf)
{ {
int old_off = tp->tp_firstwin->w_winrow; int old_off = tp->tp_firstwin->w_winrow;
curtab = tp;
firstwin = tp->tp_firstwin; firstwin = tp->tp_firstwin;
lastwin = tp->tp_lastwin; lastwin = tp->tp_lastwin;
topframe = tp->tp_topframe; topframe = tp->tp_topframe;
@ -3057,6 +3106,10 @@ enter_tabpage(tp, old_curbuf)
last_status(FALSE); /* status line may appear or disappear */ last_status(FALSE); /* status line may appear or disappear */
(void)win_comp_pos(); /* recompute w_winrow for all windows */ (void)win_comp_pos(); /* recompute w_winrow for all windows */
must_redraw = CLEAR; /* need to redraw everything */
#ifdef FEAT_DIFF
diff_need_scrollbind = TRUE;
#endif
/* The tabpage line may have appeared or disappeared, may need to resize /* The tabpage line may have appeared or disappeared, may need to resize
* the frames for that. When the Vim window was resized need to update * the frames for that. When the Vim window was resized need to update
@ -3064,7 +3117,7 @@ enter_tabpage(tp, old_curbuf)
if (tp->tp_old_Rows != Rows || old_off != firstwin->w_winrow) if (tp->tp_old_Rows != Rows || old_off != firstwin->w_winrow)
shell_new_rows(); shell_new_rows();
#ifdef FEAT_VERTSPLIT #ifdef FEAT_VERTSPLIT
if (tp->tp_old_Columns != Columns) if (tp->tp_old_Columns != Columns && starting == 0)
shell_new_columns(); /* update window widths */ shell_new_columns(); /* update window widths */
#endif #endif
@ -3090,7 +3143,7 @@ enter_tabpage(tp, old_curbuf)
goto_tabpage(n) goto_tabpage(n)
int n; int n;
{ {
tabpage_T *otp = current_tabpage(); tabpage_T *otp = curtab;
tabpage_T *tp; tabpage_T *tp;
int i; int i;
@ -3410,7 +3463,7 @@ win_enter_ext(wp, undo_sync, curwin_invalid)
maketitle(); maketitle();
#endif #endif
curwin->w_redr_status = TRUE; curwin->w_redr_status = TRUE;
redraw_tabpage = TRUE; redraw_tabline = TRUE;
if (restart_edit) if (restart_edit)
redraw_later(VALID); /* causes status line redraw */ redraw_later(VALID); /* causes status line redraw */
@ -5272,8 +5325,8 @@ min_rows()
} }
/* /*
* Return TRUE if there is only one window, not counting a help or preview * Return TRUE if there is only one window (in the current tab page), not
* window, unless it is the current window. * counting a help or preview window, unless it is the current window.
*/ */
int int
only_one_window() only_one_window()