patch 9.1.1009: diff feature can be improved

Problem:  diff feature can be improved
Solution: include the linematch diff alignment algorithm
          (Jonathon)

closes: #9661

Signed-off-by: Jonathon <jonathonwhite@protonmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/Filelist b/Filelist
index 0a1d993..aefed89 100644
--- a/Filelist
+++ b/Filelist
@@ -52,6 +52,7 @@
 		src/debugger.c \
 		src/dict.c \
 		src/diff.c \
+		src/linematch.c \
 		src/digraph.c \
 		src/drawline.c \
 		src/drawscreen.c \
@@ -286,6 +287,7 @@
 		src/proto/insexpand.pro \
 		src/proto/job.pro \
 		src/proto/json.pro \
+		src/proto/linematch.pro \
 		src/proto/list.pro \
 		src/proto/locale.pro \
 		src/proto/logfile.pro \
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 780db60..2f64ba3 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1,4 +1,4 @@
-*options.txt*	For Vim version 9.1.  Last change: 2025 Jan 10
+*options.txt*	For Vim version 9.1.  Last change: 2025 Jan 12
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -2880,11 +2880,20 @@
 	Option settings for diff mode.  It can consist of the following items.
 	All are optional.  Items must be separated by a comma.
 
-		filler		Show filler lines, to keep the text
-				synchronized with a window that has inserted
-				lines at the same position.  Mostly useful
-				when windows are side-by-side and 'scrollbind'
-				is set.
+		algorithm:{text} Use the specified diff algorithm with the
+				internal diff engine. Currently supported
+				algorithms are:
+				myers      the default algorithm
+				minimal    spend extra time to generate the
+					   smallest possible diff
+				patience   patience diff algorithm
+				histogram  histogram diff algorithm
+
+		closeoff	When a window is closed where 'diff' is set
+				and there is only one window remaining in the
+				same tab page with 'diff' set, execute
+				`:diffoff` in that window.  This undoes a
+				`:diffsplit` command.
 
 		context:{n}	Use a context of {n} lines between a change
 				and a fold that contains unchanged lines.
@@ -2895,6 +2904,23 @@
 				value (999999) to disable folding completely.
 				See |fold-diff|.
 
+		filler		Show filler lines, to keep the text
+				synchronized with a window that has inserted
+				lines at the same position.  Mostly useful
+				when windows are side-by-side and 'scrollbind'
+				is set.
+
+		foldcolumn:{n}	Set the 'foldcolumn' option to {n} when
+				starting diff mode.  Without this 2 is used.
+
+		followwrap	Follow the 'wrap' option and leave as it is.
+
+		horizontal	Start diff mode with horizontal splits (unless
+				explicitly specified otherwise).
+
+		hiddenoff	Do not use diff mode for a buffer when it
+				becomes hidden.
+
 		iblank		Ignore changes where lines are all blank.  Adds
 				the "-B" flag to the "diff" command if
 				'diffexpr' is empty.  Check the documentation
@@ -2908,6 +2934,17 @@
 				are considered the same.  Adds the "-i" flag
 				to the "diff" command if 'diffexpr' is empty.
 
+		indent-heuristic
+				Use the indent heuristic for the internal
+				diff library.
+
+		internal	Use the internal diff library.  This is
+				ignored when 'diffexpr' is set.  *E960*
+				When running out of memory when writing a
+				buffer this item will be ignored for diffs
+				involving that buffer.  Set the 'verbose'
+				option to see when this happens.
+
 		iwhite		Ignore changes in amount of white space.  Adds
 				the "-b" flag to the "diff" command if
 				'diffexpr' is empty.  Check the documentation
@@ -2927,46 +2964,19 @@
 				of the "diff" command for what this does
 				exactly.
 
-		horizontal	Start diff mode with horizontal splits (unless
-				explicitly specified otherwise).
+		linematch:{n}   Align and mark changes between the most
+				similar lines between the buffers. When the
+				total number of lines in the diff hunk exceeds
+				{n}, the lines will not be aligned because for
+				very large diff hunks there will be a
+				noticeable lag. A reasonable setting is
+				"linematch:60", as this will enable alignment
+				for a 2 buffer diff hunk of 30 lines each,
+				or a 3 buffer diff hunk of 20 lines each.
 
 		vertical	Start diff mode with vertical splits (unless
 				explicitly specified otherwise).
 
-		closeoff	When a window is closed where 'diff' is set
-				and there is only one window remaining in the
-				same tab page with 'diff' set, execute
-				`:diffoff` in that window.  This undoes a
-				`:diffsplit` command.
-
-		hiddenoff	Do not use diff mode for a buffer when it
-				becomes hidden.
-
-		foldcolumn:{n}	Set the 'foldcolumn' option to {n} when
-				starting diff mode.  Without this 2 is used.
-
-		followwrap	Follow the 'wrap' option and leave as it is.
-
-		internal	Use the internal diff library.  This is
-				ignored when 'diffexpr' is set.  *E960*
-				When running out of memory when writing a
-				buffer this item will be ignored for diffs
-				involving that buffer.  Set the 'verbose'
-				option to see when this happens.
-
-		indent-heuristic
-				Use the indent heuristic for the internal
-				diff library.
-
-		algorithm:{text} Use the specified diff algorithm with the
-				internal diff engine. Currently supported
-				algorithms are:
-				myers      the default algorithm
-				minimal    spend extra time to generate the
-					   smallest possible diff
-				patience   patience diff algorithm
-				histogram  histogram diff algorithm
-
 	Examples: >
 		:set diffopt=internal,filler,context:4
 		:set diffopt=
diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt
index bcb0b78..e212230 100644
--- a/runtime/doc/version9.txt
+++ b/runtime/doc/version9.txt
@@ -1,4 +1,4 @@
-*version9.txt*  For Vim version 9.1.  Last change: 2025 Jan 02
+*version9.txt*  For Vim version 9.1.  Last change: 2025 Jan 12
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -41625,6 +41625,9 @@
   the "matches" key
 - |v:stacktrace| The stack trace of the exception most recently caught and
   not finished
+- include the linematch algorithm for the 'diffopt' setting.  This aligns
+  changes between buffers on similar lines improving the diff highlighting in
+  Vim
 
 							*added-9.2*
 Added ~
diff --git a/src/Make_ami.mak b/src/Make_ami.mak
index 42270f3..c779914 100644
--- a/src/Make_ami.mak
+++ b/src/Make_ami.mak
@@ -123,6 +123,7 @@
 	indent.c \
 	insexpand.c \
 	json.c \
+	linematch.c\
 	list.c \
 	locale.c \
 	logfile.c \
diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak
index cd84b85..3f2a6da 100644
--- a/src/Make_cyg_ming.mak
+++ b/src/Make_cyg_ming.mak
@@ -817,6 +817,7 @@
 	$(OUTDIR)/indent.o \
 	$(OUTDIR)/insexpand.o \
 	$(OUTDIR)/json.o \
+	$(OUTDIR)/linematch.o \
 	$(OUTDIR)/list.o \
 	$(OUTDIR)/locale.o \
 	$(OUTDIR)/logfile.o \
diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak
index 49d8a33..c24f0af 100644
--- a/src/Make_mvc.mak
+++ b/src/Make_mvc.mak
@@ -738,6 +738,7 @@
 	$(OUTDIR)\indent.obj \
 	$(OUTDIR)\insexpand.obj \
 	$(OUTDIR)\json.obj \
+	$(OUTDIR)\linematch.obj \
 	$(OUTDIR)\list.obj \
 	$(OUTDIR)\locale.obj \
 	$(OUTDIR)\logfile.obj \
@@ -1675,6 +1676,8 @@
 
 $(OUTDIR)/json.obj:	$(OUTDIR) json.c  $(INCL)
 
+$(OUTDIR)/linematch.obj:	$(OUTDIR) linematch.c  $(INCL)
+
 $(OUTDIR)/list.obj:	$(OUTDIR) list.c  $(INCL)
 
 $(OUTDIR)/locale.obj:	$(OUTDIR) locale.c  $(INCL)
@@ -1954,6 +1957,7 @@
 	proto/indent.pro \
 	proto/insexpand.pro \
 	proto/json.pro \
+	proto/linematch.pro \
 	proto/list.pro \
 	proto/locale.pro \
 	proto/logfile.pro \
diff --git a/src/Make_vms.mms b/src/Make_vms.mms
index 559c2f8..2063023 100644
--- a/src/Make_vms.mms
+++ b/src/Make_vms.mms
@@ -381,6 +381,7 @@
 	insexpand.c \
 	job.c \
 	json.c \
+	linematch.c \
 	list.c \
 	locale.c \
 	logfile.c \
@@ -514,6 +515,7 @@
 	insexpand.obj \
 	job.obj \
 	json.obj \
+	linematch.obj \
 	list.obj \
 	locale.obj \
 	logfile.obj \
@@ -986,6 +988,9 @@
 json.obj : json.c vim.h [.auto]config.h feature.h os_unix.h   \
  ascii.h keymap.h termdefs.h macros.h structs.h regexp.h gui.h beval.h \
  [.proto]gui_beval.pro option.h ex_cmds.h proto.h errors.h globals.h
+linematch.obj : linematch.c vim.h [.auto]config.h feature.h os_unix.h   \
+ ascii.h keymap.h termdefs.h macros.h structs.h regexp.h gui.h beval.h \
+ [.proto]gui_beval.pro option.h ex_cmds.h proto.h errors.h globals.h
 list.obj : list.c vim.h [.auto]config.h feature.h os_unix.h \
  ascii.h keymap.h termdefs.h macros.h option.h structs.h regexp.h gui.h \
  beval.h [.proto]gui_beval.pro alloc.h ex_cmds.h spell.h proto.h \
diff --git a/src/Makefile b/src/Makefile
index f5d01cf..7f26c90 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1531,6 +1531,7 @@
 	indent.c \
 	insexpand.c \
 	json.c \
+	linematch.c \
 	list.c \
 	locale.c \
 	logfile.c \
@@ -1693,6 +1694,7 @@
 	objects/if_xcmdsrv.o \
 	objects/indent.o \
 	objects/insexpand.o \
+	objects/linematch.o \
 	objects/list.o \
 	objects/locale.o \
 	objects/logfile.o \
@@ -1842,6 +1844,7 @@
 	debugger.pro \
 	dict.pro \
 	diff.pro \
+	linematch.pro \
 	digraph.pro \
 	drawline.pro \
 	drawscreen.pro \
@@ -3343,6 +3346,9 @@
 objects/kword_test.o: kword_test.c
 	$(CCC) -o $@ kword_test.c
 
+objects/linematch.o: linematch.c
+	$(CCC) -o $@ linematch.c
+
 objects/list.o: list.c
 	$(CCC) -o $@ list.c
 
