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.c399
1 files changed, 197 insertions, 202 deletions
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 1f8acd8c79..0b55fb877c 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -29,7 +29,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/normal.h"
#include "nvim/option.h"
@@ -38,6 +37,7 @@
#include "nvim/path.h"
#include "nvim/screen.h"
#include "nvim/strings.h"
+#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/vim.h"
#include "nvim/window.h"
@@ -82,6 +82,14 @@ typedef struct {
garray_T dout_ga; // used for internal diff
} diffout_T;
+// used for recording hunks from xdiff
+typedef struct {
+ linenr_T lnum_orig;
+ long count_orig;
+ linenr_T lnum_new;
+ long count_new;
+} diffhunk_T;
+
// two diff inputs and one result
typedef struct {
diffin_T dio_orig; // original file input
@@ -158,8 +166,7 @@ void diff_buf_add(buf_T *buf)
return;
}
- int i;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (int i = 0; i < DB_COUNT; i++) {
if (curtab->tp_diffbuf[i] == NULL) {
curtab->tp_diffbuf[i] = buf;
curtab->tp_diff_invalid = true;
@@ -193,7 +200,7 @@ static void diff_buf_clear(void)
static int diff_buf_idx(buf_T *buf)
{
int idx;
- for (idx = 0; idx < DB_COUNT; ++idx) {
+ for (idx = 0; idx < DB_COUNT; idx++) {
if (curtab->tp_diffbuf[idx] == buf) {
break;
}
@@ -210,7 +217,7 @@ static int diff_buf_idx(buf_T *buf)
static int diff_buf_idx_tp(buf_T *buf, tabpage_T *tp)
{
int idx;
- for (idx = 0; idx < DB_COUNT; ++idx) {
+ for (idx = 0; idx < DB_COUNT; idx++) {
if (tp->tp_diffbuf[idx] == buf) {
break;
}
@@ -296,7 +303,6 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T
diff_T *dprev = NULL;
diff_T *dp = tp->tp_first_diff;
- linenr_T last;
linenr_T lnum_deleted = line1; // lnum of remaining deletion
int n;
int off;
@@ -315,7 +321,7 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T
dnext->df_lnum[idx] = line1;
dnext->df_count[idx] = inserted;
int i;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (i = 0; i < DB_COUNT; i++) {
if ((tp->tp_diffbuf[i] != NULL) && (i != idx)) {
if (dprev == NULL) {
dnext->df_lnum[i] = line1;
@@ -346,7 +352,7 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T
// 3 5 6
// compute last line of this change
- last = dp->df_lnum[idx] + dp->df_count[idx] - 1;
+ linenr_T last = dp->df_lnum[idx] + dp->df_count[idx] - 1;
// 1. change completely above line1: nothing to do
if (last >= line1 - 1) {
@@ -413,7 +419,7 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T
}
int i;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (i = 0; i < DB_COUNT; i++) {
if ((tp->tp_diffbuf[i] != NULL) && (i != idx)) {
dp->df_lnum[i] -= off;
dp->df_count[i] += n;
@@ -434,7 +440,7 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T
// Check if inserted lines are equal, may reduce the size of the
// diff.
//
- // TODO: also check for equal lines in the middle and perhaps split
+ // TODO(unknown): also check for equal lines in the middle and perhaps split
// the block.
diff_check_unchanged(tp, dp);
}
@@ -445,7 +451,7 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T
if ((dprev != NULL)
&& (dprev->df_lnum[idx] + dprev->df_count[idx] == dp->df_lnum[idx])) {
int i;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (i = 0; i < DB_COUNT; i++) {
if (tp->tp_diffbuf[i] != NULL) {
dprev->df_count[i] += dp->df_count[i];
}
@@ -466,7 +472,7 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T
while (dp != NULL) {
// All counts are zero, remove this entry.
int i;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (i = 0; i < DB_COUNT; i++) {
if ((tp->tp_diffbuf[i] != NULL) && (dp->df_count[i] != 0)) {
break;
}
@@ -534,7 +540,7 @@ static void diff_check_unchanged(tabpage_T *tp, diff_T *dp)
// Find the first buffers, use it as the original, compare the other
// buffer lines against this one.
int i_org;
- for (i_org = 0; i_org < DB_COUNT; ++i_org) {
+ for (i_org = 0; i_org < DB_COUNT; i_org++) {
if (tp->tp_diffbuf[i_org] != NULL) {
break;
}
@@ -566,7 +572,7 @@ static void diff_check_unchanged(tabpage_T *tp, diff_T *dp)
false));
int i_new;
- for (i_new = i_org + 1; i_new < DB_COUNT; ++i_new) {
+ for (i_new = i_org + 1; i_new < DB_COUNT; i_new++) {
if (tp->tp_diffbuf[i_new] == NULL) {
continue;
}
@@ -594,7 +600,7 @@ static void diff_check_unchanged(tabpage_T *tp, diff_T *dp)
}
// Line matched in all buffers, remove it from the diff.
- for (i_new = i_org; i_new < DB_COUNT; ++i_new) {
+ for (i_new = i_org; i_new < DB_COUNT; i_new++) {
if (tp->tp_diffbuf[i_new] != NULL) {
if (dir == FORWARD) {
dp->df_lnum[i_new]++;
@@ -620,8 +626,7 @@ static void diff_check_unchanged(tabpage_T *tp, diff_T *dp)
/// @return OK if the diff block doesn't contain invalid line numbers.
static int diff_check_sanity(tabpage_T *tp, diff_T *dp)
{
- int i;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (int i = 0; i < DB_COUNT; i++) {
if (tp->tp_diffbuf[i] != NULL) {
if (dp->df_lnum[i] + dp->df_count[i] - 1
> tp->tp_diffbuf[i]->b_ml.ml_line_count) {
@@ -674,11 +679,11 @@ void diff_redraw(bool dofold)
}
if (wp_other != NULL && curwin->w_p_scb) {
if (used_max_fill_curwin) {
- // The current window was set to used the maximum number of filler
+ // The current window was set to use the maximum number of filler
// lines, may need to reduce them.
diff_set_topline(wp_other, curwin);
} else if (used_max_fill_other) {
- // The other window was set to used the maximum number of filler
+ // The other window was set to use the maximum number of filler
// lines, may need to reduce them.
diff_set_topline(curwin, wp_other);
}
@@ -711,16 +716,13 @@ 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;
// xdiff requires one big block of memory with all the text.
- for (lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
+ for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
len += (long)STRLEN(ml_get_buf(buf, lnum, false)) + 1;
}
- ptr = try_malloc(len);
+ char_u *ptr = try_malloc(len);
if (ptr == NULL) {
// Allocating memory failed. This can happen, because we try to read
// the whole buffer text into memory. Set the failed flag, the diff
@@ -738,14 +740,19 @@ static int diff_write_buffer(buf_T *buf, diffin_T *din)
din->din_mmfile.size = len;
len = 0;
- for (lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
- for (s = ml_get_buf(buf, lnum, false); *s != NUL;) {
+ for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
+ for (char_u *s = ml_get_buf(buf, lnum, false); *s != NUL;) {
if (diff_flags & DIFF_ICASE) {
+ int c;
char_u cbuf[MB_MAXBYTES + 1];
- // xdiff doesn't support ignoring case, fold-case the text.
- int c = utf_ptr2char(s);
- c = utf_fold(c);
+ if (*s == NL) {
+ c = NUL;
+ } else {
+ // xdiff doesn't support ignoring case, fold-case the text.
+ c = utf_ptr2char(s);
+ c = utf_fold(c);
+ }
const int orig_len = utfc_ptr2len(s);
if (utf_char2bytes(c, cbuf) != orig_len) {
// TODO(Bram): handle byte length difference
@@ -757,7 +764,8 @@ static int diff_write_buffer(buf_T *buf, diffin_T *din)
s += orig_len;
len += orig_len;
} else {
- ptr[len++] = *s++;
+ ptr[len++] = *s == NL ? NUL : *s;
+ s++;
}
}
ptr[len++] = NL;
@@ -782,9 +790,14 @@ static int diff_write(buf_T *buf, diffin_T *din)
// Always use 'fileformat' set to "unix".
char_u *save_ff = buf->b_p_ff;
buf->b_p_ff = vim_strsave((char_u *)FF_UNIX);
+ const bool save_lockmarks = cmdmod.lockmarks;
+ // Writing the buffer is an implementation detail of performing the diff,
+ // so it shouldn't update the '[ and '] marks.
+ cmdmod.lockmarks = true;
int r = buf_write(buf, din->din_fname, NULL,
(linenr_T)1, buf->b_ml.ml_line_count,
NULL, false, false, false, true);
+ cmdmod.lockmarks = save_lockmarks;
free_string_option(buf->b_p_ff);
buf->b_p_ff = save_ff;
return r;
@@ -798,9 +811,6 @@ static int diff_write(buf_T *buf, diffin_T *din)
/// @param eap can be NULL
static void diff_try_update(diffio_T *dio, int idx_orig, exarg_T *eap)
{
- buf_T *buf;
- int idx_new;
-
if (dio->dio_internal) {
ga_init(&dio->dio_diff.dout_ga, sizeof(char *), 1000);
} else {
@@ -820,9 +830,11 @@ static void diff_try_update(diffio_T *dio, int idx_orig, exarg_T *eap)
goto theend;
}
+ buf_T *buf;
+
// :diffupdate!
if (eap != NULL && eap->forceit) {
- for (idx_new = idx_orig; idx_new < DB_COUNT; idx_new++) {
+ for (int idx_new = idx_orig; idx_new < DB_COUNT; idx_new++) {
buf = curtab->tp_diffbuf[idx_new];
if (buf_valid(buf)) {
buf_check_timestamp(buf);
@@ -837,7 +849,7 @@ static void diff_try_update(diffio_T *dio, int idx_orig, exarg_T *eap)
}
// Make a difference between the first buffer and every other.
- for (idx_new = idx_orig + 1; idx_new < DB_COUNT; idx_new++) {
+ for (int idx_new = idx_orig + 1; idx_new < DB_COUNT; idx_new++) {
buf = curtab->tp_diffbuf[idx_new];
if (buf == NULL || buf->b_ml.ml_mfp == NULL) {
continue; // skip buffer that isn't loaded
@@ -852,7 +864,7 @@ static void diff_try_update(diffio_T *dio, int idx_orig, exarg_T *eap)
}
// Read the diff output and add each entry to the diff list.
- diff_read(idx_orig, idx_new, &dio->dio_diff);
+ diff_read(idx_orig, idx_new, dio);
clear_diffin(&dio->dio_new);
clear_diffout(&dio->dio_diff);
@@ -880,10 +892,8 @@ int diff_internal(void)
///
static int diff_internal_failed(void)
{
- int idx;
-
// Only need to do something when there is another buffer.
- for (idx = 0; idx < DB_COUNT; idx++) {
+ for (int idx = 0; idx < DB_COUNT; idx++) {
if (curtab->tp_diffbuf[idx] != NULL
&& curtab->tp_diffbuf[idx]->b_diff_failed) {
return true;
@@ -914,7 +924,7 @@ void ex_diffupdate(exarg_T *eap)
// Use the first buffer as the original text.
int idx_orig;
- for (idx_orig = 0; idx_orig < DB_COUNT; ++idx_orig) {
+ for (idx_orig = 0; idx_orig < DB_COUNT; idx_orig++) {
if (curtab->tp_diffbuf[idx_orig] != NULL) {
break;
}
@@ -926,7 +936,7 @@ void ex_diffupdate(exarg_T *eap)
// Only need to do something when there is another buffer.
int idx_new;
- for (idx_new = idx_orig + 1; idx_new < DB_COUNT; ++idx_new) {
+ for (idx_new = idx_orig + 1; idx_new < DB_COUNT; idx_new++) {
if (curtab->tp_diffbuf[idx_new] != NULL) {
break;
}
@@ -1078,7 +1088,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.out_line = xdiff_out;
+ emit_cfg.hunk_func = xdiff_out;
if (xdl_diff(&diffio->dio_orig.din_mmfile,
&diffio->dio_new.din_mmfile,
&param, &emit_cfg, &emit_cb) < 0) {
@@ -1272,7 +1282,7 @@ void ex_diffpatch(exarg_T *eap)
ex_file(eap);
// Do filetype detection with the new name.
- if (au_has_group((char_u *)"filetypedetect")) {
+ if (augroup_exists("filetypedetect")) {
do_cmdline_cmd(":doau filetypedetect BufRead");
}
}
@@ -1508,7 +1518,7 @@ void ex_diffoff(exarg_T *eap)
diff_clear(curtab);
}
- // Remove "hor" from from 'scrollopt' if there are no diff windows left.
+ // Remove "hor" from 'scrollopt' if there are no diff windows left.
if (!diffwin && (vim_strchr(p_sbo, 'h') != NULL)) {
do_cmdline_cmd("set sbo-=hor");
}
@@ -1519,20 +1529,20 @@ void ex_diffoff(exarg_T *eap)
/// @param idx_orig idx of original file
/// @param idx_new idx of new file
/// @dout diff output
-static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
+static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
{
FILE *fd = NULL;
int line_idx = 0;
diff_T *dprev = NULL;
diff_T *dp = curtab->tp_first_diff;
diff_T *dn, *dpl;
+ diffout_T *dout = &dio->dio_diff;
char_u linebuf[LBUFLEN]; // only need to hold the diff line
char_u *line;
long off;
int i;
- linenr_T lnum_orig, lnum_new;
- long count_orig, count_new;
int notset = true; // block "*dp" not set yet
+ diffhunk_T *hunk = NULL; // init to avoid gcc warning
enum {
DIFF_ED,
DIFF_UNIFIED,
@@ -1549,70 +1559,79 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
}
}
+ if (!dio->dio_internal) {
+ hunk = xmalloc(sizeof(*hunk));
+ }
+
for (;;) {
- if (fd == NULL) {
+ if (dio->dio_internal) {
if (line_idx >= dout->dout_ga.ga_len) {
break; // did last line
}
- line = ((char_u **)dout->dout_ga.ga_data)[line_idx++];
+ hunk = ((diffhunk_T **)dout->dout_ga.ga_data)[line_idx++];
} else {
- if (vim_fgets(linebuf, LBUFLEN, fd)) {
- break; // end of file
- }
- line = linebuf;
- }
-
- if (diffstyle == DIFF_NONE) {
- // Determine diff style.
- // ed like diff looks like this:
- // {first}[,{last}]c{first}[,{last}]
- // {first}a{first}[,{last}]
- // {first}[,{last}]d{first}
- //
- // unified diff looks like this:
- // --- file1 2018-03-20 13:23:35.783153140 +0100
- // +++ file2 2018-03-20 13:23:41.183156066 +0100
- // @@ -1,3 +1,5 @@
- if (isdigit(*line)) {
- diffstyle = DIFF_ED;
- } else if ((STRNCMP(line, "@@ ", 3) == 0)) {
- diffstyle = DIFF_UNIFIED;
- } else if ((STRNCMP(line, "--- ", 4) == 0) // -V501
- && (vim_fgets(linebuf, LBUFLEN, fd) == 0) // -V501
- && (STRNCMP(line, "+++ ", 4) == 0)
- && (vim_fgets(linebuf, LBUFLEN, fd) == 0) // -V501
- && (STRNCMP(line, "@@ ", 3) == 0)) {
- diffstyle = DIFF_UNIFIED;
+ if (fd == NULL) {
+ if (line_idx >= dout->dout_ga.ga_len) {
+ break; // did last line
+ }
+ line = ((char_u **)dout->dout_ga.ga_data)[line_idx++];
} else {
- // Format not recognized yet, skip over this line. Cygwin diff
- // may put a warning at the start of the file.
- continue;
+ if (vim_fgets(linebuf, LBUFLEN, fd)) {
+ break; // end of file
+ }
+ line = linebuf;
}
- }
- if (diffstyle == DIFF_ED) {
- if (!isdigit(*line)) {
- continue; // not the start of a diff block
- }
- if (parse_diff_ed(line, &lnum_orig, &count_orig,
- &lnum_new, &count_new) == FAIL) {
- continue;
- }
- } else {
- assert(diffstyle == DIFF_UNIFIED);
- if (STRNCMP(line, "@@ ", 3) != 0) {
- continue; // not the start of a diff block
+ if (diffstyle == DIFF_NONE) {
+ // Determine diff style.
+ // ed like diff looks like this:
+ // {first}[,{last}]c{first}[,{last}]
+ // {first}a{first}[,{last}]
+ // {first}[,{last}]d{first}
+ //
+ // unified diff looks like this:
+ // --- file1 2018-03-20 13:23:35.783153140 +0100
+ // +++ file2 2018-03-20 13:23:41.183156066 +0100
+ // @@ -1,3 +1,5 @@
+ if (isdigit(*line)) {
+ diffstyle = DIFF_ED;
+ } else if ((STRNCMP(line, "@@ ", 3) == 0)) {
+ diffstyle = DIFF_UNIFIED;
+ } else if ((STRNCMP(line, "--- ", 4) == 0) // -V501
+ && (vim_fgets(linebuf, LBUFLEN, fd) == 0) // -V501
+ && (STRNCMP(line, "+++ ", 4) == 0)
+ && (vim_fgets(linebuf, LBUFLEN, fd) == 0) // -V501
+ && (STRNCMP(line, "@@ ", 3) == 0)) {
+ diffstyle = DIFF_UNIFIED;
+ } else {
+ // Format not recognized yet, skip over this line. Cygwin diff
+ // may put a warning at the start of the file.
+ continue;
+ }
}
- if (parse_diff_unified(line, &lnum_orig, &count_orig,
- &lnum_new, &count_new) == FAIL) {
- continue;
+
+ if (diffstyle == DIFF_ED) {
+ if (!isdigit(*line)) {
+ continue; // not the start of a diff block
+ }
+ if (parse_diff_ed(line, hunk) == FAIL) {
+ continue;
+ }
+ } else {
+ assert(diffstyle == DIFF_UNIFIED);
+ if (STRNCMP(line, "@@ ", 3) != 0) {
+ continue; // not the start of a diff block
+ }
+ if (parse_diff_unified(line, hunk) == FAIL) {
+ continue;
+ }
}
}
// Go over blocks before the change, for which orig and new are equal.
// Copy blocks from orig to new.
while (dp != NULL
- && lnum_orig > dp->df_lnum[idx_orig] + dp->df_count[idx_orig]) {
+ && hunk->lnum_orig > dp->df_lnum[idx_orig] + dp->df_count[idx_orig]) {
if (notset) {
diff_copy_entry(dprev, dp, idx_orig, idx_new);
}
@@ -1622,35 +1641,35 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
}
if ((dp != NULL)
- && (lnum_orig <= dp->df_lnum[idx_orig] + dp->df_count[idx_orig])
- && (lnum_orig + count_orig >= dp->df_lnum[idx_orig])) {
+ && (hunk->lnum_orig <= dp->df_lnum[idx_orig] + dp->df_count[idx_orig])
+ && (hunk->lnum_orig + hunk->count_orig >= dp->df_lnum[idx_orig])) {
// New block overlaps with existing block(s).
// First find last block that overlaps.
for (dpl = dp; dpl->df_next != NULL; dpl = dpl->df_next) {
- if (lnum_orig + count_orig < dpl->df_next->df_lnum[idx_orig]) {
+ if (hunk->lnum_orig + hunk->count_orig < dpl->df_next->df_lnum[idx_orig]) {
break;
}
}
// If the newly found block starts before the old one, set the
// start back a number of lines.
- off = dp->df_lnum[idx_orig] - lnum_orig;
+ off = dp->df_lnum[idx_orig] - hunk->lnum_orig;
if (off > 0) {
- for (i = idx_orig; i < idx_new; ++i) {
+ for (i = idx_orig; i < idx_new; i++) {
if (curtab->tp_diffbuf[i] != NULL) {
dp->df_lnum[i] -= off;
}
}
- dp->df_lnum[idx_new] = lnum_new;
- dp->df_count[idx_new] = count_new;
+ dp->df_lnum[idx_new] = hunk->lnum_new;
+ dp->df_count[idx_new] = hunk->count_new;
} else if (notset) {
// new block inside existing one, adjust new block
- dp->df_lnum[idx_new] = lnum_new + off;
- dp->df_count[idx_new] = count_new - off;
+ dp->df_lnum[idx_new] = hunk->lnum_new + off;
+ dp->df_count[idx_new] = hunk->count_new - off;
} else {
// second overlap of new block with existing block
- dp->df_count[idx_new] += count_new - count_orig
+ dp->df_count[idx_new] += hunk->count_new - hunk->count_orig
+ dpl->df_lnum[idx_orig] +
dpl->df_count[idx_orig]
- (dp->df_lnum[idx_orig] +
@@ -1659,7 +1678,7 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
// Adjust the size of the block to include all the lines to the
// end of the existing block or the new diff, whatever ends last.
- off = (lnum_orig + count_orig)
+ off = (hunk->lnum_orig + hunk->count_orig)
- (dpl->df_lnum[idx_orig] + dpl->df_count[idx_orig]);
if (off < 0) {
@@ -1671,7 +1690,7 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
off = 0;
}
- for (i = idx_orig; i < idx_new; ++i) {
+ for (i = idx_orig; i < idx_new; i++) {
if (curtab->tp_diffbuf[i] != NULL) {
dp->df_count[i] = dpl->df_lnum[i] + dpl->df_count[i]
- dp->df_lnum[i] + off;
@@ -1691,15 +1710,15 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
// Allocate a new diffblock.
dp = diff_alloc_new(curtab, dprev, dp);
- dp->df_lnum[idx_orig] = lnum_orig;
- dp->df_count[idx_orig] = count_orig;
- dp->df_lnum[idx_new] = lnum_new;
- dp->df_count[idx_new] = count_new;
+ dp->df_lnum[idx_orig] = hunk->lnum_orig;
+ dp->df_count[idx_orig] = hunk->count_orig;
+ dp->df_lnum[idx_new] = hunk->lnum_new;
+ dp->df_count[idx_new] = hunk->count_new;
// Set values for other buffers, these must be equal to the
// original buffer, otherwise there would have been a change
// already.
- for (i = idx_orig + 1; i < idx_new; ++i) {
+ for (i = idx_orig + 1; i < idx_new; i++) {
if (curtab->tp_diffbuf[i] != NULL) {
diff_copy_entry(dprev, dp, idx_orig, i);
}
@@ -1718,6 +1737,10 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
notset = true;
}
+ if (!dio->dio_internal) {
+ xfree(hunk);
+ }
+
if (fd != NULL) {
fclose(fd);
}
@@ -1749,9 +1772,8 @@ static void diff_copy_entry(diff_T *dprev, diff_T *dp, int idx_orig, int idx_new
void diff_clear(tabpage_T *tp)
FUNC_ATTR_NONNULL_ALL
{
- diff_T *p;
diff_T *next_p;
- for (p = tp->tp_first_diff; p != NULL; p = next_p) {
+ for (diff_T *p = tp->tp_first_diff; p != NULL; p = next_p) {
next_p = p->df_next;
xfree(p);
}
@@ -1773,12 +1795,8 @@ 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
diff_T *dp;
- int maxcount;
- int i;
buf_T *buf = wp->w_buffer;
- int cmp;
if (curtab->tp_diff_invalid) {
// update after a big change
@@ -1795,7 +1813,7 @@ int diff_check(win_T *wp, linenr_T lnum)
return 0;
}
- idx = diff_buf_idx(buf);
+ int idx = diff_buf_idx(buf); // index in tp_diffbuf[] for this buffer
if (idx == DB_COUNT) {
// no diffs for buffer "buf"
@@ -1824,9 +1842,9 @@ int diff_check(win_T *wp, linenr_T lnum)
// Changed or inserted line. If the other buffers have a count of
// zero, the lines were inserted. If the other buffers have the same
// count, check if the lines are identical.
- cmp = false;
+ int cmp = false;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (int i = 0; i < DB_COUNT; i++) {
if ((i != idx) && (curtab->tp_diffbuf[i] != NULL)) {
if (dp->df_count[i] == 0) {
zero = true;
@@ -1843,7 +1861,7 @@ int diff_check(win_T *wp, linenr_T lnum)
if (cmp) {
// Compare all lines. If they are equal the lines were inserted
// in some buffers, deleted in others, but not changed.
- for (i = 0; i < DB_COUNT; ++i) {
+ for (int i = 0; i < DB_COUNT; i++) {
if ((i != idx)
&& (curtab->tp_diffbuf[i] != NULL)
&& (dp->df_count[i] != 0)) {
@@ -1872,8 +1890,8 @@ int diff_check(win_T *wp, linenr_T lnum)
// Insert filler lines above the line just below the change. Will return
// 0 when this buf had the max count.
- maxcount = 0;
- for (i = 0; i < DB_COUNT; ++i) {
+ int maxcount = 0;
+ for (int i = 0; i < DB_COUNT; i++) {
if ((curtab->tp_diffbuf[i] != NULL) && (dp->df_count[i] > maxcount)) {
maxcount = dp->df_count[i];
}
@@ -2004,8 +2022,6 @@ void diff_set_topline(win_T *fromwin, win_T *towin)
buf_T *frombuf = fromwin->w_buffer;
linenr_T lnum = fromwin->w_topline;
diff_T *dp;
- int max_count;
- int i;
int fromidx = diff_buf_idx(frombuf);
if (fromidx == DB_COUNT) {
@@ -2045,9 +2061,9 @@ void diff_set_topline(win_T *fromwin, win_T *towin)
if (lnum >= dp->df_lnum[fromidx]) {
// Inside a change: compute filler lines. With three or more
// buffers we need to know the largest count.
- max_count = 0;
+ int max_count = 0;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (int i = 0; i < DB_COUNT; i++) {
if ((curtab->tp_diffbuf[i] != NULL) && (max_count < dp->df_count[i])) {
max_count = dp->df_count[i];
}
@@ -2193,7 +2209,7 @@ int diffopt_changed(void)
}
if (*p == ',') {
- ++p;
+ p++;
}
}
@@ -2296,7 +2312,7 @@ bool diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)
int off = lnum - dp->df_lnum[idx];
int i;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (i = 0; i < DB_COUNT; i++) {
if ((curtab->tp_diffbuf[i] != NULL) && (i != idx)) {
// Skip lines that are not in the other change (filler lines).
if (off >= dp->df_count[i]) {
@@ -2395,7 +2411,6 @@ bool diff_infold(win_T *wp, linenr_T lnum)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1)
{
bool other = false;
- diff_T *dp;
// Return if 'diff' isn't set.
if (!wp->w_p_diff) {
@@ -2404,7 +2419,7 @@ bool diff_infold(win_T *wp, linenr_T lnum)
int idx = -1;
int i;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (i = 0; i < DB_COUNT; i++) {
if (curtab->tp_diffbuf[i] == wp->w_buffer) {
idx = i;
} else if (curtab->tp_diffbuf[i] != NULL) {
@@ -2427,7 +2442,7 @@ bool diff_infold(win_T *wp, linenr_T lnum)
return true;
}
- for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) {
+ for (diff_T *dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) {
// If this change is below the line there can't be any further match.
if (dp->df_lnum[idx] - diff_context > lnum) {
break;
@@ -2454,7 +2469,7 @@ void nv_diffgetput(bool put, size_t count)
if (count == 0) {
ea.arg = (char_u *)"";
} else {
- vim_snprintf(buf, 30, "%zu", count);
+ vim_snprintf(buf, sizeof(buf), "%zu", count);
ea.arg = (char_u *)buf;
}
@@ -2479,7 +2494,6 @@ void ex_diffgetput(exarg_T *eap)
int count;
linenr_T off = 0;
diff_T *dp;
- diff_T *dprev;
diff_T *dfree;
int i;
int added;
@@ -2503,7 +2517,7 @@ void ex_diffgetput(exarg_T *eap)
if (*eap->arg == NUL) {
// No argument: Find the other buffer in the list of diff buffers.
- for (idx_other = 0; idx_other < DB_COUNT; ++idx_other) {
+ for (idx_other = 0; idx_other < DB_COUNT; idx_other++) {
if ((curtab->tp_diffbuf[idx_other] != curbuf)
&& (curtab->tp_diffbuf[idx_other] != NULL)) {
if ((eap->cmdidx != CMD_diffput)
@@ -2524,7 +2538,7 @@ void ex_diffgetput(exarg_T *eap)
}
// Check that there isn't a third buffer in the list
- for (i = idx_other + 1; i < DB_COUNT; ++i) {
+ for (i = idx_other + 1; i < DB_COUNT; i++) {
if ((curtab->tp_diffbuf[i] != curbuf)
&& (curtab->tp_diffbuf[i] != NULL)
&& ((eap->cmdidx != CMD_diffput)
@@ -2541,7 +2555,7 @@ void ex_diffgetput(exarg_T *eap)
p--;
}
- for (i = 0; ascii_isdigit(eap->arg[i]) && eap->arg + i < p; ++i) {
+ for (i = 0; ascii_isdigit(eap->arg[i]) && eap->arg + i < p; i++) {
}
if (eap->arg + i == p) {
@@ -2584,9 +2598,9 @@ void ex_diffgetput(exarg_T *eap)
&& (eap->line1 == curbuf->b_ml.ml_line_count)
&& (diff_check(curwin, eap->line1) == 0)
&& ((eap->line1 == 1) || (diff_check(curwin, eap->line1 - 1) == 0))) {
- ++eap->line2;
+ eap->line2++;
} else if (eap->line1 > 0) {
- --eap->line1;
+ eap->line1--;
}
}
@@ -2615,7 +2629,7 @@ void ex_diffgetput(exarg_T *eap)
}
}
- dprev = NULL;
+ diff_T *dprev = NULL;
for (dp = curtab->tp_first_diff; dp != NULL;) {
if (dp->df_lnum[idx_cur] > eap->line2 + off) {
@@ -2677,14 +2691,14 @@ void ex_diffgetput(exarg_T *eap)
buf_empty = buf_is_empty(curbuf);
added = 0;
- for (i = 0; i < count; ++i) {
+ for (i = 0; i < count; i++) {
// remember deleting the last line of the buffer
buf_empty = curbuf->b_ml.ml_line_count == 1;
ml_delete(lnum, false);
added--;
}
- for (i = 0; i < dp->df_count[idx_from] - start_skip - end_skip; ++i) {
+ for (i = 0; i < dp->df_count[idx_from] - start_skip - end_skip; i++) {
linenr_T nr = dp->df_lnum[idx_from] + start_skip + i;
if (nr > curtab->tp_diffbuf[idx_from]->b_ml.ml_line_count) {
break;
@@ -2706,7 +2720,7 @@ void ex_diffgetput(exarg_T *eap)
if ((start_skip == 0) && (end_skip == 0)) {
// Check if there are any other buffers and if the diff is
// equal in them.
- for (i = 0; i < DB_COUNT; ++i) {
+ for (i = 0; i < DB_COUNT; i++) {
if ((curtab->tp_diffbuf[i] != NULL)
&& (i != idx_from)
&& (i != idx_to)
@@ -2809,7 +2823,7 @@ theend:
static void diff_fold_update(diff_T *dp, int skip_idx)
{
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- for (int i = 0; i < DB_COUNT; ++i) {
+ for (int i = 0; i < DB_COUNT; i++) {
if ((curtab->tp_diffbuf[i] == wp->w_buffer) && (i != skip_idx)) {
foldUpdate(wp, dp->df_lnum[i], dp->df_lnum[i] + dp->df_count[i]);
}
@@ -2898,13 +2912,10 @@ int diff_move_to(int dir, long count)
/// "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;
- idx1 = diff_buf_idx(buf1);
- idx2 = diff_buf_idx(curbuf);
+ int idx1 = diff_buf_idx(buf1);
+ int idx2 = diff_buf_idx(curbuf);
if ((idx1 == DB_COUNT)
|| (idx2 == DB_COUNT)
@@ -2922,7 +2933,7 @@ static linenr_T diff_get_corresponding_line_int(buf_T *buf1, linenr_T lnum1)
return lnum1;
}
- for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) {
+ for (diff_T *dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) {
if (dp->df_lnum[idx1] > lnum1) {
return lnum1 - baseline;
}
@@ -2978,11 +2989,8 @@ linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1)
linenr_T diff_lnum_win(linenr_T lnum, win_T *wp)
{
diff_T *dp;
- int idx;
- int i;
- linenr_T n;
- idx = diff_buf_idx(curbuf);
+ int idx = diff_buf_idx(curbuf);
if (idx == DB_COUNT) {
// safety check
@@ -3008,14 +3016,14 @@ linenr_T diff_lnum_win(linenr_T lnum, win_T *wp)
}
// Find index for "wp".
- i = diff_buf_idx(wp->w_buffer);
+ int i = diff_buf_idx(wp->w_buffer);
if (i == DB_COUNT) {
// safety check
return (linenr_T)0;
}
- n = lnum + (dp->df_lnum[i] - dp->df_lnum[idx]);
+ linenr_T n = lnum + (dp->df_lnum[i] - dp->df_lnum[idx]);
if (n > dp->df_lnum[i] + dp->df_count[i]) {
n = dp->df_lnum[i] + dp->df_count[i];
}
@@ -3026,19 +3034,16 @@ 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, diffhunk_T *hunk)
{
- char_u *p;
- long f1, l1, f2, l2;
- int difftype;
+ long l1, l2;
// The line must be one of three formats:
// change: {first}[,{last}]c{first}[,{last}]
// append: {first}a{first}[,{last}]
// delete: {first}[,{last}]d{first}
- p = line;
- f1 = getdigits(&p, true, 0);
+ char_u *p = line;
+ long f1 = getdigits(&p, true, 0);
if (*p == ',') {
p++;
l1 = getdigits(&p, true, 0);
@@ -3048,8 +3053,8 @@ static int parse_diff_ed(char_u *line, linenr_T *lnum_orig, long *count_orig, li
if (*p != 'a' && *p != 'c' && *p != 'd') {
return FAIL; // invalid diff format
}
- difftype = *p++;
- f2 = getdigits(&p, true, 0);
+ int difftype = *p++;
+ long f2 = getdigits(&p, true, 0);
if (*p == ',') {
p++;
l2 = getdigits(&p, true, 0);
@@ -3061,18 +3066,18 @@ static int parse_diff_ed(char_u *line, linenr_T *lnum_orig, long *count_orig, li
}
if (difftype == 'a') {
- *lnum_orig = f1 + 1;
- *count_orig = 0;
+ hunk->lnum_orig = f1 + 1;
+ hunk->count_orig = 0;
} else {
- *lnum_orig = f1;
- *count_orig = l1 - f1 + 1;
+ hunk->lnum_orig = f1;
+ hunk->count_orig = l1 - f1 + 1;
}
if (difftype == 'd') {
- *lnum_new = f2 + 1;
- *count_new = 0;
+ hunk->lnum_new = f2 + 1;
+ hunk->count_new = 0;
} else {
- *lnum_new = f2;
- *count_new = l2 - f2 + 1;
+ hunk->lnum_new = f2;
+ hunk->count_new = l2 - f2 + 1;
}
return OK;
}
@@ -3081,17 +3086,16 @@ static int parse_diff_ed(char_u *line, linenr_T *lnum_orig, long *count_orig, li
/// 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, diffhunk_T *hunk)
{
- char_u *p;
- long oldline, oldcount, newline, newcount;
-
// Parse unified diff hunk header:
// @@ -oldline,oldcount +newline,newcount @@
- p = line;
+ char_u *p = line;
if (*p++ == '@' && *p++ == '@' && *p++ == ' ' && *p++ == '-') {
- oldline = getdigits(&p, true, 0);
+ long oldcount;
+ long newline;
+ long newcount;
+ long oldline = getdigits(&p, true, 0);
if (*p == ',') {
p++;
oldcount = getdigits(&p, true, 0);
@@ -3120,10 +3124,10 @@ static int parse_diff_unified(char_u *line, linenr_T *lnum_orig, long *count_ori
newline = 1;
}
- *lnum_orig = oldline;
- *count_orig = oldcount;
- *lnum_new = newline;
- *count_new = newcount;
+ hunk->lnum_orig = oldline;
+ hunk->count_orig = oldcount;
+ hunk->lnum_new = newline;
+ hunk->count_new = newcount;
return OK;
}
@@ -3135,25 +3139,16 @@ static int parse_diff_unified(char_u *line, linenr_T *lnum_orig, long *count_ori
/// Callback function for the xdl_diff() function.
/// Stores the diff output in a grow array.
///
-static int xdiff_out(void *priv, mmbuffer_t *mb, int nbuf)
+static int xdiff_out(long start_a, long count_a, long start_b, long count_b, void *priv)
{
diffout_T *dout = (diffout_T *)priv;
- char_u *p;
-
- // The header line always comes by itself, text lines in at least two
- // parts. We drop the text part.
- if (nbuf > 1) {
- return 0;
- }
-
- // sanity check
- if (STRNCMP(mb[0].ptr, "@@ ", 3) != 0) {
- return 0;
- }
+ diffhunk_T *p = xmalloc(sizeof(*p));
ga_grow(&dout->dout_ga, 1);
-
- p = vim_strnsave((char_u *)mb[0].ptr, mb[0].size);
- ((char_u **)dout->dout_ga.ga_data)[dout->dout_ga.ga_len++] = p;
+ p->lnum_orig = start_a + 1;
+ p->count_orig = count_a;
+ p->lnum_new = start_b + 1;
+ p->count_new = count_b;
+ ((diffhunk_T **)dout->dout_ga.ga_data)[dout->dout_ga.ga_len++] = p;
return 0;
}