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.c48
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;
}