aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/diff.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/diff.c')
-rw-r--r--src/nvim/diff.c97
1 files changed, 57 insertions, 40 deletions
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 11ade20c1c..cc0f3b2629 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -1,3 +1,6 @@
+// This is an open source non-commercial project. Dear PVS-Studio, please check
+// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
/// @file diff.c
///
/// Code for diff'ing two, three or four buffers.
@@ -132,6 +135,20 @@ void diff_buf_add(buf_T *buf)
EMSGN(_("E96: Cannot diff more than %" PRId64 " buffers"), DB_COUNT);
}
+///
+/// Remove all buffers to make diffs for.
+///
+static void diff_buf_clear(void)
+{
+ for (int i = 0; i < DB_COUNT; i++) {
+ if (curtab->tp_diffbuf[i] != NULL) {
+ curtab->tp_diffbuf[i] = NULL;
+ curtab->tp_diff_invalid = true;
+ diff_redraw(true);
+ }
+ }
+}
+
/// Find buffer "buf" in the list of diff buffers for the current tab page.
///
/// @param buf The buffer to find.
@@ -1030,10 +1047,7 @@ void ex_diffsplit(exarg_T *eap)
if (bufref_valid(&old_curbuf)) {
// Move the cursor position to that of the old window.
curwin->w_cursor.lnum = diff_get_corresponding_line(
- old_curbuf.br_buf,
- old_curwin->w_cursor.lnum,
- curbuf,
- curwin->w_cursor.lnum);
+ old_curbuf.br_buf, old_curwin->w_cursor.lnum);
}
}
// Now that lines are folded scroll to show the cursor at the same
@@ -1076,8 +1090,8 @@ void diff_win_options(win_T *wp, int addbuf)
if (!wp->w_p_diff) {
wp->w_p_wrap_save = wp->w_p_wrap;
}
- wp->w_p_wrap = FALSE;
- curwin = wp;
+ wp->w_p_wrap = false;
+ curwin = wp; // -V519
curbuf = curwin->w_buffer;
if (!wp->w_p_diff) {
@@ -1175,6 +1189,11 @@ void ex_diffoff(exarg_T *eap)
diffwin |= wp->w_p_diff;
}
+ // Also remove hidden buffers from the list.
+ if (eap->forceit) {
+ diff_buf_clear();
+ }
+
// Remove "hor" from from 'scrollopt' if there are no diff windows left.
if (!diffwin && (vim_strchr(p_sbo, 'h') != NULL)) {
do_cmdline_cmd("set sbo-=hor");
@@ -1586,7 +1605,7 @@ static int diff_cmp(char_u *s1, char_u *s2)
}
if ((diff_flags & DIFF_ICASE) && !(diff_flags & DIFF_IWHITE)) {
- return mb_stricmp(s1, s2);
+ return mb_stricmp((const char *)s1, (const char *)s2);
}
// Ignore white space changes and possibly ignore case.
@@ -2308,7 +2327,7 @@ void ex_diffgetput(exarg_T *eap)
// Adjust marks. This will change the following entries!
if (added != 0) {
- mark_adjust(lnum, lnum + count - 1, (long)MAXLNUM, (long)added);
+ mark_adjust(lnum, lnum + count - 1, (long)MAXLNUM, (long)added, false);
if (curwin->w_cursor.lnum >= lnum) {
// Adjust the cursor position if it's in/after the changed
// lines.
@@ -2460,25 +2479,17 @@ int diff_move_to(int dir, long count)
return OK;
}
-/// Finds the corresponding line in a diff.
-///
-/// @param buf1
-/// @param lnum1
-/// @param buf2
-/// @param lnum3
-///
-/// @return The corresponding line.
-linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1, buf_T *buf2,
- linenr_T lnum3)
+/// Return the line number in the current window that is closest to "lnum1" in
+/// "buf1" in diff mode.
+static linenr_T diff_get_corresponding_line_int(buf_T *buf1, linenr_T lnum1)
{
int idx1;
int idx2;
diff_T *dp;
int baseline = 0;
- linenr_T lnum2;
idx1 = diff_buf_idx(buf1);
- idx2 = diff_buf_idx(buf2);
+ idx2 = diff_buf_idx(curbuf);
if ((idx1 == DB_COUNT)
|| (idx2 == DB_COUNT)
@@ -2498,15 +2509,9 @@ linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1, buf_T *buf2,
for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) {
if (dp->df_lnum[idx1] > lnum1) {
- lnum2 = lnum1 - baseline;
-
- // don't end up past the end of the file
- if (lnum2 > buf2->b_ml.ml_line_count) {
- lnum2 = buf2->b_ml.ml_line_count;
- }
-
- return lnum2;
- } else if ((dp->df_lnum[idx1] + dp->df_count[idx1]) > lnum1) {
+ return lnum1 - baseline;
+ }
+ if ((dp->df_lnum[idx1] + dp->df_count[idx1]) > lnum1) {
// Inside the diffblock
baseline = lnum1 - dp->df_lnum[idx1];
@@ -2515,30 +2520,42 @@ linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1, buf_T *buf2,
}
return dp->df_lnum[idx2] + baseline;
- } else if ((dp->df_lnum[idx1] == lnum1)
- && (dp->df_count[idx1] == 0)
- && (dp->df_lnum[idx2] <= lnum3)
- && ((dp->df_lnum[idx2] + dp->df_count[idx2]) > lnum3)) {
+ }
+ if ((dp->df_lnum[idx1] == lnum1)
+ && (dp->df_count[idx1] == 0)
+ && (dp->df_lnum[idx2] <= curwin->w_cursor.lnum)
+ && ((dp->df_lnum[idx2] + dp->df_count[idx2])
+ > curwin->w_cursor.lnum)) {
// Special case: if the cursor is just after a zero-count
// block (i.e. all filler) and the target cursor is already
// inside the corresponding block, leave the target cursor
// unmoved. This makes repeated CTRL-W W operations work
// as expected.
- return lnum3;
+ return curwin->w_cursor.lnum;
}
baseline = (dp->df_lnum[idx1] + dp->df_count[idx1])
- - (dp->df_lnum[idx2] + dp->df_count[idx2]);
+ - (dp->df_lnum[idx2] + dp->df_count[idx2]);
}
// If we get here then the cursor is after the last diff
- lnum2 = lnum1 - baseline;
+ return lnum1 - baseline;
+}
+
+/// Finds the corresponding line in a diff.
+///
+/// @param buf1
+/// @param lnum1
+///
+/// @return The corresponding line.
+linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1)
+{
+ linenr_T lnum = diff_get_corresponding_line_int(buf1, lnum1);
// don't end up past the end of the file
- if (lnum2 > buf2->b_ml.ml_line_count) {
- lnum2 = buf2->b_ml.ml_line_count;
+ if (lnum > curbuf->b_ml.ml_line_count) {
+ return curbuf->b_ml.ml_line_count;
}
-
- return lnum2;
+ return lnum;
}
/// For line "lnum" in the current window find the equivalent lnum in window