@@ -3944,6 +3950,11 @@
  proto/gui_beval.pro structs.h regexp.h gui.h libvterm/include/vterm.h \
  libvterm/include/vterm_keycodes.h alloc.h ex_cmds.h spell.h proto.h \
  globals.h errors.h
+objects/linematch.o: linematch.c vim.h protodef.h auto/config.h feature.h \
+ os_unix.h auto/osdef.h ascii.h keymap.h termdefs.h macros.h option.h \
+ beval.h proto/gui_beval.pro structs.h regexp.h gui.h \
+ libvterm/include/vterm.h libvterm/include/vterm_keycodes.h xdiff/xdiff.h \
+ xdiff/../vim.h alloc.h ex_cmds.h spell.h proto.h globals.h errors.h
 objects/list.o: list.c vim.h protodef.h auto/config.h feature.h os_unix.h \
  auto/osdef.h ascii.h keymap.h termdefs.h macros.h option.h beval.h \
  proto/gui_beval.pro structs.h regexp.h gui.h libvterm/include/vterm.h \
diff --git a/src/diff.c b/src/diff.c
index ebe409e..971ef65 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -37,6 +37,7 @@
 #define DIFF_INTERNAL	0x200	// use internal xdiff algorithm
 #define DIFF_CLOSE_OFF	0x400	// diffoff when closing window
 #define DIFF_FOLLOWWRAP	0x800	// follow the wrap option
+#define DIFF_LINEMATCH  0x1000  // match most similar lines within diff
 #define ALL_WHITE_DIFF (DIFF_IWHITE | DIFF_IWHITEALL | DIFF_IWHITEEOL)
 static int	diff_flags = DIFF_INTERNAL | DIFF_FILLER | DIFF_CLOSE_OFF;
 
@@ -398,7 +399,8 @@
 	{
 	    // 6. change below line2: only adjust for amount_after; also when
 	    // "deleted" became zero when deleted all lines between two diffs
-	    if (dp->df_lnum[idx] - (deleted + inserted != 0) > line2)
+	    if (dp->df_lnum[idx] - (deleted + inserted != 0) > line2 -
+						(dp->is_linematched ? 1 : 0))
 	    {
 		if (amount_after == 0)
 		    break;	// nothing left to change
@@ -501,8 +503,9 @@
 	}
 
 	// check if this block touches the previous one, may merge them.
-	if (dprev != NULL && dprev->df_lnum[idx] + dprev->df_count[idx]
-							  == dp->df_lnum[idx])
+	if (dprev != NULL && !dp->is_linematched
+				&& dprev->df_lnum[idx] + dprev->df_count[idx]
+							== dp->df_lnum[idx])
 	{
 	    for (i = 0; i < DB_COUNT; ++i)
 		if (tp->tp_diffbuf[i] != NULL)
@@ -570,6 +573,7 @@
     if (dnew == NULL)
 	return NULL;
 
+    dnew->is_linematched = FALSE;
     dnew->df_next = dp;
     if (dprev == NULL)
 	tp->tp_first_diff = dnew;
@@ -753,13 +757,16 @@
  * Return FAIL for failure.
  */
     static int
-diff_write_buffer(buf_T *buf, diffin_T *din)
+diff_write_buffer(buf_T *buf, diffin_T *din, linenr_T start, linenr_T end)
 {
     linenr_T	lnum;
     char_u	*s;
     long	len = 0;
     char_u	*ptr;
 
+    if (end < 0)
+      end = buf->b_ml.ml_line_count;
+
     if (buf->b_ml.ml_flags & ML_EMPTY)
     {
 	din->din_mmfile.ptr = NULL;
@@ -768,7 +775,7 @@
     }
 
     // xdiff requires one big block of memory with all the text.
-    for (lnum = 1; lnum <= buf->b_ml.ml_line_count; ++lnum)
+    for (lnum = start; lnum <= end; ++lnum)
 	len += ml_get_buf_len(buf, lnum) + 1;
     ptr = alloc(len);
     if (ptr == NULL)
@@ -790,7 +797,7 @@
     din->din_mmfile.size = len;
 
     len = 0;
-    for (lnum = 1; lnum <= buf->b_ml.ml_line_count; ++lnum)
+    for (lnum = start; lnum <= end; ++lnum)
     {
 	for (s = ml_get_buf(buf, lnum, FALSE); *s != NUL; )
 	{
@@ -841,7 +848,7 @@
     int		save_cmod_flags;
 
     if (din->din_fname == NULL)
-	return diff_write_buffer(buf, din);
+	return diff_write_buffer(buf, din, 1, -1);
 
     // Always use 'fileformat' set to "unix".
     save_ff = buf->b_p_ff;
@@ -1923,6 +1930,360 @@
 }
 
 /*
+ *  return true if the options are set to use diff linematch
+ */
+    static int
+diff_linematch(diff_T *dp)
+{
+    if (!(diff_flags & DIFF_LINEMATCH))
+	return 0;
+
+    // are there more than three diff buffers?
+    int tsize = 0;
+    for (int i = 0; i < DB_COUNT; i++)
+    {
+	if (curtab->tp_diffbuf[i] != NULL)
+	{
+	    // for the rare case (bug?) that the count of a diff block is
+	    // negative, do not run the algorithm because this will try to
+	    // allocate a negative amount of space and crash
+	    if (dp->df_count[i] < 0)
+		return FALSE;
+	    tsize += dp->df_count[i];
+	}
+    }
+
+    // avoid allocating a huge array because it will lag
+    return tsize <= linematch_lines;
+}
+
+    static int
+get_max_diff_length(const diff_T *dp)
+{
+    int maxlength = 0;
+
+    for (int k = 0; k < DB_COUNT; k++)
+    {
+	if (curtab->tp_diffbuf[k] != NULL)
+	{
+	    if (dp->df_count[k] > maxlength)
+		maxlength = dp->df_count[k];
+	}
+    }
+    return maxlength;
+}
+
+    static void
+find_top_diff_block(
+    diff_T	**thistopdiff,
+    diff_T	**nextblockblock,
+    int		fromidx,
+    int		topline)
+{
+    diff_T	*topdiff = NULL;
+    diff_T	*localtopdiff = NULL;
+    int		topdiffchange = 0;
+
+    for (topdiff = curtab->tp_first_diff; topdiff != NULL;
+						topdiff = topdiff->df_next)
+    {
+	// set the top of the current overlapping diff block set as we
+	// iterate through all of the sets of overlapping diff blocks
+	if (!localtopdiff || topdiffchange)
+	{
+	    localtopdiff = topdiff;
+	    topdiffchange = 0;
+	}
+
+	// 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
+	    // top block of the set of blocks to refer to later
+	    if ((*thistopdiff) == NULL)
+		(*thistopdiff) = localtopdiff;
+	}
+
+	// check if the next set of overlapping diff blocks is next
+	if (!(topdiff->df_next && (topdiff->df_next->df_lnum[fromidx] ==
+			(topdiff->df_lnum[fromidx] +
+						topdiff->df_count[fromidx]))))
+	{
+	    // mark that the next diff block is belongs to a different set of
+	    // overlapping diff blocks
+	    topdiffchange = 1;
+
+	    // if we already have found that the line number is inside a diff
+	    // block, set the marker of the next block and finish the iteration
+	    if (*thistopdiff)
+	    {
+		(*nextblockblock) = topdiff->df_next;
+		break;
+	    }
+	}
+    }
+}
+
+    static void
+count_filler_lines_and_topline(
+    int			*curlinenum_to,
+    int			*linesfiller,
+    const diff_T	*thistopdiff,
+    const int		toidx,
+    int			virtual_lines_passed)
+{
+    const diff_T	*curdif = thistopdiff;
+    int			ch_virtual_lines = 0;
+    int			isfiller = FALSE;
+
+    while (virtual_lines_passed > 0)
+    {
+	if (ch_virtual_lines)
+	{
+	    virtual_lines_passed--;
+	    ch_virtual_lines--;
+	    if (!isfiller)
+		(*curlinenum_to)++;
+	    else
+		(*linesfiller)++;
+	}
+	else
+	{
+	    (*linesfiller) = 0;
+	    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] &&
+		       curdif->df_next->df_count[toidx] == 0)
+		{
+		    curdif = curdif->df_next;
+		    ch_virtual_lines += get_max_diff_length(curdif);
+		}
+	    }
+	    if (curdif)
+		curdif = curdif->df_next;
+	}
+    }
+}
+
+    static void
+calculate_topfill_and_topline(
+    const int	fromidx,
+    const int	toidx,
+    const int	from_topline,
+    const int	from_topfill,
+    int		*topfill,
+    linenr_T	*topline)
+{
+    // 1. find the position from the top of the diff block, and the start
+    // of the next diff block
+    diff_T	*thistopdiff = NULL;
+    diff_T	*nextblockblock = NULL;
+    int		virtual_lines_passed = 0;
+
+    find_top_diff_block(&thistopdiff, &nextblockblock, fromidx, from_topline);
+
+    // count the virtual lines that have been passed
+    diff_T *curdif = thistopdiff;
+    while (curdif && (curdif->df_lnum[fromidx] + curdif->df_count[fromidx])
+							<= from_topline)
+    {
+	virtual_lines_passed += get_max_diff_length(curdif);
+
+	curdif = curdif->df_next;
+    }
+
+    if (curdif != nextblockblock)
+	virtual_lines_passed += from_topline - curdif->df_lnum[fromidx];
+    virtual_lines_passed -= from_topfill;
+
+    // count the same amount of virtual lines in the toidx buffer
+    int curlinenum_to = thistopdiff->df_lnum[toidx];
+    int linesfiller = 0;
+
+    count_filler_lines_and_topline(&curlinenum_to, &linesfiller, thistopdiff,
+				   toidx, virtual_lines_passed);
+
+    // count the number of filler lines that would normally be above this line
+    int maxfiller = 0;
+    for (diff_T *dpfillertest = thistopdiff; dpfillertest != NULL;
+					dpfillertest = dpfillertest->df_next)
+    {
+	if (dpfillertest->df_lnum[toidx] == curlinenum_to)
+	{
+	    while (dpfillertest && dpfillertest->df_lnum[toidx] ==
+							curlinenum_to)
+	    {
+		maxfiller += dpfillertest->df_count[toidx] ? 0 :
+					get_max_diff_length(dpfillertest);
+		dpfillertest = dpfillertest->df_next;
+	    }
+	    break;
+	}
+    }
+    (*topfill) = maxfiller - linesfiller;
+    (*topline) = curlinenum_to;
+}
+
+    static int
+linematched_filler_lines(diff_T *dp, int idx, linenr_T lnum, int *linestatus)
+{
+    int filler_lines_d1 = 0;
+
+    while (dp && dp->df_next &&
+	   lnum == (dp->df_lnum[idx] + dp->df_count[idx]) &&
+	   dp->df_next->df_lnum[idx] == lnum)
+    {
+	if (dp->df_count[idx] == 0)
+	    filler_lines_d1 += get_max_diff_length(dp);
+	dp = dp->df_next;
+    }
+
+    if (dp->df_count[idx] == 0)
+	filler_lines_d1 += get_max_diff_length(dp);
+
+    if (lnum < dp->df_lnum[idx] + dp->df_count[idx])
+    {
+	int j = 0;
+
+	for (int i = 0; i < DB_COUNT; i++)
+	{
+	    if (curtab->tp_diffbuf[i] != NULL)
+	    {
+		if (dp->df_count[i])
+		    j++;
+	    }
+	    // is this an added line or a changed line?
+	    if (linestatus)
+		(*linestatus) = (j == 1) ? -2 : -1;
+	}
+    }
+
+    return filler_lines_d1;
+}
+
+// Apply results from the linematch algorithm and apply to 'dp' by splitting it
+// into multiple adjacent diff blocks.
+    static void
+apply_linematch_results(
+    diff_T	*dp,
+    size_t	decisions_length,
+    const int	*decisions)
+{
+    // get the start line number here in each diff buffer, and then increment
+    int		line_numbers[DB_COUNT];
+    int		outputmap[DB_COUNT];
+    size_t	ndiffs = 0;
+
+    for (int i = 0; i < DB_COUNT; i++)
+    {
+	if (curtab->tp_diffbuf[i] != NULL)
+	{
+	    line_numbers[i] = dp->df_lnum[i];
+	    dp->df_count[i] = 0;
+
+	    // Keep track of the index of the diff buffer we are using here.
+	    // We will use this to write the output of the algorithm to
+	    // diff_T structs at the correct indexes
+	    outputmap[ndiffs] = i;
+	    ndiffs++;
+	}
+    }
+
+    // write the diffs starting with the current diff block
+    diff_T *dp_s = dp;
+    for (size_t i = 0; i < decisions_length; i++)
+    {
+	// Don't allocate on first iter since we can reuse the initial
+	// diffblock
+	if (i != 0 && (decisions[i - 1] != decisions[i]))
+	{
+	    // create new sub diff blocks to segment the original diff block
+	    // which we further divided by running the linematch algorithm
+	    dp_s = diff_alloc_new(curtab, dp_s, dp_s->df_next);
+	    dp_s->is_linematched = TRUE;
+	    for (int j = 0; j < DB_COUNT; j++)
+	    {
+		if (curtab->tp_diffbuf[j] != NULL)
+		{
+		    dp_s->df_lnum[j] = line_numbers[j];
+		    dp_s->df_count[j] = 0;
+		}
+	    }
+	}
+	for (size_t j = 0; j < ndiffs; j++)
+	{
+	    if (decisions[i] & (1 << j))
+	    {
+		// will need to use the map here
+		dp_s->df_count[outputmap[j]]++;
+		line_numbers[outputmap[j]]++;
+	    }
+	}
+    }
+    dp->is_linematched = TRUE;
+}
+
+    static void
+run_linematch_algorithm(diff_T *dp)
+{
+    // define buffers for diff algorithm
+    diffin_T		diffbufs_mm[DB_COUNT];
+    const mmfile_t	*diffbufs[DB_COUNT];
+    int			diff_length[DB_COUNT];
+    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]
+	    if (dp->df_count[i] > 0)
+	    {
+		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].din_mmfile.size = 0;
+		diffbufs_mm[ndiffs].din_mmfile.ptr = NULL;
+	    }
+
+	    diffbufs[ndiffs] = &diffbufs_mm[ndiffs].din_mmfile;
+
+	    // keep track of the length of this diff block to pass it to the
+	    // linematch algorithm
+	    diff_length[ndiffs] = dp->df_count[i];
+
+	    // increment the amount of diff buffers we are passing to the
+	    // algorithm
+	    ndiffs++;
+	}
+    }
+
+    // we will get the output of the linematch algorithm in the format of an
+    // array of integers (*decisions) and the length of that array
+    // (decisions_length)
+    int *decisions = NULL;
+    const int iwhite = (diff_flags & (DIFF_IWHITEALL | DIFF_IWHITE)) > 0 ? 1 : 0;
+    size_t decisions_length =
+	linematch_nbuffers(diffbufs, diff_length, ndiffs, &decisions, iwhite);
+
+    for (size_t i = 0; i < ndiffs; i++)
+	free(diffbufs_mm[i].din_mmfile.ptr); // TODO should this be vim_free ?
+
+    apply_linematch_results(dp, decisions_length, decisions);
+
+    free(decisions);
+}
+
+/*
  * Check diff status for line "lnum" in buffer "buf":
  * Returns 0 for nothing special
  * Returns -1 for a line that should be highlighted as changed.
@@ -1930,9 +2291,15 @@
  * 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
  */
     int
