diff options
Diffstat (limited to 'src/nvim/diff.c')
-rw-r--r-- | src/nvim/diff.c | 188 |
1 files changed, 89 insertions, 99 deletions
diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 5f8b81822b..5c43b2498e 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -13,14 +13,12 @@ #include <inttypes.h> #include <stdbool.h> -#include "nvim/vim.h" -#include "xdiff/xdiff.h" #include "nvim/ascii.h" -#include "nvim/diff.h" #include "nvim/buffer.h" #include "nvim/change.h" #include "nvim/charset.h" #include "nvim/cursor.h" +#include "nvim/diff.h" #include "nvim/eval.h" #include "nvim/ex_cmds.h" #include "nvim/ex_docmd.h" @@ -29,19 +27,21 @@ #include "nvim/mark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" +#include "nvim/memory.h" #include "nvim/message.h" #include "nvim/misc1.h" -#include "nvim/memory.h" #include "nvim/move.h" #include "nvim/normal.h" #include "nvim/option.h" +#include "nvim/os/os.h" +#include "nvim/os/shell.h" #include "nvim/path.h" #include "nvim/screen.h" #include "nvim/strings.h" #include "nvim/undo.h" +#include "nvim/vim.h" #include "nvim/window.h" -#include "nvim/os/os.h" -#include "nvim/os/shell.h" +#include "xdiff/xdiff.h" static int diff_busy = false; // using diff structs, don't change them static bool diff_need_update = false; // ex_diffupdate needs to be called @@ -72,22 +72,22 @@ static TriState diff_a_works = kNone; // used for diff input typedef struct { - char_u *din_fname; // used for external diff - mmfile_t din_mmfile; // used for internal diff + char_u *din_fname; // used for external diff + mmfile_t din_mmfile; // used for internal diff } diffin_T; // used for diff result typedef struct { - char_u *dout_fname; // used for external diff - garray_T dout_ga; // used for internal diff + char_u *dout_fname; // used for external diff + garray_T dout_ga; // used for internal diff } diffout_T; // two diff inputs and one result typedef struct { - diffin_T dio_orig; // original file input - diffin_T dio_new; // new file input - diffout_T dio_diff; // diff result - int dio_internal; // using internal diff + diffin_T dio_orig; // original file input + diffin_T dio_new; // new file input + diffout_T dio_diff; // diff result + int dio_internal; // using internal diff } diffio_T; #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -119,7 +119,6 @@ void diff_buf_delete(buf_T *buf) /// @param win void diff_buf_adjust(win_T *win) { - if (!win->w_p_diff) { // When there is no window showing a diff for this buffer, remove // it from the diffs. @@ -242,8 +241,7 @@ void diff_invalidate(buf_T *buf) /// @param line2 /// @param amount /// @param amount_after -void diff_mark_adjust(linenr_T line1, linenr_T line2, long amount, - long amount_after) +void diff_mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after) { // Handle all tab pages that use the current buffer in a diff. FOR_ALL_TABS(tp) { @@ -267,8 +265,8 @@ void diff_mark_adjust(linenr_T line1, linenr_T line2, long amount, /// @param line2 /// @param amount /// @amount_after -static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, - linenr_T line2, long amount, long amount_after) +static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T line2, long amount, + long amount_after) { if (diff_internal()) { // Will update diffs before redrawing. Set _invalid to update the @@ -299,7 +297,7 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, diff_T *dp = tp->tp_first_diff; linenr_T last; - linenr_T lnum_deleted = line1; // lnum of remaining deletion + linenr_T lnum_deleted = line1; // lnum of remaining deletion int n; int off; for (;;) { @@ -323,8 +321,8 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, dnext->df_lnum[i] = line1; } else { dnext->df_lnum[i] = line1 - + (dprev->df_lnum[i] + dprev->df_count[i]) - - (dprev->df_lnum[idx] + dprev->df_count[idx]); + + (dprev->df_lnum[i] + dprev->df_count[i]) + - (dprev->df_lnum[idx] + dprev->df_count[idx]); } dnext->df_count[i] = deleted; } @@ -509,7 +507,7 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, /// @param dp /// /// @return The new diff block. -static diff_T* diff_alloc_new(tabpage_T *tp, diff_T *dprev, diff_T *dp) +static diff_T *diff_alloc_new(tabpage_T *tp, diff_T *dprev, diff_T *dp) { diff_T *dnew = xmalloc(sizeof(*dnew)); @@ -639,12 +637,18 @@ static int diff_check_sanity(tabpage_T *tp, diff_T *dp) /// @param dofold Also recompute the folds void diff_redraw(bool dofold) { + win_T *wp_other = NULL; + bool used_max_fill = false; + need_diff_redraw = false; FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { if (!wp->w_p_diff) { continue; } redraw_later(wp, SOME_VALID); + if (wp != curwin) { + wp_other = wp; + } if (dofold && foldmethodIsDiff(wp)) { foldUpdateAll(wp); } @@ -658,10 +662,18 @@ void diff_redraw(bool dofold) wp->w_topfill = (n < 0 ? 0 : n); } else if ((n > 0) && (n > wp->w_topfill)) { wp->w_topfill = n; + if (wp == curwin) { + used_max_fill = true; + } } check_topfill(wp, false); } } + if (wp_other != NULL && used_max_fill && curwin->w_p_scb) { + // The current window was set to used the maximum number of filler + // lines, may need to reduce them. + diff_set_topline(wp_other, curwin); + } } static void clear_diffin(diffin_T *din) @@ -690,10 +702,10 @@ static void clear_diffout(diffout_T *dout) /// @return FAIL for failure. static int diff_write_buffer(buf_T *buf, diffin_T *din) { - linenr_T lnum; - char_u *s; - long len = 0; - char_u *ptr; + linenr_T lnum; + char_u *s; + long len = 0; + char_u *ptr; // xdiff requires one big block of memory with all the text. for (lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) { @@ -720,7 +732,7 @@ static int diff_write_buffer(buf_T *buf, diffin_T *din) for (lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) { for (s = ml_get_buf(buf, lnum, false); *s != NUL; ) { if (diff_flags & DIFF_ICASE) { - char_u cbuf[MB_MAXBYTES + 1]; + char_u cbuf[MB_MAXBYTES + 1]; // xdiff doesn't support ignoring case, fold-case the text. int c = PTR2CHAR(s); @@ -775,12 +787,10 @@ static int diff_write(buf_T *buf, diffin_T *din) /// @param dio /// @param idx_orig /// @param eap can be NULL -static void diff_try_update(diffio_T *dio, - int idx_orig, - exarg_T *eap) +static void diff_try_update(diffio_T *dio, int idx_orig, exarg_T *eap) { buf_T *buf; - int idx_new; + int idx_new; if (dio->dio_internal) { ga_init(&dio->dio_diff.dout_ga, sizeof(char *), 1000); @@ -918,7 +928,7 @@ void ex_diffupdate(exarg_T *eap) } // Only use the internal method if it did not fail for one of the buffers. - diffio_T diffio; + diffio_T diffio; memset(&diffio, 0, sizeof(diffio)); diffio.dio_internal = diff_internal() && !diff_internal_failed(); @@ -1034,9 +1044,9 @@ static int check_external_diff(diffio_T *diffio) /// static int diff_file_internal(diffio_T *diffio) { - xpparam_t param; - xdemitconf_t emit_cfg; - xdemitcb_t emit_cb; + xpparam_t param; + xdemitconf_t emit_cfg; + xdemitcb_t emit_cb; memset(¶m, 0, sizeof(param)); memset(&emit_cfg, 0, sizeof(emit_cfg)); @@ -1059,7 +1069,7 @@ static int diff_file_internal(diffio_T *diffio) emit_cfg.ctxlen = 0; // don't need any diff_context here emit_cb.priv = &diffio->dio_diff; - emit_cb.outf = xdiff_out; + emit_cb.out_line = xdiff_out; if (xdl_diff(&diffio->dio_orig.din_mmfile, &diffio->dio_new.din_mmfile, ¶m, &emit_cfg, &emit_cb) < 0) { @@ -1076,9 +1086,9 @@ static int diff_file_internal(diffio_T *diffio) /// @return OK or FAIL static int diff_file(diffio_T *dio) { - char *tmp_orig = (char *)dio->dio_orig.din_fname; - char *tmp_new = (char *)dio->dio_new.din_fname; - char *tmp_diff = (char *)dio->dio_diff.dout_fname; + char *tmp_orig = (char *)dio->dio_orig.din_fname; + char *tmp_new = (char *)dio->dio_new.din_fname; + char *tmp_diff = (char *)dio->dio_diff.dout_fname; if (*p_dex != NUL) { // Use 'diffexpr' to generate the diff file. eval_diff(tmp_orig, tmp_new, tmp_diff); @@ -1109,9 +1119,9 @@ static int diff_file(diffio_T *dio) (diff_flags & DIFF_IBLANK) ? "-B " : "", (diff_flags & DIFF_ICASE) ? "-i " : "", tmp_orig, tmp_new); - append_redir(cmd, len, (char *) p_srr, tmp_diff); + append_redir(cmd, len, (char *)p_srr, tmp_diff); block_autocmds(); // Avoid ShellCmdPost stuff - (void)call_shell((char_u *) cmd, + (void)call_shell((char_u *)cmd, kShellOptFilter | kShellOptSilent | kShellOptDoOut, NULL); unblock_autocmds(); @@ -1157,8 +1167,8 @@ void ex_diffpatch(exarg_T *eap) #ifdef UNIX // Get the absolute path of the patchfile, changing directory below. fullname = FullName_save((char *)eap->arg, false); - esc_name = vim_strsave_shellescape( - (fullname != NULL ? (char_u *)fullname : eap->arg), true, true); + esc_name = + vim_strsave_shellescape((fullname != NULL ? (char_u *)fullname : eap->arg), true, true); #else esc_name = vim_strsave_shellescape(eap->arg, true, true); #endif @@ -1310,8 +1320,8 @@ 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); + curwin->w_cursor.lnum = diff_get_corresponding_line(old_curbuf.br_buf, + old_curwin->w_cursor.lnum); } } // Now that lines are folded scroll to show the cursor at the same @@ -1330,15 +1340,15 @@ void ex_diffthis(exarg_T *eap) static void set_diff_option(win_T *wp, int value) { - win_T *old_curwin = curwin; - - curwin = wp; - curbuf = curwin->w_buffer; - curbuf_lock++; - set_option_value("diff", (long)value, NULL, OPT_LOCAL); - curbuf_lock--; - curwin = old_curwin; - curbuf = curwin->w_buffer; + win_T *old_curwin = curwin; + + curwin = wp; + curbuf = curwin->w_buffer; + curbuf->b_ro_locked++; + set_option_value("diff", (long)value, NULL, OPT_LOCAL); + curbuf->b_ro_locked--; + curwin = old_curwin; + curbuf = curwin->w_buffer; } @@ -1710,8 +1720,7 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout) /// @param dp /// @param idx_orig /// @param idx_new -static void diff_copy_entry(diff_T *dprev, diff_T *dp, int idx_orig, - int idx_new) +static void diff_copy_entry(diff_T *dprev, diff_T *dp, int idx_orig, int idx_new) { long off; @@ -1755,7 +1764,7 @@ void diff_clear(tabpage_T *tp) /// @return diff status. int diff_check(win_T *wp, linenr_T lnum) { - int idx; // index in tp_diffbuf[] for this buffer + int idx; // index in tp_diffbuf[] for this buffer diff_T *dp; int maxcount; int i; @@ -1869,7 +1878,7 @@ int diff_check(win_T *wp, linenr_T lnum) /// @param idx1 first entry in diff "dp" /// @param idx2 second entry in diff "dp" /// -/// @return true if two entires are equal. +/// @return true if two entries are equal. static bool diff_equal_entry(diff_T *dp, int idx1, int idx2) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1) { @@ -1898,8 +1907,7 @@ static bool diff_equal_entry(diff_T *dp, int idx1, int idx2) // Compare the characters at "p1" and "p2". If they are equal (possibly // ignoring case) return true and set "len" to the number of bytes. -static bool diff_equal_char(const char_u *const p1, const char_u *const p2, - int *const len) +static bool diff_equal_char(const char_u *const p1, const char_u *const p2, int *const len) { const int l = utfc_ptr2len(p1); @@ -1977,26 +1985,6 @@ static int diff_cmp(char_u *s1, char_u *s2) return 0; } -/// Return the number of filler lines above "lnum". -/// -/// @param wp -/// @param lnum -/// -/// @return Number of filler lines above lnum -int diff_check_fill(win_T *wp, linenr_T lnum) -{ - // be quick when there are no filler lines - if (!(diff_flags & DIFF_FILLER)) { - return 0; - } - int n = diff_check(wp, lnum); - - if (n <= 0) { - return 0; - } - return n; -} - /// Set the topline of "towin" to match the position in "fromwin", so that they /// show the same diff'ed lines. /// @@ -2022,6 +2010,7 @@ void diff_set_topline(win_T *fromwin, win_T *towin) } towin->w_topfill = 0; + // search for a change that includes "lnum" in the list of diffblocks. for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) { if (lnum <= dp->df_lnum[fromidx] + dp->df_count[fromidx]) { @@ -2247,6 +2236,13 @@ bool diffopt_closeoff(void) return (diff_flags & DIFF_CLOSE_OFF) != 0; } +// Return true if 'diffopt' contains "filler". +bool diffopt_filler(void) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + return (diff_flags & DIFF_FILLER) != 0; +} + /// Find the difference within a changed line. /// /// @param wp window whose current buffer to check @@ -2523,7 +2519,7 @@ void ex_diffgetput(exarg_T *eap) if ((curtab->tp_diffbuf[i] != curbuf) && (curtab->tp_diffbuf[i] != NULL) && ((eap->cmdidx != CMD_diffput) - || MODIFIABLE(curtab->tp_diffbuf[i]))) { + || MODIFIABLE(curtab->tp_diffbuf[i]))) { EMSG(_("E101: More than two buffers in diff mode, don't know " "which one to use")); return; @@ -2603,7 +2599,7 @@ void ex_diffgetput(exarg_T *eap) // FileChangedRO autocommand, which may do nasty things and mess // everything up. if (!curbuf->b_changed) { - change_warning(0); + change_warning(curbuf, 0); if (diff_buf_idx(curbuf) != idx_to) { EMSG(_("E787: Buffer changed unexpectedly")); goto theend; @@ -2669,7 +2665,7 @@ void ex_diffgetput(exarg_T *eap) } } - buf_empty = BUFEMPTY(); + buf_empty = buf_is_empty(curbuf); added = 0; for (i = 0; i < count; ++i) { @@ -2944,7 +2940,7 @@ static linenr_T diff_get_corresponding_line_int(buf_T *buf1, linenr_T lnum1) 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 @@ -3021,15 +3017,12 @@ linenr_T diff_lnum_win(linenr_T lnum, win_T *wp) /// Handle an ED style diff line. /// Return FAIL if the line does not contain diff info. /// -static int parse_diff_ed(char_u *line, - linenr_T *lnum_orig, - long *count_orig, - linenr_T *lnum_new, - long *count_new) +static int parse_diff_ed(char_u *line, linenr_T *lnum_orig, long *count_orig, linenr_T *lnum_new, + long *count_new) { char_u *p; - long f1, l1, f2, l2; - int difftype; + long f1, l1, f2, l2; + int difftype; // The line must be one of three formats: // change: {first}[,{last}]c{first}[,{last}] @@ -3079,14 +3072,11 @@ static int parse_diff_ed(char_u *line, /// Parses unified diff with zero(!) context lines. /// Return FAIL if there is no diff information in "line". /// -static int parse_diff_unified(char_u *line, - linenr_T *lnum_orig, - long *count_orig, - linenr_T *lnum_new, - long *count_new) +static int parse_diff_unified(char_u *line, linenr_T *lnum_orig, long *count_orig, + linenr_T *lnum_new, long *count_new) { char_u *p; - long oldline, oldcount, newline, newcount; + long oldline, oldcount, newline, newcount; // Parse unified diff hunk header: // @@ -oldline,oldcount +newline,newcount @@ @@ -3139,7 +3129,7 @@ static int parse_diff_unified(char_u *line, static int xdiff_out(void *priv, mmbuffer_t *mb, int nbuf) { diffout_T *dout = (diffout_T *)priv; - char_u *p; + char_u *p; // The header line always comes by itself, text lines in at least two // parts. We drop the text part. |