diff options
Diffstat (limited to 'src/nvim/diff.c')
-rw-r--r-- | src/nvim/diff.c | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/src/nvim/diff.c b/src/nvim/diff.c index f1dd08f0e6..68441f7adc 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -44,6 +44,7 @@ #include "nvim/mbyte.h" #include "nvim/mbyte_defs.h" #include "nvim/memline.h" +#include "nvim/memline_defs.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/move.h" @@ -1621,6 +1622,11 @@ static void process_hunk(diff_T **dpp, diff_T **dprevp, int idx_orig, int idx_ne } else { // second overlap of new block with existing block dp->df_count[idx_new] += (linenr_T)hunk->count_new; + if ((dp->df_lnum[idx_new] + dp->df_count[idx_new] - 1) + > curtab->tp_diffbuf[idx_new]->b_ml.ml_line_count) { + dp->df_count[idx_new] = curtab->tp_diffbuf[idx_new]->b_ml.ml_line_count + - dp->df_lnum[idx_new] + 1; + } } // Adjust the size of the block to include all the lines to the @@ -1631,6 +1637,11 @@ static void process_hunk(diff_T **dpp, diff_T **dprevp, int idx_orig, int idx_ne if (off < 0) { // new change ends in existing block, adjust the end dp->df_count[idx_new] += -off; + if ((dp->df_lnum[idx_new] + dp->df_count[idx_new] - 1) + > curtab->tp_diffbuf[idx_new]->b_ml.ml_line_count) { + dp->df_count[idx_new] = curtab->tp_diffbuf[idx_new]->b_ml.ml_line_count + - dp->df_lnum[idx_new] + 1; + } off = 0; } @@ -1809,7 +1820,8 @@ static void find_top_diff_block(diff_T **thistopdiff, diff_T **nextblockblock, i topdiffchange = 0; } - // check if the fromwin topline is matched by the current diff. if so, set it to the top of the diff block + // check if the fromwin topline is matched by the current diff. if so, + // set it to the top of the diff block if (topline >= topdiff->df_lnum[fromidx] && topline <= (topdiff->df_lnum[fromidx] + topdiff->df_count[fromidx])) { // this line is inside the current diff block, so we will save the @@ -1854,8 +1866,10 @@ static void count_filler_lines_and_topline(int *curlinenum_to, int *linesfiller, } } else { (*linesfiller) = 0; - ch_virtual_lines = get_max_diff_length(curdif); - isfiller = (curdif->df_count[toidx] ? false : true); + if (curdif) { + ch_virtual_lines = get_max_diff_length(curdif); + isfiller = (curdif->df_count[toidx] ? false : true); + } if (isfiller) { while (curdif && curdif->df_next && curdif->df_lnum[toidx] == curdif->df_next->df_lnum[toidx] @@ -2010,10 +2024,15 @@ static void run_linematch_algorithm(diff_T *dp) size_t ndiffs = 0; for (int i = 0; i < DB_COUNT; i++) { if (curtab->tp_diffbuf[i] != NULL) { - // write the contents of the entire buffer to - // diffbufs_mm[diffbuffers_count] - diff_write_buffer(curtab->tp_diffbuf[i], &diffbufs_mm[ndiffs], - dp->df_lnum[i], dp->df_lnum[i] + dp->df_count[i] - 1); + if (dp->df_count[i] > 0) { + // write the contents of the entire buffer to + // diffbufs_mm[diffbuffers_count] + diff_write_buffer(curtab->tp_diffbuf[i], &diffbufs_mm[ndiffs], + dp->df_lnum[i], dp->df_lnum[i] + dp->df_count[i] - 1); + } else { + diffbufs_mm[ndiffs].size = 0; + diffbufs_mm[ndiffs].ptr = NULL; + } diffbufs[ndiffs] = &diffbufs_mm[ndiffs]; @@ -2049,6 +2068,12 @@ static void run_linematch_algorithm(diff_T *dp) /// Returns > 0 for inserting that many filler lines above it (never happens /// when 'diffopt' doesn't contain "filler"). /// This should only be used for windows where 'diff' is set. +/// When diffopt contains linematch, a changed/added/deleted line +/// may also have filler lines above it. In such a case, the possibilities +/// are no longer mutually exclusive. The number of filler lines is +/// returned from diff_check, and the integer 'linestatus' passed by +/// pointer is set to -1 to indicate a changed line, and -2 to indicate an +/// added line /// /// @param wp /// @param lnum @@ -2102,7 +2127,8 @@ int diff_check_with_linestatus(win_T *wp, linenr_T lnum, int *linestatus) // Useful for scrollbind calculations which need to count all the filler lines // above the screen. if (lnum >= wp->w_topline && lnum < wp->w_botline - && !dp->is_linematched && diff_linematch(dp)) { + && !dp->is_linematched && diff_linematch(dp) + && diff_check_sanity(curtab, dp)) { run_linematch_algorithm(dp); } @@ -2417,7 +2443,7 @@ int diffopt_changed(void) char *p = p_dip; while (*p != NUL) { - // Note: Keep this in sync with p_dip_values + // Note: Keep this in sync with opt_dip_values. if (strncmp(p, "filler", 6) == 0) { p += 6; diff_flags_new |= DIFF_FILLER; @@ -2464,7 +2490,7 @@ int diffopt_changed(void) p += 8; diff_flags_new |= DIFF_INTERNAL; } else if (strncmp(p, "algorithm:", 10) == 0) { - // Note: Keep this in sync with p_dip_algorithm_values. + // Note: Keep this in sync with opt_dip_algorithm_values. p += 10; if (strncmp(p, "myers", 5) == 0) { p += 5; @@ -2745,7 +2771,7 @@ bool diff_infold(win_T *wp, linenr_T lnum) void nv_diffgetput(bool put, size_t count) { if (bt_prompt(curbuf)) { - vim_beep(BO_OPER); + vim_beep(kOptBoFlagOperator); return; } |