diff options
Diffstat (limited to 'src/nvim/diff.c')
-rw-r--r-- | src/nvim/diff.c | 101 |
1 files changed, 55 insertions, 46 deletions
diff --git a/src/nvim/diff.c b/src/nvim/diff.c index f7b96ba3e1..17de4284ce 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. @@ -129,7 +132,7 @@ void diff_buf_add(buf_T *buf) } } - EMSGN(_("E96: Can not diff more than %" PRId64 " buffers"), DB_COUNT); + EMSGN(_("E96: Cannot diff more than %" PRId64 " buffers"), DB_COUNT); } /// Find buffer "buf" in the list of diff buffers for the current tab page. @@ -1004,7 +1007,12 @@ theend: void ex_diffsplit(exarg_T *eap) { win_T *old_curwin = curwin; - buf_T *old_curbuf = curbuf; + bufref_T old_curbuf; + set_bufref(&old_curbuf, curbuf); + + // Need to compute w_fraction when no redraw happened yet. + validate_cursor(); + set_fraction(curwin); // don't use a new tab page, each tab page has its own diffs cmdmod.tab = 0; @@ -1022,15 +1030,15 @@ void ex_diffsplit(exarg_T *eap) if (win_valid(old_curwin)) { diff_win_options(old_curwin, true); - if (buf_valid(old_curbuf)) { + 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, - 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 + // relative position. + scroll_to_fraction(curwin, curwin->w_height); } } } @@ -1068,8 +1076,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) { @@ -1153,10 +1161,13 @@ void ex_diffoff(exarg_T *eap) } foldUpdateAll(wp); - - // make sure topline is not halfway through a fold - changed_window_setting_win(wp); } + // remove filler lines + wp->w_topfill = 0; + + // make sure topline is not halfway a fold and cursor is + // invalidated + changed_window_setting_win(wp); // Note: 'sbo' is not restored, it's a global option. diff_buf_adjust(wp); @@ -1575,7 +1586,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. @@ -2297,7 +2308,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. @@ -2449,25 +2460,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) @@ -2487,15 +2490,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]; @@ -2504,30 +2501,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 |