-diff_check(win_T *wp, linenr_T lnum)
+diff_check_with_linestatus(win_T *wp, linenr_T lnum, int *linestatus)
 {
     int		idx;		// index in tp_diffbuf[] for this buffer
     diff_T	*dp;
@@ -1968,6 +2335,15 @@
     if (dp == NULL || lnum < dp->df_lnum[idx])
 	return 0;
 
+    // Don't run linematch when lnum is offscreen.  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))
+      run_linematch_algorithm(dp);
+
+    if (dp->is_linematched)
+      return linematched_filler_lines(dp, idx, lnum, linestatus);
+
     if (lnum < dp->df_lnum[idx] + dp->df_count[idx])
     {
 	int	zero = FALSE;
@@ -2014,13 +2390,16 @@
 
     // 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)
-	if (curtab->tp_diffbuf[i] != NULL && dp->df_count[i] > maxcount)
-	    maxcount = dp->df_count[i];
+    maxcount = get_max_diff_length(dp);
     return maxcount - dp->df_count[idx];
 }
 
+    int
+diff_check(win_T *wp, linenr_T lnum)
+{
+    return diff_check_with_linestatus(wp, lnum, NULL);
+}
+
 /*
  * Compare two entries in diff "*dp" and return TRUE if they are equal.
  */
@@ -2194,53 +2573,64 @@
 	towin->w_topline = lnum + (dp->df_lnum[toidx] - dp->df_lnum[fromidx]);
 	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;
-	    for (i = 0; i < DB_COUNT; ++i)
-		if (curtab->tp_diffbuf[i] != NULL
-					       && max_count < dp->df_count[i])
-		    max_count = dp->df_count[i];
+	    if (dp->is_linematched)
+	    {
+		calculate_topfill_and_topline(fromidx, toidx,
+						fromwin->w_topline,
+						fromwin->w_topfill,
+						&towin->w_topfill,
+						&towin->w_topline);
+	    }
+	    else
+	    {
+		// Inside a change: compute filler lines. With three or more
+		// buffers we need to know the largest count.
+		max_count = 0;
+		for (i = 0; i < DB_COUNT; ++i)
+		    if (curtab->tp_diffbuf[i] != NULL
+						   && max_count < dp->df_count[i])
+			max_count = dp->df_count[i];
 
-	    if (dp->df_count[toidx] == dp->df_count[fromidx])
-	    {
-		// same number of lines: use same filler count
-		towin->w_topfill = fromwin->w_topfill;
-	    }
-	    else if (dp->df_count[toidx] > dp->df_count[fromidx])
-	    {
-		if (lnum == dp->df_lnum[fromidx] + dp->df_count[fromidx])
+		if (dp->df_count[toidx] == dp->df_count[fromidx])
 		{
-		    // more lines in towin and fromwin doesn't show diff
-		    // lines, only filler lines
-		    if (max_count - fromwin->w_topfill >= dp->df_count[toidx])
-		    {
-			// towin also only shows filler lines
-			towin->w_topline = dp->df_lnum[toidx]
-						       + dp->df_count[toidx];
-			towin->w_topfill = fromwin->w_topfill;
-		    }
-		    else
-			// towin still has some diff lines to show
-			towin->w_topline = dp->df_lnum[toidx]
-					     + max_count - fromwin->w_topfill;
+		    // same number of lines: use same filler count
+		    towin->w_topfill = fromwin->w_topfill;
 		}
-	    }
-	    else if (towin->w_topline >= dp->df_lnum[toidx]
-							+ dp->df_count[toidx])
-	    {
-		// less lines in towin and no diff lines to show: compute
-		// filler lines
-		towin->w_topline = dp->df_lnum[toidx] + dp->df_count[toidx];
-		if (diff_flags & DIFF_FILLER)
+		else if (dp->df_count[toidx] > dp->df_count[fromidx])
 		{
 		    if (lnum == dp->df_lnum[fromidx] + dp->df_count[fromidx])
-			// fromwin is also out of diff lines
-			towin->w_topfill = fromwin->w_topfill;
-		    else
-			// fromwin has some diff lines
-			towin->w_topfill = dp->df_lnum[fromidx]
-							   + max_count - lnum;
+		    {
+			// more lines in towin and fromwin doesn't show diff
+			// lines, only filler lines
+			if (max_count - fromwin->w_topfill >= dp->df_count[toidx])
+			{
+			    // towin also only shows filler lines
+			    towin->w_topline = dp->df_lnum[toidx]
+							   + dp->df_count[toidx];
+			    towin->w_topfill = fromwin->w_topfill;
+			}
+			else
+			    // towin still has some diff lines to show
+			    towin->w_topline = dp->df_lnum[toidx]
+						 + max_count - fromwin->w_topfill;
+		    }
+		}
+		else if (towin->w_topline >= dp->df_lnum[toidx]
+							    + dp->df_count[toidx])
+		{
+		    // less lines in towin and no diff lines to show: compute
+		    // filler lines
+		    towin->w_topline = dp->df_lnum[toidx] + dp->df_count[toidx];
+		    if (diff_flags & DIFF_FILLER)
+		    {
+			if (lnum == dp->df_lnum[fromidx] + dp->df_count[fromidx])
+			    // fromwin is also out of diff lines
+			    towin->w_topfill = fromwin->w_topfill;
+			else
+			    // fromwin has some diff lines
+			    towin->w_topfill = dp->df_lnum[fromidx] +
+							max_count - lnum;
+		    }
 		}
 	    }
 	}
@@ -2278,6 +2668,7 @@
 {
     char_u	*p;
     int		diff_context_new = 6;
+    int		linematch_lines_new = 0;
     int		diff_flags_new = 0;
     int		diff_foldcolumn_new = 2;
     long	diff_algorithm_new = 0;
@@ -2390,6 +2781,12 @@
 	    else
 		return FAIL;
 	}
+	else if (STRNCMP(p, "linematch:", 10) == 0 && VIM_ISDIGIT(p[11]))
+	{
+	    p += 10;
+	    linematch_lines_new = getdigits(&p);
+	    diff_flags_new |= DIFF_LINEMATCH;
+	}
 
 	if (*p != ',' && *p != NUL)
 	    return FAIL;
@@ -2411,6 +2808,7 @@
 
     diff_flags = diff_flags_new;
     diff_context = diff_context_new == 0 ? 1 : diff_context_new;
+    linematch_lines = linematch_lines_new;
     diff_foldcolumn = diff_foldcolumn_new;
     diff_algorithm = diff_algorithm_new;
 
@@ -2489,6 +2887,13 @@
     FOR_ALL_DIFFBLOCKS_IN_TAB(curtab, dp)
 	if (lnum <= dp->df_lnum[idx] + dp->df_count[idx])
 	    break;
+    if (dp->is_linematched)
+    {
+	while (dp && dp->df_next
+			&& lnum == dp->df_count[idx] + dp->df_lnum[idx]
+			&& dp->df_next->df_lnum[idx] == lnum)
+	    dp = dp->df_next;
+    }
     if (dp == NULL || diff_check_sanity(curtab, dp) == FAIL)
     {
 	vim_free(line_org);
@@ -2829,6 +3234,19 @@
     dprev = NULL;
     for (dp = curtab->tp_first_diff; dp != NULL; )
     {
+	if (!eap->addr_count)
+	{
+	    // handle the case with adjacent diff blocks
+	    while (dp->is_linematched
+		    && dp->df_next
+		    && dp->df_next->df_lnum[idx_cur] == dp->df_lnum[idx_cur] +
+							dp->df_count[idx_cur]
+		    && dp->df_next->df_lnum[idx_cur] == eap->line1 + off + 1)
+	    {
+		dprev = dp;
+		dp = dp->df_next;
+	    }
+	}
 	if (dp->df_lnum[idx_cur] > eap->line2 + off)
 	    break;	// past the range that was specified
 
@@ -3445,10 +3863,11 @@
 	    || fnum != curbuf->b_fnum)
     {
 	// New line, buffer, change: need to get the values.
-	filler_lines = diff_check(curwin, lnum);
-	if (filler_lines < 0)
+	int linestatus = 0;
+	filler_lines = diff_check_with_linestatus(curwin, lnum, &linestatus);
+	if (filler_lines < 0 || linestatus < 0)
 	{
-	    if (filler_lines == -1)
+	    if (filler_lines == -1 || linestatus == -1)
 	    {
 		change_start = MAXCOL;
 		change_end = -1;
diff --git a/src/drawline.c b/src/drawline.c
index f383857..a6b6317 100644
--- a/src/drawline.c
+++ b/src/drawline.c
@@ -1467,10 +1467,13 @@
     }
 
 #ifdef FEAT_DIFF
-    wlv.filler_lines = diff_check(wp, lnum);
-    if (wlv.filler_lines < 0)
+
+    int linestatus = 0;
+    wlv.filler_lines = diff_check_with_linestatus(wp, lnum, &linestatus);
+
+    if (wlv.filler_lines < 0 || linestatus < 0)
     {
-	if (wlv.filler_lines == -1)
+	if (wlv.filler_lines == -1 || linestatus == -1)
 	{
 	    if (diff_find_change(wp, lnum, &change_start, &change_end))
 		wlv.diff_hlf = HLF_ADD;	// added line
@@ -1480,12 +1483,17 @@
 		wlv.diff_hlf = HLF_CHD;	// changed line
 	}
 	else
-	    wlv.diff_hlf = HLF_ADD;		// added line
-	wlv.filler_lines = 0;
+	    wlv.diff_hlf = HLF_ADD;
+
+	if (linestatus == 0)
+	    wlv.filler_lines = 0;
+
 	area_highlighting = TRUE;
     }
+
     if (lnum == wp->w_topline)
 	wlv.filler_lines = wp->w_topfill;
+
     wlv.filler_todo = wlv.filler_lines;
 #endif
 
diff --git a/src/globals.h b/src/globals.h
index 77ddea8..e3b1e27f 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -869,6 +869,7 @@
 #ifdef FEAT_DIFF
 // Value set from 'diffopt'.
 EXTERN int	diff_context INIT(= 6);		// context for folds
+EXTERN int      linematch_lines INIT(= 0);      // number of lines for diff line match
 EXTERN int	diff_foldcolumn INIT(= 2);	// 'foldcolumn' for diff mode
 EXTERN int	diff_need_scrollbind INIT(= FALSE);
 #endif
diff --git a/src/linematch.c b/src/linematch.c
new file mode 100644
index 0000000..c1463fd
--- /dev/null
+++ b/src/linematch.c
@@ -0,0 +1,486 @@
+/* vi:set ts=8 sts=4 sw=4 noet:
+ *
+ * VIM - Vi IMproved	by Bram Moolenaar
+ *
+ * Do ":help uganda"  in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#include "vim.h"
+
+#define LN_MAX_BUFS 8
+#define LN_DECISION_MAX 255  // pow(2, LN_MAX_BUFS(8)) - 1 = 255
+
+// struct for running the diff linematch algorithm
+typedef struct diffcmppath_S diffcmppath_T;
+struct diffcmppath_S
+{
+    // to keep track of the total score of this path
+    int			df_lev_score;
+    size_t		df_path_n;	// current index of this path
+    int			df_choice_mem[LN_DECISION_MAX + 1];
+    int			df_choice[LN_DECISION_MAX];
+    // to keep track of this path traveled
+    diffcmppath_T	*df_decision[LN_DECISION_MAX];
+    size_t		df_optimal_choice;
+};
+
+static int matching_chars(const mmfile_t *m1, const mmfile_t *m2);
+static size_t unwrap_indexes(const int *values, const int *diff_len, const size_t ndiffs);
+static size_t test_charmatch_paths(diffcmppath_T *node, int lastdecision);
+
+    static size_t
+line_len(const mmfile_t *m)
+{
+    char	*s = m->ptr;
+    size_t	n = (size_t)m->size;
+    char	*end;
+
+    end = vim_strnchr(s, &n, '\n');
+    if (end)
+	return (size_t)(end - s);
+
+    return (size_t)m->size;
+}
+
+#define MATCH_CHAR_MAX_LEN 800
+
+/// Same as matching_chars but ignore whitespace
+///
+/// @param s1
+/// @param s2
+    static int
+matching_chars_iwhite(const mmfile_t *s1, const mmfile_t *s2)
+{
+    // the newly processed strings that will be compared
+    // delete the white space characters
+    mmfile_t	sp[2];
+    char	p[2][MATCH_CHAR_MAX_LEN];
+
+    for (int k = 0; k < 2; k++)
+    {
+	const	mmfile_t *s = k == 0 ? s1 : s2;
+	size_t	pi = 0;
+	size_t	slen = MIN(MATCH_CHAR_MAX_LEN - 1, line_len(s));
+
+	for (size_t i = 0; i <= slen; i++)
+	{
+	    char e = s->ptr[i];
+
+	    if (e != ' ' && e != '\t')
+	    {
+		p[k][pi] = e;
+		pi++;
+	    }
+	}
+
+	sp[k].ptr = p[k];
+	sp[k].size = (int)pi;
+    }
+
+    return matching_chars(&sp[0], &sp[1]);
+}
+
+/// Return matching characters between "s1" and "s2" whilst respecting sequence
+/// order.
+/// Consider the case of two strings 'AAACCC' and 'CCCAAA', the
+/// return value from this function will be 3, either to match
+/// the 3 C's, or the 3 A's.
+///
+/// Examples:
+///   matching_chars("aabc", "acba")               -> 2  // 'a' and 'b' in common
+///   matching_chars("123hello567", "he123ll567o") -> 8  // '123', 'll' and '567' in common
+///   matching_chars("abcdefg", "gfedcba")         -> 1  // all characters in common,
+///                                                      // but only at most 1 in sequence
+///
+/// @param m1
+/// @param m2
+    static int
+matching_chars(const mmfile_t *m1, const mmfile_t *m2)
+{
+    size_t	s1len = MIN(MATCH_CHAR_MAX_LEN - 1, line_len(m1));
+    size_t	s2len = MIN(MATCH_CHAR_MAX_LEN - 1, line_len(m2));
+    char	*s1 = m1->ptr;
+    char	*s2 = m2->ptr;
+    int		matrix[2][MATCH_CHAR_MAX_LEN] = { 0 };
+    int		icur = 1;  // save space by storing only two rows for i axis
+
+    for (size_t i = 0; i < s1len; i++)
+    {
+	icur = (icur == 1 ? 0 : 1);
+	int *e1 = matrix[icur];
+	int *e2 = matrix[!icur];
+
+	for (size_t j = 0; j < s2len; j++)
+	{
+	    // skip char in s1
+	    if (e2[j + 1] > e1[j + 1])
+		e1[j + 1] = e2[j + 1];
+	    // skip char in s2
+	    if (e1[j] > e1[j + 1])
+		e1[j + 1] = e1[j];
+	    // compare char in s1 and s2
+	    if ((s1[i] == s2[j]) && (e2[j] + 1) > e1[j + 1])
+		e1[j + 1] = e2[j] + 1;
+	}
+    }
+
+    return matrix[icur][s2len];
+}
+
+/// count the matching characters between a variable number of strings "sp"
+/// mark the strings that have already been compared to extract them later
+/// without re-running the character match counting.
+/// @param sp
+/// @param fomvals
+/// @param n
+    static int
+count_n_matched_chars(mmfile_t **sp, const size_t n, int iwhite)
+{
+    int matched_chars = 0;
+    int matched = 0;
+
+    for (size_t i = 0; i < n; i++)
+    {
+	for (size_t j = i + 1; j < n; j++)
+	{
+	    if (sp[i]->ptr != NULL && sp[j]->ptr != NULL)
+	    {
+		matched++;
+		// TODO(lewis6991): handle whitespace ignoring higher up in the
+		// stack
+		matched_chars += iwhite ? matching_chars_iwhite(sp[i], sp[j])
+					: matching_chars(sp[i], sp[j]);
+	    }
+	}
+    }
+
+    // prioritize a match of 3 (or more lines) equally to a match of 2 lines
+    if (matched >= 2)
+    {
+	matched_chars *= 2;
+	matched_chars /= matched;
+    }
+
+    return matched_chars;
+}
+
+    static mmfile_t
+fastforward_buf_to_lnum(mmfile_t s, linenr_T lnum)
+{
+    for (int i = 0; i < lnum - 1; i++)
+    {
+	size_t n = (size_t)s.size;
+
+	s.ptr = vim_strnchr(s.ptr, &n, '\n');
+	s.size = (int)n;
+	if (!s.ptr)
+	    break;
+	s.ptr++;
+	s.size--;
+    }
+
+    return s;
+}
+
+/// try all the different ways to compare these lines and use the one that
+/// results in the most matching characters
+/// @param df_iters
+/// @param paths
+/// @param npaths
+/// @param path_idx
+/// @param choice
+/// @param diffcmppath
+/// @param diff_len
+/// @param ndiffs
+/// @param diff_blk
+    static void
+try_possible_paths(
+    const int		*df_iters,
+    const size_t	*paths,
+    const int		npaths,
+    const int		path_idx,
+    int			*choice,
+    diffcmppath_T	*diffcmppath,
+    const int		*diff_len,
+    const size_t	ndiffs,
+    const mmfile_t	**diff_blk,
+    int			iwhite)
+{
+    if (path_idx == npaths)
+    {
+	if ((*choice) > 0)
+	{
+	    int from_vals[LN_MAX_BUFS] = { 0 };
+	    const int *to_vals = df_iters;
+
+	    mmfile_t mm[LN_MAX_BUFS];  // stack memory for current_lines
+	    mmfile_t *current_lines[LN_MAX_BUFS];
+	    for (size_t k = 0; k < ndiffs; k++)
+	    {
+		from_vals[k] = df_iters[k];
+		// get the index at all of the places
+		if ((*choice) & (1 << k))
+		{
+		    from_vals[k]--;
+		    mm[k] = fastforward_buf_to_lnum(*diff_blk[k], df_iters[k]);
+		}
+		else
+		    CLEAR_FIELD(mm[k]);
+		current_lines[k] = &mm[k];
+	    }
+	    size_t unwrapped_idx_from = unwrap_indexes(from_vals, diff_len, ndiffs);
+	    size_t unwrapped_idx_to = unwrap_indexes(to_vals, diff_len, ndiffs);
+	    int matched_chars = count_n_matched_chars(current_lines, ndiffs, iwhite);
+	    int score = diffcmppath[unwrapped_idx_from].df_lev_score + matched_chars;
+
+	    if (score > diffcmppath[unwrapped_idx_to].df_lev_score)
+	    {
+		diffcmppath[unwrapped_idx_to].df_path_n = 1;
+		diffcmppath[unwrapped_idx_to].df_decision[0] =
+					&diffcmppath[unwrapped_idx_from];
+		diffcmppath[unwrapped_idx_to].df_choice[0] = *choice;
+		diffcmppath[unwrapped_idx_to].df_lev_score = score;
+	    }
+	    else if (score == diffcmppath[unwrapped_idx_to].df_lev_score)
+	    {
+		size_t k = diffcmppath[unwrapped_idx_to].df_path_n++;
+		diffcmppath[unwrapped_idx_to].df_decision[k] =
+					&diffcmppath[unwrapped_idx_from];
+		diffcmppath[unwrapped_idx_to].df_choice[k] = *choice;
+	    }
+	}
+	return;
+    }
+
+    size_t bit_place = paths[path_idx];
+    *(choice) |= (1 << bit_place);  // set it to 1
+    try_possible_paths(df_iters, paths, npaths, path_idx + 1, choice,
+	    diffcmppath, diff_len, ndiffs, diff_blk, iwhite);
+    *(choice) &= ~(1 << bit_place);  // set it to 0
+    try_possible_paths(df_iters, paths, npaths, path_idx + 1, choice,
+	    diffcmppath, diff_len, ndiffs, diff_blk, iwhite);
+}
+
+/// unwrap indexes to access n dimensional tensor
+/// @param values
+/// @param diff_len
+/// @param ndiffs
+    static size_t
+unwrap_indexes(const int *values, const int *diff_len, const size_t ndiffs)
+{
+    size_t num_unwrap_scalar = 1;
+
+    for (size_t k = 0; k < ndiffs; k++)
+	num_unwrap_scalar *= (size_t)diff_len[k] + 1;
+
+    size_t path_idx = 0;
+    for (size_t k = 0; k < ndiffs; k++)
+    {
+	num_unwrap_scalar /= (size_t)diff_len[k] + 1;
+
+	int n = values[k];
+	path_idx += num_unwrap_scalar * (size_t)n;
+    }
+
+    return path_idx;
+}
+
+/// populate the values of the linematch algorithm tensor, and find the best
+/// decision for how to compare the relevant lines from each of the buffers at
+/// each point in the tensor
+/// @param df_iters
+/// @param ch_dim
+/// @param diffcmppath
+/// @param diff_len
+/// @param ndiffs
+/// @param diff_blk
+    static void
+populate_tensor(
+    int			*df_iters,
+    const size_t	ch_dim,
+    diffcmppath_T	*diffcmppath,
+    const int		*diff_len,
+    const size_t	ndiffs,
+    const mmfile_t	**diff_blk,
+    int			iwhite)
+{
+    if (ch_dim == ndiffs)
+    {
+	int npaths = 0;
+	size_t paths[LN_MAX_BUFS];
+
+	for (size_t j = 0; j < ndiffs; j++)
+	{
+	    if (df_iters[j] > 0)
+	    {
+		paths[npaths] = j;
+		npaths++;
+	    }
+	}
+
+	int choice = 0;
+	size_t unwrapper_idx_to = unwrap_indexes(df_iters, diff_len, ndiffs);
+
+	diffcmppath[unwrapper_idx_to].df_lev_score = -1;
+	try_possible_paths(df_iters, paths, npaths, 0, &choice, diffcmppath,
+					diff_len, ndiffs, diff_blk, iwhite);
+	return;
+    }
+
+    for (int i = 0; i <= diff_len[ch_dim]; i++)
+    {
+	df_iters[ch_dim] = i;
+	populate_tensor(df_iters, ch_dim + 1, diffcmppath, diff_len,
+		ndiffs, diff_blk, iwhite);
+    }
+}
+
+/// algorithm to find an optimal alignment of lines of a diff block with 2 or
+/// more files. The algorithm is generalized to work for any number of files
+/// which corresponds to another dimension added to the tensor used in the
+/// algorithm
+///
+/// for questions and information about the linematch algorithm please contact
+/// Jonathon White (jonathonwhite@protonmail.com)
+///
+/// for explanation, a summary of the algorithm in 3 dimensions (3 files
+///     compared) follows
+///
+/// The 3d case (for 3 buffers) of the algorithm implemented when diffopt
+/// 'linematch' is enabled. The algorithm constructs a 3d tensor to
+/// compare a diff between 3 buffers. The dimensions of the tensor are
+/// the length of the diff in each buffer plus 1 A path is constructed by
+/// moving from one edge of the cube/3d tensor to the opposite edge.
+/// Motions from one cell of the cube to the next represent decisions. In
+/// a 3d cube, there are a total of 7 decisions that can be made,
+/// represented by the enum df_path3_choice which is defined in
+/// buffer_defs.h a comparison of buffer 0 and 1 represents a motion
+/// toward the opposite edge of the cube with components along the 0 and
+/// 1 axes.  a comparison of buffer 0, 1, and 2 represents a motion
+/// toward the opposite edge of the cube with components along the 0, 1,
+/// and 2 axes. A skip of buffer 0 represents a motion along only the 0
+/// axis. For each action, a point value is awarded, and the path is
+/// saved for reference later, if it is found to have been the optimal
+/// path. The optimal path has the highest score.  The score is
+/// calculated as the summation of the total characters matching between
+/// all of the lines which were compared. The structure of the algorithm
+/// is that of a dynamic programming problem.  We can calculate a point
+/// i,j,k in the cube as a function of i-1, j-1, and k-1. To find the
+/// score and path at point i,j,k, we must determine which path we want
+/// to use, this is done by looking at the possibilities and choosing
+/// the one which results in the local highest score.  The total highest
+/// scored path is, then in the end represented by the cell in the
+/// opposite corner from the start location.  The entire algorithm
+/// consists of populating the 3d cube with the optimal paths from which
+/// it may have came.
+///
+/// Optimizations:
+/// As the function to calculate the cell of a tensor at point i,j,k is a
+/// function of the cells at i-1, j-1, k-1, the whole tensor doesn't need
+/// to be stored in memory at once. In the case of the 3d cube, only two
+/// slices (along k and j axis) are stored in memory. For the 2d matrix
+/// (for 2 files), only two rows are stored at a time. The next/previous
+/// slice (or row) is always calculated from the other, and they alternate
+/// at each iteration.
+/// In the 3d case, 3 arrays are populated to memorize the score (matched
+/// characters) of the 3 buffers, so a redundant calculation of the
+/// scores does not occur
+/// @param diff_blk
+/// @param diff_len
+/// @param ndiffs
+/// @param [out] [allocated] decisions
+/// @return the length of decisions
+    size_t
+linematch_nbuffers(
+    const mmfile_t	**diff_blk,
+    const int		*diff_len,
+    const size_t	ndiffs,
+    int			**decisions,
+    int			iwhite)
+{
+    assert(ndiffs <= LN_MAX_BUFS);
+
+    size_t memsize = 1;
+    size_t memsize_decisions = 0;
+    for (size_t i = 0; i < ndiffs; i++)
+    {
+	assert(diff_len[i] >= 0);
+	memsize *= (size_t)(diff_len[i] + 1);
+	memsize_decisions += (size_t)diff_len[i];
+    }
+
+    // create the flattened path matrix
+    diffcmppath_T *diffcmppath = lalloc(sizeof(diffcmppath_T) * memsize, TRUE);
+    // allocate memory here
+    for (size_t i = 0; i < memsize; i++)
+    {
+	diffcmppath[i].df_lev_score = 0;
+	diffcmppath[i].df_path_n = 0;
+	for (size_t j = 0; j < (size_t)pow(2, (double)ndiffs); j++)
+	    diffcmppath[i].df_choice_mem[j] = -1;
+    }
+
+    // memory for avoiding repetitive calculations of score
+    int df_iters[LN_MAX_BUFS];
+    populate_tensor(df_iters, 0, diffcmppath, diff_len, ndiffs, diff_blk,
+		    iwhite);
+
+    const size_t u = unwrap_indexes(diff_len, diff_len, ndiffs);
+    diffcmppath_T *startNode = &diffcmppath[u];
+
+    *decisions = lalloc(sizeof(int) * memsize_decisions, TRUE);
+    size_t n_optimal = 0;
+    test_charmatch_paths(startNode, 0);
+    while (startNode->df_path_n > 0)
+    {
+	size_t j = startNode->df_optimal_choice;
+	(*decisions)[n_optimal++] = startNode->df_choice[j];
+	startNode = startNode->df_decision[j];
+    }
+    // reverse array
+    for (size_t i = 0; i < (n_optimal / 2); i++)
+    {
+	int tmp = (*decisions)[i];
+	(*decisions)[i] = (*decisions)[n_optimal - 1 - i];
+	(*decisions)[n_optimal - 1 - i] = tmp;
+    }
+
+    vim_free(diffcmppath);
+
+    return n_optimal;
+}
+
+// returns the minimum amount of path changes from start to end
+    static size_t
+test_charmatch_paths(diffcmppath_T *node, int lastdecision)
+{
+    // memoization
+    if (node->df_choice_mem[lastdecision] == -1)
+    {
+	if (node->df_path_n == 0)
+	    // we have reached the end of the tree
+	    node->df_choice_mem[lastdecision] = 0;
+	else
+	{
+	    // the minimum amount of turns required to reach the end
+	    size_t minimum_turns = SIZE_MAX;
+	    for (size_t i = 0; i < node->df_path_n; i++)
+	    {
+		// recurse
+		size_t t = test_charmatch_paths(node->df_decision[i],
+							node->df_choice[i]) +
+		    (lastdecision != node->df_choice[i] ? 1 : 0);
+		if (t < minimum_turns)
+		{
+		    node->df_optimal_choice = i;
+		    minimum_turns = t;
+		}
+	    }
+	    node->df_choice_mem[lastdecision] = (int)minimum_turns;
+	}
+    }
+
+    return (size_t)node->df_choice_mem[lastdecision];
+}
diff --git a/src/proto.h b/src/proto.h
index 94e34b0..091e093 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -74,6 +74,7 @@
 # include "debugger.pro"
 # include "dict.pro"
 # include "diff.pro"
+# include "linematch.pro"
 # include "digraph.pro"
 # include "drawline.pro"
 # include "drawscreen.pro"
diff --git a/src/proto/diff.pro b/src/proto/diff.pro
index 9c34dcf..5141e37 100644
--- a/src/proto/diff.pro
+++ b/src/proto/diff.pro
@@ -14,6 +14,7 @@
 void ex_diffoff(exarg_T *eap);
 void diff_clear(tabpage_T *tp);
 int diff_check(win_T *wp, linenr_T lnum);
+int diff_check_with_linestatus(win_T *wp, linenr_T lnum, int *linestatus);
 int diff_check_fill(win_T *wp, linenr_T lnum);
 void diff_set_topline(win_T *fromwin, win_T *towin);
 int diffopt_changed(void);
diff --git a/src/proto/linematch.pro b/src/proto/linematch.pro
new file mode 100644
index 0000000..56d0037
--- /dev/null
+++ b/src/proto/linematch.pro
@@ -0,0 +1,3 @@
+/* linematch.c */
+size_t linematch_nbuffers(const mmfile_t **diff_blk, const int *diff_len, const size_t ndiffs, int **decisions, int iwhite);
+/* vim: set ft=c : */
diff --git a/src/proto/strings.pro b/src/proto/strings.pro
index b792edc..c25555f 100644
--- a/src/proto/strings.pro
+++ b/src/proto/strings.pro
@@ -17,6 +17,7 @@
 int vim_strnicmp(char *s1, char *s2, size_t len);
 int vim_strnicmp_asc(char *s1, char *s2, size_t len);
 char_u *vim_strchr(char_u *string, int c);
+char *vim_strnchr(const char *p, size_t *n, int c);
 char_u *vim_strbyte(char_u *string, int c);
 char_u *vim_strrchr(char_u *string, int c);
 void sort_strings(char_u **files, int count);
diff --git a/src/strings.c b/src/strings.c
index cd75bc3..54ac178 100644
--- a/src/strings.c
+++ b/src/strings.c
@@ -674,6 +674,22 @@
     return NULL;
 }
 
+// Sized version of strchr that can handle embedded NULs.
+// Adjusts n to the new size.
+    char *
+vim_strnchr(const char *p, size_t *n, int c)
+{
+    while (*n > 0)
+    {
+	if (*p == c)
+	    return (char *)p;
+	p++;
+	(*n)--;
+    }
+
+    return NULL;
+}
+
 /*
  * Version of strchr() that only works for bytes and handles unsigned char
  * strings with characters above 128 correctly. It also doesn't return a
diff --git a/src/structs.h b/src/structs.h
index 87aca30..69494dd 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -3553,6 +3553,8 @@
     diff_T	*df_next;
     linenr_T	df_lnum[DB_COUNT];	// line number in buffer
     linenr_T	df_count[DB_COUNT];	// nr of inserted/changed lines
+    int is_linematched;  // has the linematch algorithm ran on this diff hunk to divide it into
+			  // smaller diff hunks?
 };
 #endif
 
diff --git a/src/testdir/dumps/Test_diff_23.dump b/src/testdir/dumps/Test_diff_23.dump
new file mode 100644
index 0000000..25e1750
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_23.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|a| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34
+| +0#0000e05#a8a8a8255@1|?+2#0000000#ff404010|b+0&#ffd7ff255| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|!+2#0000000#ff404010|b+0&#ffd7ff255| @32
+| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|c| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34
+|~+0&#ffffff0| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| @10|1|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|1|,|1| @11|A|l@1
+|:+0&&> @73
diff --git a/src/testdir/dumps/Test_diff_24.dump b/src/testdir/dumps/Test_diff_24.dump
new file mode 100644
index 0000000..71004bd
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_24.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34
+| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34
+| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34
+| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| @10|1|,|0|-|1| @9|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|1|,|0|-|1| @9|A|l@1
+|:+0&&> @73
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_1.dump b/src/testdir/dumps/Test_diff_get_put_linematch_1.dump
new file mode 100644
index 0000000..056c4be
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_1.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1> +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| @10|1|,|0|-|1| @9|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|1|,|0|-|1| @9|A|l@1
+|"+0&&|X|d|i|f|i|l|e|2|"| |1|7|L|,| |1|2|0|B| @54
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_10.dump b/src/testdir/dumps/Test_diff_get_put_linematch_10.dump
new file mode 100644
index 0000000..f163146
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_10.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F| @31||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F| @31
+| +0#0000e05#a8a8a8255@1>s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| |[|+|]| @6|1|3|,|1| @10|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|1|7|,|1| @10|A|l@1
+|:+0&&|d|i|f@1|g|e|t| @66
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_11.dump b/src/testdir/dumps/Test_diff_get_put_linematch_11.dump
new file mode 100644
index 0000000..7e78baf
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_11.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1>A+0#0000000#ffffff0|B|C|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| @10|5|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| |[|+|]| @6|5|,|1| @11|A|l@1
+|:+0&&|d|i|f@1|p|u|t| @66
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_12.dump b/src/testdir/dumps/Test_diff_get_put_linematch_12.dump
new file mode 100644
index 0000000..8e9e0c6
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_12.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1>A+0#0000000#ffffff0|B|C|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| @10|6|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| |[|+|]| @6|9|,|1| @11|A|l@1
+|:+0&&|d|i|f@1|p|u|t| @66
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_13.dump b/src/testdir/dumps/Test_diff_get_put_linematch_13.dump
new file mode 100644
index 0000000..1601c5d
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_13.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28
+| +0#0000e05#a8a8a8255@1>A+0#0000000#ffffff0|B|C|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| @10|7|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| |[|+|]| @6|1|0|,|1| @10|A|l@1
+|:+0&&|d|i|f@1|p|u|t| @66
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_14.dump b/src/testdir/dumps/Test_diff_get_put_linematch_14.dump
new file mode 100644
index 0000000..9c7d17b
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_14.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1>c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| @10|1@1|,|1| @10|A|l@1| |X+1&&|d|i|f|i|l|e|2| |[|+|]| @6|1|4|,|1| @10|A|l@1
+|:+0&&|d|i|f@1|p|u|t| @66
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_15.dump b/src/testdir/dumps/Test_diff_get_put_linematch_15.dump
new file mode 100644
index 0000000..d9b72ad
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_15.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1>s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| @10|1|2|,|1| @10|A|l@1| |X+1&&|d|i|f|i|l|e|2| |[|+|]| @6|1|6|,|1| @10|A|l@1
+|:+0&&|d|i|f@1|p|u|t| @66
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_16.dump b/src/testdir/dumps/Test_diff_get_put_linematch_16.dump
new file mode 100644
index 0000000..d4649d2
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_16.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31||+1&&| +0#0000e05#a8a8a8255@1>x+0#0000000#ffffff0|y|z| @31
+| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31||+1&&| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31
+| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31||+1&&| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+1#0000000&|d|i|f|i|l|e|1| |[|+|]| @6|9|,|1| @11|A|l@1| |X+3&&|d|i|f|i|l|e|2| @10|6|,|1| @11|A|l@1
+|:+0&&|d|i|f@1|p|u|t| @66
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_17.dump b/src/testdir/dumps/Test_diff_get_put_linematch_17.dump
new file mode 100644
index 0000000..69737fa
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_17.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31||+1&&| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31
+| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31||+1&&| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31
+| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31||+1&&| +0#0000e05#a8a8a8255@1>x+0#0000000#ffffff0|y|z| @31
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+1#0000000&|d|i|f|i|l|e|1| |[|+|]| @6|9|,|1| @11|A|l@1| |X+3&&|d|i|f|i|l|e|2| @10|8|,|1| @11|A|l@1
+|:+0&&|d|i|f@1|p|u|t| @66
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_18.dump b/src/testdir/dumps/Test_diff_get_put_linematch_18.dump
new file mode 100644
index 0000000..49ab243
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_18.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1>D+0#0000000#ffffff0|E|F|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+1#0000000&|d|i|f|i|l|e|1| |[|+|]| @6|6|,|1| @11|A|l@1| |X+3&&|d|i|f|i|l|e|2| @10|9|,|1| @11|A|l@1
+|:+0&&|d|i|f@1|p|u|t| @66
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_19.dump b/src/testdir/dumps/Test_diff_get_put_linematch_19.dump
new file mode 100644
index 0000000..cbea3e5
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_19.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F| @31||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F| @31
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1>s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+1#0000000&|d|i|f|i|l|e|1| |[|+|]| @6|1|3|,|1| @10|A|l@1| |X+3&&|d|i|f|i|l|e|2| @10|1|7|,|1| @10|A|l@1
+|:+0&&|d|i|f@1|p|u|t| @66
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_2.dump b/src/testdir/dumps/Test_diff_get_put_linematch_2.dump
new file mode 100644
index 0000000..df249ab
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_2.dump
@@ -0,0 +1,20 @@
+|++0#0000e05#a8a8a8255| >+|-@1| @1|7| |l|i|n|e|s|:| |c|o|m@1|o|n| |l|i|n|e|-@9||+1#0000000#ffffff0|++0#0000e05#a8a8a8255| |+|-@1| @1|7| |l|i|n|e|s|:| |c|o|m@1|o|n| |l|i|n|e|-@9
+| @1|x+0#0000000#ffffff0|y|z| @31||+1&&| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31
+| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| |[|+|]| @6|1|,|0|-|1| @9|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|1|,|0|-|1| @9|A|l@1
+|:+0&&|5|,|9|d|i|f@1|g|e|t| @63
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_3.dump b/src/testdir/dumps/Test_diff_get_put_linematch_3.dump
new file mode 100644
index 0000000..cb62a9e
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_3.dump
@@ -0,0 +1,20 @@
+|-+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@34||+1&&|-+0#0000e05#a8a8a8255| | +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1>A+0#0000000#ffffff0|B|C|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+1#0000000&|d|i|f|i|l|e|1| @10|5|,|1| @11|A|l@1| |X+3&&|d|i|f|i|l|e|2| |[|+|]| @6|5|,|1| @11|A|l@1
+|:+0&&|5|,|1|0|d|i|f@1|g|e|t| @62
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_4.dump b/src/testdir/dumps/Test_diff_get_put_linematch_4.dump
new file mode 100644
index 0000000..6cd85c9
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_4.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1>A+0#0000000#ffffff0|B|C|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+1#0000000&|d|i|f|i|l|e|1| @10|5|,|1| @11|A|l@1| |X+3&&|d|i|f|i|l|e|2| |[|+|]| @6|5|,|1| @11|A|l@1
+|:+0&&|4|,|1|7|d|i|f@1|g|e|t| @62
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_5.dump b/src/testdir/dumps/Test_diff_get_put_linematch_5.dump
new file mode 100644
index 0000000..d203885
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_5.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1>D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31||+1&&| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31
+| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31||+1&&| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31
+| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31||+1&&| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31
+| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F| @31||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F| @31
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F| @31||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F| @31
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| |[|+|]| @6|5|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|5|,|1| @11|A|l@1
+|:+0&&|4|,|1|2|d|i|f@1|g|e|t| @62
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_6.dump b/src/testdir/dumps/Test_diff_get_put_linematch_6.dump
new file mode 100644
index 0000000..b2ca4d1
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_6.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1>D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| |[|+|]| @6|5|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|5|,|1| @11|A|l@1
+|:+0&&|d|i|f@1|g|e|t| @66
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_7.dump b/src/testdir/dumps/Test_diff_get_put_linematch_7.dump
new file mode 100644
index 0000000..fa85299
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_7.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1>D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| |[|+|]| @6|6|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|9|,|1| @11|A|l@1
+|:+0&&|d|i|f@1|g|e|t| @66
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_8.dump b/src/testdir/dumps/Test_diff_get_put_linematch_8.dump
new file mode 100644
index 0000000..d99744e
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_8.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
+| +0#0000e05#a8a8a8255@1>D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| |[|+|]| @6|7|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|1|0|,|1| @10|A|l@1
+|:+0&&|d|i|f@1|g|e|t| @66
diff --git a/src/testdir/dumps/Test_diff_get_put_linematch_9.dump b/src/testdir/dumps/Test_diff_get_put_linematch_9.dump
new file mode 100644
index 0000000..3c1674f
--- /dev/null
+++ b/src/testdir/dumps/Test_diff_get_put_linematch_9.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|A+2#0000000#ff404010|B|C|a+0&#ffd7ff255|b|c| @28||+1&#ffffff0| +0#0000e05#a8a8a8255@1|D+2#0000000#ff404010|E|F|a+0&#ffd7ff255|b|c| @28
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F| @31||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F| @31
+| +0#0000e05#a8a8a8255@1>c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| |[|+|]| @6|1|2|,|1| @10|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|1|5|,|1| @10|A|l@1
+|:+0&&|d|i|f@1|g|e|t| @66
diff --git a/src/testdir/dumps/Test_linematch_3diffs1.dump b/src/testdir/dumps/Test_linematch_3diffs1.dump
new file mode 100644
index 0000000..e54fe26
--- /dev/null
+++ b/src/testdir/dumps/Test_linematch_3diffs1.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@22||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@21||+1&&| +0#0000e05#a8a8a8255@1> +0#0000000#ffffff0@21
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@1|c|o|m@1|o|n| |l|i|n|e| @9||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@1|c|o|m@1|o|n| |l|i|n|e| @8||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@1|c|o|m@1|o|n| |l|i|n|e| @8
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@22||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@1|<@6| |H|E|A|D| @7||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@21
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@5|A@2| @13||+1&#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@5|A@2| @12||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@21
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@5|A@2| @13||+1&#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@5|A@2| @12||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@21
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@5|A@2| @13||+1&#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@5|A@2| @12||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@21
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@22||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@1|=@6| @12||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@21
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@22||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@5|B@2| @12||+1&#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@5|B@2| @12
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@22||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@5|B@2| @12||+1&#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@5|B@2| @12
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@22||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@5|B@2| @12||+1&#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@5|B@2| @12
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@22||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@1|>@6| |b|r|a|n|c|h|1| @4||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@21
+|~+0&#ffffff0| @23||+1#0000000&|~+0#4040ff13&| @22||+1#0000000&|~+0#4040ff13&| @22
+|~| @23||+1#0000000&|~+0#4040ff13&| @22||+1#0000000&|~+0#4040ff13&| @22
+|~| @23||+1#0000000&|~+0#4040ff13&| @22||+1#0000000&|~+0#4040ff13&| @22
+|~| @23||+1#0000000&|~+0#4040ff13&| @22||+1#0000000&|~+0#4040ff13&| @22
+|~| @23||+1#0000000&|~+0#4040ff13&| @22||+1#0000000&|~+0#4040ff13&| @22
+|~| @23||+1#0000000&|~+0#4040ff13&| @22||+1#0000000&|~+0#4040ff13&| @22
+|~| @23||+1#0000000&|~+0#4040ff13&| @22||+1#0000000&|~+0#4040ff13&| @22
+|X+1#0000000&|d|i|f|i|l|e|1| @4|1|,|0|-|1| @3|A|l@1| |X|d|i|f|i|l|e|2| @3|1|,|0|-|1| @3|A|l@1| |X+3&&|d|i|f|i|l|e|3| @3|1|,|0|-|1| @3|A|l@1
+|"+0&&|X|d|i|f|i|l|e|3|"| |5|L|,| |4|5|B| @56
diff --git a/src/testdir/dumps/Test_linematch_diff1.dump b/src/testdir/dumps/Test_linematch_diff1.dump
new file mode 100644
index 0000000..26b729c
--- /dev/null
+++ b/src/testdir/dumps/Test_linematch_diff1.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|!+0#0000000#5fd7ff255| @33
+| +0#0000e05#a8a8a8255@1>/+2#0000000#ff404010@1| |a|b|c| |d|?| +0&#ffd7ff255@25||+1&#ffffff0| +0#0000e05#a8a8a8255@1|a+2#0000000#ff404010|b|c| |d|!| +0&#ffd7ff255@28
+| +0#0000e05#a8a8a8255@1|/+2#0000000#ff404010@1| |d|?| +0&#ffd7ff255@29||+1&#ffffff0| +0#0000e05#a8a8a8255@1|d+2#0000000#ff404010|!| +0&#ffd7ff255@32
+| +0#0000e05#a8a8a8255@1|/+0#0000000#5fd7ff255@1| |d|?| @29||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34
+|~+0&#ffffff0| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| @10|1|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|1|,|1| @11|A|l@1
+|"+0&&|X|d|i|f|i|l|e|2|"| |3|L|,| |1|2|B| @56
diff --git a/src/testdir/dumps/Test_linematch_diff_grouping1.dump b/src/testdir/dumps/Test_linematch_diff_grouping1.dump
new file mode 100644
index 0000000..19c9073
--- /dev/null
+++ b/src/testdir/dumps/Test_linematch_diff_grouping1.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|Z| @32
+| +0#0000e05#a8a8a8255@1>!+2#0000000#ff404010|A+0&#ffd7ff255| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|?+2#0000000#ff404010|A+0&#ffd7ff255| @32
+| +0#0000e05#a8a8a8255@1|!+2#0000000#ff404010|B+0&#ffd7ff255| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|?+2#0000000#ff404010|B+0&#ffd7ff255| @32
+| +0#0000e05#a8a8a8255@1|!+2#0000000#ff404010|C+0&#ffd7ff255| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|?+2#0000000#ff404010|C+0&#ffd7ff255| @32
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|A| @32
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|B| @32
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|B| @32
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|C| @32
+|~+0#4040ff13#ffffff0| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| @10|1|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|1|,|1| @11|A|l@1
+|"+0&&|X|d|i|f|i|l|e|2|"| |8|L|,| |2|4|B| @56
diff --git a/src/testdir/dumps/Test_linematch_diff_grouping2.dump b/src/testdir/dumps/Test_linematch_diff_grouping2.dump
new file mode 100644
index 0000000..35cf575
--- /dev/null
+++ b/src/testdir/dumps/Test_linematch_diff_grouping2.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|A| @32
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|Z| @32
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|B| @32
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|C| @32
+| +0#0000e05#a8a8a8255@1>!+2#0000000#ff404010|A+0&#ffd7ff255| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|?+2#0000000#ff404010|A+0&#ffd7ff255| @32
+| +0#0000e05#a8a8a8255@1|!+2#0000000#ff404010|B+0&#ffd7ff255| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|?+2#0000000#ff404010|B+0&#ffd7ff255| @32
+| +0#0000e05#a8a8a8255@1|!+2#0000000#ff404010|C+0&#ffd7ff255| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|?+2#0000000#ff404010|C+0&#ffd7ff255| @32
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|C| @32
+|~+0#4040ff13#ffffff0| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| @10|1|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|1|,|1| @11|A|l@1
+|"+0&&|X|d|i|f|i|l|e|2|"| |8|L|,| |2|4|B| @56
diff --git a/src/testdir/dumps/Test_linematch_diff_grouping_scroll0.dump b/src/testdir/dumps/Test_linematch_diff_grouping_scroll0.dump
new file mode 100644
index 0000000..35cf575
--- /dev/null
+++ b/src/testdir/dumps/Test_linematch_diff_grouping_scroll0.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|A| @32
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|Z| @32
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|B| @32
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|C| @32
+| +0#0000e05#a8a8a8255@1>!+2#0000000#ff404010|A+0&#ffd7ff255| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|?+2#0000000#ff404010|A+0&#ffd7ff255| @32
+| +0#0000e05#a8a8a8255@1|!+2#0000000#ff404010|B+0&#ffd7ff255| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|?+2#0000000#ff404010|B+0&#ffd7ff255| @32
+| +0#0000e05#a8a8a8255@1|!+2#0000000#ff404010|C+0&#ffd7ff255| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|?+2#0000000#ff404010|C+0&#ffd7ff255| @32
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|C| @32
+|~+0#4040ff13#ffffff0| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| @10|1|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|1|,|1| @11|A|l@1
+|"+0&&|X|d|i|f|i|l|e|2|"| |8|L|,| |2|4|B| @56
diff --git a/src/testdir/dumps/Test_linematch_diff_grouping_scroll1.dump b/src/testdir/dumps/Test_linematch_diff_grouping_scroll1.dump
new file mode 100644
index 0000000..673b909
--- /dev/null
+++ b/src/testdir/dumps/Test_linematch_diff_grouping_scroll1.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|C| @32
+| +0#0000e05#a8a8a8255@1>!+2#0000000#ff404010|A+0&#ffd7ff255| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|?+2#0000000#ff404010|A+0&#ffd7ff255| @32
+| +0#0000e05#a8a8a8255@1|!+2#0000000#ff404010|B+0&#ffd7ff255| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|?+2#0000000#ff404010|B+0&#ffd7ff255| @32
+| +0#0000e05#a8a8a8255@1|!+2#0000000#ff404010|C+0&#ffd7ff255| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|?+2#0000000#ff404010|C+0&#ffd7ff255| @32
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|C| @32
+|~+0#4040ff13#ffffff0| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| @10|1|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|8|,|1| @11|B|o|t
+| +0&&@74
diff --git a/src/testdir/dumps/Test_linematch_diff_grouping_scroll2.dump b/src/testdir/dumps/Test_linematch_diff_grouping_scroll2.dump
new file mode 100644
index 0000000..0d91732
--- /dev/null
+++ b/src/testdir/dumps/Test_linematch_diff_grouping_scroll2.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1>!+2#0000000#ff404010|C+0&#ffd7ff255| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|?+2#0000000#ff404010|C+0&#ffd7ff255| @32
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|?+0#0000000#5fd7ff255|C| @32
+|~+0#4040ff13#ffffff0| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| @10|3|,|1| @11|B|o|t| |X+1&&|d|i|f|i|l|e|2| @10|7|,|1| @11|B|o|t
+| +0&&@74
diff --git a/src/testdir/dumps/Test_linematch_diff_iwhite1.dump b/src/testdir/dumps/Test_linematch_diff_iwhite1.dump
new file mode 100644
index 0000000..50803a3
--- /dev/null
+++ b/src/testdir/dumps/Test_linematch_diff_iwhite1.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1>v+0#0000000#ffffff0|o|i|d| |t|e|s|t|F|u|n|c|t|i|o|n| |(|)| |{| @12||+1&&| +0#0000e05#a8a8a8255@1|v+0#0000000#ffffff0|o|i|d| |t|e|s|t|F|u|n|c|t|i|o|n| |(|)| |{| @12
+| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@1|f|o|r| |(|i|n|t| |i| |=| |0|;| |i| |<| |1|0|;| |i|+@1|)| |{| @2||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@1| +2&#ff404010@1|f|o|r| |(|i|n|t| |j| |=| |0|;| |j| |<| |1|0|;| |j|++0&#ffd7ff255@1|)| |{| ||+1&#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@1|/+2&#ff404010@1| |f|o|r| |(|i|n|t| |j| |=| |0|;| |j| |<| |1|0|;| |i|++0&#ffd7ff255@1|)| |{
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@1| +2&#ff404010| +0&#ffd7ff255|}| @29||+1&#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@1|/+2&#ff404010@1| +0&#ffd7ff255|}| @28
+| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@1|}| @31||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34
+| +0#0000e05#a8a8a8255@1|}+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|}+0#0000000#ffffff0| @33
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| @10|1|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|1|,|1| @11|A|l@1
+|"+0&&|X|d|i|f|i|l|e|2|"| |4|L|,| |6|8|B| @56
diff --git a/src/testdir/dumps/Test_linematch_diff_iwhite2.dump b/src/testdir/dumps/Test_linematch_diff_iwhite2.dump
new file mode 100644
index 0000000..11a489a
--- /dev/null
+++ b/src/testdir/dumps/Test_linematch_diff_iwhite2.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1>v+0#0000000#ffffff0|o|i|d| |t|e|s|t|F|u|n|c|t|i|o|n| |(|)| |{| @12||+1&&| +0#0000e05#a8a8a8255@1|v+0#0000000#ffffff0|o|i|d| |t|e|s|t|F|u|n|c|t|i|o|n| |(|)| |{| @12
+| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@1|f|o|r| |(|i|n|t| |i| |=| |0|;| |i| |<| |1|0|;| |i|+@1|)| |{| @2||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@3|f+2&#ff404010|o|r| |(|i|n|t| |j| |=| |0|;| |j| |<| |1|0|;| |j|++0&#ffd7ff255@1|)| |{| ||+1&#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@1|/+2&#ff404010@1| |f|o|r| |(|i|n|t| |j| |=| |0|;| |j| |<| |1|0|;| |i|++0&#ffd7ff255@1|)| |{
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@3|}| @29||+1&#ffffff0| +0#0000e05#a8a8a8255@1| +0#0000000#ffd7ff255@1|/+2&#ff404010@1| |}+0&#ffd7ff255| @28
+| +0#0000e05#a8a8a8255@1| +0#0000000#5fd7ff255@1|}| @31||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34
+| +0#0000e05#a8a8a8255@1|}+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|}+0#0000000#ffffff0| @33
+|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|~| @35||+1#0000000&|~+0#4040ff13&| @35
+|X+3#0000000&|d|i|f|i|l|e|1| @10|1|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|1|,|1| @11|A|l@1
+|:+0&&|s|e|t| |d|i|f@1|o|p|t|+|=|i|w|h|i|t|e|a|l@1| @51
diff --git a/src/testdir/dumps/Test_linematch_line_limit_exceeded1.dump b/src/testdir/dumps/Test_linematch_line_limit_exceeded1.dump
new file mode 100644
index 0000000..71b0848
--- /dev/null
+++ b/src/testdir/dumps/Test_linematch_line_limit_exceeded1.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1>c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|H+2#0000000#ff404010|I|L| +0&#ffd7ff255@31||+1&#ffffff0| +0#0000e05#a8a8a8255@1|G+2#0000000#ff404010|H|I| +0&#ffd7ff255@31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|s+0#0000000#5fd7ff255|o|m|e|t|h|i|n|g| @25
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|a+0#0000000#ffd7ff255|A+2&#ff404010|B|C|a+0&#ffd7ff255|b|c| @27||+1&#ffffff0| +0#0000e05#a8a8a8255@1|a+0#0000000#ffd7ff255|D+2&#ff404010|E|F|a+0&#ffd7ff255|b|c| @27
+| +0#0000e05#a8a8a8255@1|a+2#0000000#ff404010|A|B|C|a|b|c| +0&#ffd7ff255@27||+1&#ffffff0| +0#0000e05#a8a8a8255@1|x+2#0000000#ff404010|y|z| +0&#ffd7ff255@31
+| +0#0000e05#a8a8a8255@1|a+2#0000000#ff404010|A|B|C|a|b|c| +0&#ffd7ff255@27||+1&#ffffff0| +0#0000e05#a8a8a8255@1|x+2#0000000#ff404010|y|z| +0&#ffd7ff255@31
+| +0#0000e05#a8a8a8255@1|a+2#0000000#ff404010|A|B|C|a|b|c| +0&#ffd7ff255@27||+1&#ffffff0| +0#0000e05#a8a8a8255@1|x+2#0000000#ff404010|y|z| +0&#ffd7ff255@31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|a+0#0000000#5fd7ff255|D|E|F|a|b|c| @27
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|a+0#0000000#5fd7ff255|D|E|F|a|b|c| @27
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|a+0#0000000#5fd7ff255|D|E|F|a|b|c| @27
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|H+2#0000000#ff404010|I|L| +0&#ffd7ff255@31||+1&#ffffff0| +0#0000e05#a8a8a8255@1|G+2#0000000#ff404010|H|I| +0&#ffd7ff255@31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|s+0#0000000#5fd7ff255|o|m|e|t|h|i|n|g| |e|l|s|e| @20
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|X+3&&|d|i|f|i|l|e|1| @10|1|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|1|,|1| @11|A|l@1
+|"+0&&|X|d|i|f|i|l|e|2|"| |1|8|L|,| |1|3|2|B| @54
diff --git a/src/testdir/dumps/Test_linematch_line_limit_exceeded2.dump b/src/testdir/dumps/Test_linematch_line_limit_exceeded2.dump
new file mode 100644
index 0000000..b88b407
--- /dev/null
+++ b/src/testdir/dumps/Test_linematch_line_limit_exceeded2.dump
@@ -0,0 +1,20 @@
+| +0#0000e05#a8a8a8255@1>c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|H+2#0000000#ff404010|I|L| +0&#ffd7ff255@31||+1&#ffffff0| +0#0000e05#a8a8a8255@1|G+2#0000000#ff404010|H|I| +0&#ffd7ff255@31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|s+0#0000000#5fd7ff255|o|m|e|t|h|i|n|g| @25
+| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
+| +0#0000e05#a8a8a8255@1|a+0#0000000#ffd7ff255|A+2&#ff404010|B|C|a+0&#ffd7ff255|b|c| @27||+1&#ffffff0| +0#0000e05#a8a8a8255@1|a+0#0000000#ffd7ff255|D+2&#ff404010|E|F|a+0&#ffd7ff255|b|c| @27
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|x+0#0000000#5fd7ff255|y|z| @31
+| +0#0000e05#a8a8a8255@1|a+0#0000000#ffd7ff255|A+2&#ff404010|B|C|a+0&#ffd7ff255|b|c| @27||+1&#ffffff0| +0#0000e05#a8a8a8255@1|a+0#0000000#ffd7ff255|D+2&#ff404010|E|F|a+0&#ffd7ff255|b|c| @27
+| +0#0000e05#a8a8a8255@1|a+0#0000000#ffd7ff255|A+2&#ff404010|B|C|a+0&#ffd7ff255|b|c| @27||+1&#ffffff0| +0#0000e05#a8a8a8255@1|a+0#0000000#ffd7ff255|D+2&#ff404010|E|F|a+0&#ffd7ff255|b|c| @27
+| +0#0000e05#a8a8a8255@1|a+0#0000000#ffd7ff255|A+2&#ff404010|B|C|a+0&#ffd7ff255|b|c| @27||+1&#ffffff0| +0#0000e05#a8a8a8255@1|a+0#0000000#ffd7ff255|D+2&#ff404010|E|F|a+0&#ffd7ff255|b|c| @27
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|D+0#0000000#5fd7ff255|E|F| @31
+| +0#0000e05#a8a8a8255@1|H+2#0000000#ff404010|I|L| +0&#ffd7ff255@31||+1&#ffffff0| +0#0000e05#a8a8a8255@1|G+2#0000000#ff404010|H|I| +0&#ffd7ff255@31
+| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|s+0#0000000#5fd7ff255|o|m|e|t|h|i|n|g| |e|l|s|e| @20
+| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
+| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
+|X+3&&|d|i|f|i|l|e|1| @10|1|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|1|,|1| @11|A|l@1
+|:+0&&|s|e|t| |d|i|f@1|o|p|t|+|=|l|i|n|e|m|a|t|c|h|:|3|0| @48
diff --git a/src/testdir/test_diffmode.vim b/src/testdir/test_diffmode.vim
index bed795e..1c7233e 100644
--- a/src/testdir/test_diffmode.vim
+++ b/src/testdir/test_diffmode.vim
Binary files differ
diff --git a/src/version.c b/src/version.c
index 858034e..19c08b9 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1009,
+/**/
     1008,
 /**/
     1007,
diff --git a/src/vim.h b/src/vim.h
index 25c9d12..1cf7648 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -1992,6 +1992,7 @@
 // Note that gui.h is included by structs.h
 
 #include "structs.h"	// defines many structures
+#include "xdiff/xdiff.h"	// TODO: maybe remove this, but this brings in mmfile_t so it can compile
 
 #include "alloc.h"