]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.1009: diff feature can be improved v9.1.1009
authorJonathon <jonathonwhite@protonmail.com>
Sun, 12 Jan 2025 08:58:00 +0000 (09:58 +0100)
committerChristian Brabandt <cb@256bit.org>
Sun, 12 Jan 2025 08:58:00 +0000 (09:58 +0100)
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>
53 files changed:
Filelist
runtime/doc/options.txt
runtime/doc/version9.txt
src/Make_ami.mak
src/Make_cyg_ming.mak
src/Make_mvc.mak
src/Make_vms.mms
src/Makefile
src/diff.c
src/drawline.c
src/globals.h
src/linematch.c [new file with mode: 0644]
src/proto.h
src/proto/diff.pro
src/proto/linematch.pro [new file with mode: 0644]
src/proto/strings.pro
src/strings.c
src/structs.h
src/testdir/dumps/Test_diff_23.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_24.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_1.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_10.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_11.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_12.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_13.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_14.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_15.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_16.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_17.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_18.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_19.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_2.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_3.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_4.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_5.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_6.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_7.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_8.dump [new file with mode: 0644]
src/testdir/dumps/Test_diff_get_put_linematch_9.dump [new file with mode: 0644]
src/testdir/dumps/Test_linematch_3diffs1.dump [new file with mode: 0644]
src/testdir/dumps/Test_linematch_diff1.dump [new file with mode: 0644]
src/testdir/dumps/Test_linematch_diff_grouping1.dump [new file with mode: 0644]
src/testdir/dumps/Test_linematch_diff_grouping2.dump [new file with mode: 0644]
src/testdir/dumps/Test_linematch_diff_grouping_scroll0.dump [new file with mode: 0644]
src/testdir/dumps/Test_linematch_diff_grouping_scroll1.dump [new file with mode: 0644]
src/testdir/dumps/Test_linematch_diff_grouping_scroll2.dump [new file with mode: 0644]
src/testdir/dumps/Test_linematch_diff_iwhite1.dump [new file with mode: 0644]
src/testdir/dumps/Test_linematch_diff_iwhite2.dump [new file with mode: 0644]
src/testdir/dumps/Test_linematch_line_limit_exceeded1.dump [new file with mode: 0644]
src/testdir/dumps/Test_linematch_line_limit_exceeded2.dump [new file with mode: 0644]
src/testdir/test_diffmode.vim
src/version.c
src/vim.h

index 0a1d9936a26b7ebef4ffc4e2763a8916f5e745ff..aefed89d88af5fb8ba8186f39dab63c102ee7195 100644 (file)
--- a/Filelist
+++ b/Filelist
@@ -52,6 +52,7 @@ SRC_ALL =     \
                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_ALL =   \
                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 \
index 780db60aba41fd77f79c3f6a9ecf65b472d9cebf..2f64ba3be00d768a10542aeece17c8bb5116af2b 100644 (file)
@@ -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 @@ A jump table for the options with a short description can be found at |Q_op|.
        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 @@ A jump table for the options with a short description can be found at |Q_op|.
                                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 @@ A jump table for the options with a short description can be found at |Q_op|.
                                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 @@ A jump table for the options with a short description can be found at |Q_op|.
                                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=
index bcb0b78f7b97ba6b231b1388c69cffbb832ac05b..e212230e5bbdcc558475ba90c754b4cb5c7abfa4 100644 (file)
@@ -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 @@ Changed~
   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 ~
index 42270f36ba904682cf24194e2f7dc52a4b4d8d87..c779914292b95f707c75db83c1863aaf472253de 100644 (file)
@@ -123,6 +123,7 @@ SRC += \
        indent.c \
        insexpand.c \
        json.c \
+       linematch.c\
        list.c \
        locale.c \
        logfile.c \
index cd84b85a5a0e3ca7be565d5fe6a3759691921892..3f2a6dabdb0c342f20dbf24f953600c613071e0c 100644 (file)
@@ -817,6 +817,7 @@ OBJ = \
        $(OUTDIR)/indent.o \
        $(OUTDIR)/insexpand.o \
        $(OUTDIR)/json.o \
+       $(OUTDIR)/linematch.o \
        $(OUTDIR)/list.o \
        $(OUTDIR)/locale.o \
        $(OUTDIR)/logfile.o \
index 49d8a337325d74bda163ddb1ba3dbcd796b61e58..c24f0af8554499ecbb50c62a00b529741e680cd6 100644 (file)
@@ -738,6 +738,7 @@ OBJ = \
        $(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)/job.obj:        $(OUTDIR) job.c $(INCL)
 
 $(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.h: \
        proto/indent.pro \
        proto/insexpand.pro \
        proto/json.pro \
+       proto/linematch.pro \
        proto/list.pro \
        proto/locale.pro \
        proto/logfile.pro \
index 559c2f8e43a0fe98f1e61f265cf4815f2ab6a2bc..20630236fedb85f12828fc6ed93f4bae227aef0b 100644 (file)
@@ -381,6 +381,7 @@ SRC = \
        insexpand.c \
        job.c \
        json.c \
+       linematch.c \
        list.c \
        locale.c \
        logfile.c \
@@ -514,6 +515,7 @@ OBJ = \
        insexpand.obj \
        job.obj \
        json.obj \
+       linematch.obj \
        list.obj \
        locale.obj \
        logfile.obj \
@@ -986,6 +988,9 @@ job.obj : job.c vim.h [.auto]config.h feature.h os_unix.h
 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 \
index f5d01cf08265a28a72cb585bb8054298456bb13c..7f26c908c885aedfb2dc2b9e9376d7cc2fb5a9df 100644 (file)
@@ -1531,6 +1531,7 @@ BASIC_SRC = \
        indent.c \
        insexpand.c \
        json.c \
+       linematch.c \
        list.c \
        locale.c \
        logfile.c \
@@ -1693,6 +1694,7 @@ OBJ_COMMON = \
        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 @@ PRO_AUTO = \
        debugger.pro \
        dict.pro \
        diff.pro \
+       linematch.pro \
        digraph.pro \
        drawline.pro \
        drawscreen.pro \
@@ -3343,6 +3346,9 @@ objects/json_test.o: json_test.c
 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 @@ objects/json.o: json.c vim.h protodef.h auto/config.h feature.h os_unix.h \
  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 \
index ebe409e5f35550163152ef60040c5c0c535a0f53..971ef6520de39c32bc0575b7bdbff9580b1cc1ee 100644 (file)
@@ -37,6 +37,7 @@ static int diff_need_update = FALSE; // ex_diffupdate needs to be called
 #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 @@ diff_mark_adjust_tp(
        {
            // 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 @@ diff_mark_adjust_tp(
        }
 
        // 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 @@ diff_alloc_new(tabpage_T *tp, diff_T *dprev, diff_T *dp)
     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 @@ clear_diffout(diffout_T *dout)
  * 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 @@ diff_write_buffer(buf_T *buf, diffin_T *din)
     }
 
     // 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 @@ diff_write_buffer(buf_T *buf, diffin_T *din)
     din->din_mmfile.size = len;
 
     len = 0;
-    for (lnum = 1; lnum <= buf->b_ml.ml_line_count; ++lnum)
+    for (lnum = start; lnum <= end; ++lnum)
     {
        for (s = ml_get_buf(buf, lnum, FALSE); *s != NUL; )
        {
@@ -841,7 +848,7 @@ diff_write(buf_T *buf, diffin_T *din)
     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;
@@ -1922,6 +1929,360 @@ diff_clear(tabpage_T *tp)
     tp->tp_first_diff = NULL;
 }
 
+/*
+ *  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
@@ -1930,9 +2291,15 @@ diff_clear(tabpage_T *tp)
  * 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 @@ diff_check(win_T *wp, linenr_T lnum)
     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 @@ diff_check(win_T *wp, linenr_T lnum)
 
     // Insert filler lines above the line just below the change.  Will return
     // 0 when this buf had the max count.
-    maxcount = 0;
-    for (i = 0; i < DB_COUNT; ++i)
-       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 @@ diff_set_topline(win_T *fromwin, win_T *towin)
        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->df_count[toidx] == dp->df_count[fromidx])
+           if (dp->is_linematched)
            {
-               // same number of lines: use same filler count
-               towin->w_topfill = fromwin->w_topfill;
+               calculate_topfill_and_topline(fromidx, toidx,
+                                               fromwin->w_topline,
+                                               fromwin->w_topfill,
+                                               &towin->w_topfill,
+                                               &towin->w_topline);
            }
-           else if (dp->df_count[toidx] > dp->df_count[fromidx])
+           else
            {
-               if (lnum == dp->df_lnum[fromidx] + dp->df_count[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->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])
                {
-                   // more lines in towin and fromwin doesn't show diff
-                   // lines, only filler lines
-                   if (max_count - fromwin->w_topfill >= dp->df_count[toidx])
+                   if (lnum == dp->df_lnum[fromidx] + dp->df_count[fromidx])
                    {
-                       // towin also only shows filler lines
-                       towin->w_topline = dp->df_lnum[toidx]
-                                                      + dp->df_count[toidx];
-                       towin->w_topfill = fromwin->w_topfill;
+                       // 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
-                       // 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)
+               else if (towin->w_topline >= dp->df_lnum[toidx]
+                                                           + dp->df_count[toidx])
                {
-                   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;
+                   // 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 @@ diffopt_changed(void)
 {
     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 @@ diffopt_changed(void)
            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 @@ diffopt_changed(void)
 
     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 @@ diff_find_change(
     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 @@ ex_diffgetput(exarg_T *eap)
     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 @@ f_diff_hlID(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
            || 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;
index f3838572c31df0b71d7785aed97ea056e1b50963..a6b6317f831340a9c0ee5d4be6f7e5545dca284c 100644 (file)
@@ -1467,10 +1467,13 @@ win_line(
     }
 
 #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 @@ win_line(
                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
 
index 77ddea816b92b31b7285457d3ddd26593feaa433..e3b1e27f4516b72123e1fb87b5aea904b90dee23 100644 (file)
@@ -869,6 +869,7 @@ EXTERN int  drag_sep_line INIT(= FALSE);    // dragging vert separator
 #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 (file)
index 0000000..c1463fd
--- /dev/null
@@ -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];
+}
index 94e34b0eee3a18edcdfe706ef1b1d378b4402ce1..091e09350ca864b9949a779e36d5966ea2fb9cac 100644 (file)
@@ -74,6 +74,7 @@ extern int _stricoll(char *a, char *b);
 # include "debugger.pro"
 # include "dict.pro"
 # include "diff.pro"
+# include "linematch.pro"
 # include "digraph.pro"
 # include "drawline.pro"
 # include "drawscreen.pro"
index 9c34dcfa250a3cadd1a96752ecd81f979cf35b6e..5141e370f28e116b565f296772fd7ae4bc5d7550 100644 (file)
@@ -14,6 +14,7 @@ void diff_win_options(win_T *wp, int addbuf);
 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 (file)
index 0000000..56d0037
--- /dev/null
@@ -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 : */
index b792edcc85fa281845459dd7b21cf68d5cec05dc..c25555f1cdba8037f8d73df082ba9126e5030aba 100644 (file)
@@ -17,6 +17,7 @@ int vim_stricmp(char *s1, char *s2);
 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);
index cd75bc371d768a5de6fb5ce25a84242b27966225..54ac17873f2258d0ee14128c98e51aac3193f14b 100644 (file)
@@ -674,6 +674,22 @@ vim_strchr(char_u *string, int c)
     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
index 87aca3074280e5526c0013b131443ccfb07bf31b..69494dd9b03e575c662564fc57c57acb2c7cce9b 100644 (file)
@@ -3553,6 +3553,8 @@ struct diffblock_S
     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 (file)
index 0000000..25e1750
--- /dev/null
@@ -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 (file)
index 0000000..71004bd
--- /dev/null
@@ -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 (file)
index 0000000..056c4be
--- /dev/null
@@ -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 (file)
index 0000000..f163146
--- /dev/null
@@ -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 (file)
index 0000000..7e78baf
--- /dev/null
@@ -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 (file)
index 0000000..8e9e0c6
--- /dev/null
@@ -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 (file)
index 0000000..1601c5d
--- /dev/null
@@ -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 (file)
index 0000000..9c7d17b
--- /dev/null
@@ -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 (file)
index 0000000..d9b72ad
--- /dev/null
@@ -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 (file)
index 0000000..d4649d2
--- /dev/null
@@ -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 (file)
index 0000000..69737fa
--- /dev/null
@@ -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 (file)
index 0000000..49ab243
--- /dev/null
@@ -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 (file)
index 0000000..cbea3e5
--- /dev/null
@@ -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 (file)
index 0000000..df249ab
--- /dev/null
@@ -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 (file)
index 0000000..cb62a9e
--- /dev/null
@@ -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 (file)
index 0000000..6cd85c9
--- /dev/null
@@ -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 (file)
index 0000000..d203885
--- /dev/null
@@ -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 (file)
index 0000000..b2ca4d1
--- /dev/null
@@ -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 (file)
index 0000000..fa85299
--- /dev/null
@@ -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 (file)
index 0000000..d99744e
--- /dev/null
@@ -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 (file)
index 0000000..3c1674f
--- /dev/null
@@ -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 (file)
index 0000000..e54fe26
--- /dev/null
@@ -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 (file)
index 0000000..26b729c
--- /dev/null
@@ -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 (file)
index 0000000..19c9073
--- /dev/null
@@ -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 (file)
index 0000000..35cf575
--- /dev/null
@@ -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 (file)
index 0000000..35cf575
--- /dev/null
@@ -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 (file)
index 0000000..673b909
--- /dev/null
@@ -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 (file)
index 0000000..0d91732
--- /dev/null
@@ -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 (file)
index 0000000..50803a3
--- /dev/null
@@ -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 (file)
index 0000000..11a489a
--- /dev/null
@@ -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 (file)
index 0000000..71b0848
--- /dev/null
@@ -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 (file)
index 0000000..b88b407
--- /dev/null
@@ -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
index bed795e1ccffb88d949a689c1fa933bcdc3ff58b..1c7233e35a6d4279421d419deca8202a62f540c9 100644 (file)
@@ -1035,6 +1035,41 @@ func Test_diff_screen()
   call WriteDiffFiles(buf, [], [0])
   call VerifyBoth(buf, "Test_diff_22", "")
 
+  call WriteDiffFiles(buf, ['?a', '?b', '?c'], ['!b'])
+  call VerifyInternal(buf, 'Test_diff_23', " diffopt+=linematch:30")
+
+  call WriteDiffFiles(buf, ['',
+      \ 'common line',
+      \ 'common line',
+      \ '',
+      \ 'DEFabc',
+      \ 'xyz',
+      \ 'xyz',
+      \ 'xyz',
+      \ 'DEFabc',
+      \ 'DEFabc',
+      \ 'DEFabc',
+      \ 'common line',
+      \ 'common line',
+      \ 'DEF',
+      \ 'common line',
+      \ 'DEF',
+      \ 'something' ],
+      \ ['',
+      \ 'common line',
+      \ 'common line',
+      \ '',
+      \ 'ABCabc',
+      \ 'ABCabc',
+      \ 'ABCabc',
+      \ 'ABCabc',
+      \ 'common line',
+      \ 'common line',
+      \ 'common line',
+      \ 'something'])
+  call VerifyInternal(buf, 'Test_diff_24', " diffopt+=linematch:30")
+
+
   " clean up
   call StopVimInTerminal(buf)
   call delete('Xdifile1')
@@ -2285,4 +2320,411 @@ func Test_diff_topline_noscroll()
   call StopVimInTerminal(buf)
 endfunc
 
+func Test_diffget_diffput_linematch()
+  CheckScreendump
+  call delete('.Xdifile1.swp')
+  call delete('.Xdifile2.swp')
+  call WriteDiffFiles(0, [], [])
+  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
+  call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
+
+  " enable linematch
+  call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
+  call WriteDiffFiles(buf, ['',
+      \ 'common line',
+      \ 'common line',
+      \ '',
+      \ 'ABCabc',
+      \ 'ABCabc',
+      \ 'ABCabc',
+      \ 'ABCabc',
+      \ 'common line',
+      \ 'common line',
+      \ 'common line',
+      \ 'something' ],
+      \ ['',
+      \ 'common line',
+      \ 'common line',
+      \ '',
+      \ 'DEFabc',
+      \ 'xyz',
+      \ 'xyz',
+      \ 'xyz',
+      \ 'DEFabc',
+      \ 'DEFabc',
+      \ 'DEFabc',
+      \ 'common line',
+      \ 'common line',
+      \ 'DEF',
+      \ 'common line',
+      \ 'DEF',
+      \ 'something'])
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_1', {})
+
+  " get from window 1 from line 5 to 9
+  call term_sendkeys(buf, "1\<c-w>w")
+  call term_sendkeys(buf, ":5,9diffget\<CR>")
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_2', {})
+
+  " undo the last diffget
+  call term_sendkeys(buf, "u")
+
+  " get from window 2 from line 5 to 10
+  call term_sendkeys(buf, "2\<c-w>w")
+  call term_sendkeys(buf, ":5,10diffget\<CR>")
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_3', {})
+
+  " undo the last diffget
+  call term_sendkeys(buf, "u")
+
+  " get all from window 2
+  call term_sendkeys(buf, "2\<c-w>w")
+  call term_sendkeys(buf, ":4,17diffget\<CR>")
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_4', {})
+
+  " undo the last diffget
+  call term_sendkeys(buf, "u")
+
+  " get all from window 1
+  call term_sendkeys(buf, "1\<c-w>w")
+  call term_sendkeys(buf, ":4,12diffget\<CR>")
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_5', {})
+
+  " undo the last diffget
+  call term_sendkeys(buf, "u")
+
+  " get from window 1 using do 1 line 5
+  call term_sendkeys(buf, "1\<c-w>w")
+  call term_sendkeys(buf, "5gg")
+  call term_sendkeys(buf, ":diffget\<CR>")
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_6', {})
+
+  " undo the last diffget
+  call term_sendkeys(buf, "u")
+
+  " get from window 1 using do 2 line 6
+  call term_sendkeys(buf, "1\<c-w>w")
+  call term_sendkeys(buf, "6gg")
+  call term_sendkeys(buf, ":diffget\<CR>")
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_7', {})
+
+  " undo the last diffget
+  call term_sendkeys(buf, "u")
+
+  " get from window 1 using do 2 line 7
+  call term_sendkeys(buf, "1\<c-w>w")
+  call term_sendkeys(buf, "7gg")
+  call term_sendkeys(buf, ":diffget\<CR>")
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_8', {})
+
+  " undo the last diffget
+  call term_sendkeys(buf, "u")
+
+  " get from window 1 using do 2 line 11
+  call term_sendkeys(buf, "1\<c-w>w")
+  call term_sendkeys(buf, "11gg")
+  call term_sendkeys(buf, ":diffget\<CR>")
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_9', {})
+
+  " undo the last diffget
+  call term_sendkeys(buf, "u")
+
+  " get from window 1 using do 2 line 12
+  call term_sendkeys(buf, "1\<c-w>w")
+  call term_sendkeys(buf, "12gg")
+  call term_sendkeys(buf, ":diffget\<CR>")
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_10', {})
+
+  " undo the last diffget
+  call term_sendkeys(buf, "u")
+
+  " put from window 1 using dp 1 line 5
+  call term_sendkeys(buf, "1\<c-w>w")
+  call term_sendkeys(buf, "5gg")
+  call term_sendkeys(buf, ":diffput\<CR>")
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_11', {})
+
+  " undo the last diffput
+  call term_sendkeys(buf, "2\<c-w>w")
+  call term_sendkeys(buf, "u")
+
+  " put from window 1 using dp 2 line 6
+  call term_sendkeys(buf, "1\<c-w>w")
+  call term_sendkeys(buf, "6gg")
+  call term_sendkeys(buf, ":diffput\<CR>")
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_12', {})
+
+  " undo the last diffput
+  call term_sendkeys(buf, "2\<c-w>w")
+  call term_sendkeys(buf, "u")
+
+  " put from window 1 using dp 2 line 7
+  call term_sendkeys(buf, "1\<c-w>w")
+  call term_sendkeys(buf, "7gg")
+  call term_sendkeys(buf, ":diffput\<CR>")
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_13', {})
+
+  " undo the last diffput
+  call term_sendkeys(buf, "2\<c-w>w")
+  call term_sendkeys(buf, "u")
+
+  " put from window 1 using dp 2 line 11
+  call term_sendkeys(buf, "1\<c-w>w")
+  call term_sendkeys(buf, "11gg")
+  call term_sendkeys(buf, ":diffput\<CR>")
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_14', {})
+
+  " undo the last diffput
+  call term_sendkeys(buf, "2\<c-w>w")
+  call term_sendkeys(buf, "u")
+
+  " put from window 1 using dp 2 line 12
+  call term_sendkeys(buf, "1\<c-w>w")
+  call term_sendkeys(buf, "12gg")
+  call term_sendkeys(buf, ":diffput\<CR>")
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_15', {})
+
+  " undo the last diffput
+  call term_sendkeys(buf, "2\<c-w>w")
+  call term_sendkeys(buf, "u")
+
+  " put from window 2 using dp line 6
+  call term_sendkeys(buf, "2\<c-w>w")
+  call term_sendkeys(buf, "6gg")
+  call term_sendkeys(buf, ":diffput\<CR>")
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_16', {})
+
+  " undo the last diffput
+  call term_sendkeys(buf, "1\<c-w>w")
+  call term_sendkeys(buf, "u")
+
+  " put from window 2 using dp line 8
+  call term_sendkeys(buf, "2\<c-w>w")
+  call term_sendkeys(buf, "8gg")
+  call term_sendkeys(buf, ":diffput\<CR>")
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_17', {})
+
+  " undo the last diffput
+  call term_sendkeys(buf, "1\<c-w>w")
+  call term_sendkeys(buf, "u")
+
+  " put from window 2 using dp line 9
+  call term_sendkeys(buf, "2\<c-w>w")
+  call term_sendkeys(buf, "9gg")
+  call term_sendkeys(buf, ":diffput\<CR>")
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_18', {})
+
+  " undo the last diffput
+  call term_sendkeys(buf, "1\<c-w>w")
+  call term_sendkeys(buf, "u")
+
+  " put from window 2 using dp line 17
+  call term_sendkeys(buf, "2\<c-w>w")
+  call term_sendkeys(buf, "17gg")
+  call term_sendkeys(buf, ":diffput\<CR>")
+  call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_19', {})
+
+endfunc
+
+func Test_linematch_diff()
+  CheckScreendump
+  call delete('.Xdifile1.swp')
+  call delete('.Xdifile2.swp')
+  call WriteDiffFiles(0, [], [])
+  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
+  call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
+
+  " enable linematch
+  call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
+  call WriteDiffFiles(buf, ['// abc d?',
+      \ '// d?',
+      \ '// d?' ],
+      \ ['!',
+      \ 'abc d!',
+      \ 'd!'])
+  call VerifyScreenDump(buf, 'Test_linematch_diff1', {})
+
+endfunc
+
+func Test_linematch_diff_iwhite()
+  CheckScreendump
+  call delete('.Xdifile1.swp')
+  call delete('.Xdifile2.swp')
+  call WriteDiffFiles(0, [], [])
+  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
+  call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
+
+  " setup a diff with 2 files and set linematch:30, with ignore white
+  call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
+  call WriteDiffFiles(buf, ['void testFunction () {',
+      \ '  for (int i = 0; i < 10; i++) {',
+      \ '    for (int j = 0; j < 10; j++) {',
+      \ '    }',
+      \ '  }',
+      \ '}' ],
+      \ ['void testFunction () {',
+      \ '  // for (int j = 0; j < 10; i++) {',
+      \ '  // }',
+      \ '}'])
+  call VerifyScreenDump(buf, 'Test_linematch_diff_iwhite1', {})
+  call term_sendkeys(buf, ":set diffopt+=iwhiteall\<CR>")
+  call VerifyScreenDump(buf, 'Test_linematch_diff_iwhite2', {})
+
+endfunc
+
+func Test_linematch_diff_grouping()
+  CheckScreendump
+  call delete('.Xdifile1.swp')
+  call delete('.Xdifile2.swp')
+  call WriteDiffFiles(0, [], [])
+  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
+  call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
+
+  " a diff that would result in multiple groups before grouping optimization
+  call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
+  call WriteDiffFiles(buf, ['!A',
+      \ '!B',
+      \ '!C' ],
+      \ ['?Z',
+      \ '?A',
+      \ '?B',
+      \ '?C',
+      \ '?A',
+      \ '?B',
+      \ '?B',
+      \ '?C'])
+  call VerifyScreenDump(buf, 'Test_linematch_diff_grouping1', {})
+  call WriteDiffFiles(buf, ['!A',
+      \ '!B',
+      \ '!C' ],
+      \ ['?A',
+      \ '?Z',
+      \ '?B',
+      \ '?C',
+      \ '?A',
+      \ '?B',
+      \ '?C',
+      \ '?C'])
+  call VerifyScreenDump(buf, 'Test_linematch_diff_grouping2', {})
+
+endfunc
+
+func Test_linematch_diff_scroll()
+  CheckScreendump
+  call delete('.Xdifile1.swp')
+  call delete('.Xdifile2.swp')
+  call WriteDiffFiles(0, [], [])
+  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
+  call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
+
+  " a diff that would result in multiple groups before grouping optimization
+  call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
+  call WriteDiffFiles(buf, ['!A',
+      \ '!B',
+      \ '!C' ],
+      \ ['?A',
+      \ '?Z',
+      \ '?B',
+      \ '?C',
+      \ '?A',
+      \ '?B',
+      \ '?C',
+      \ '?C'])
+  " scroll down to show calculation of top fill and scroll to correct line in
+  " both windows
+  call VerifyScreenDump(buf, 'Test_linematch_diff_grouping_scroll0', {})
+  call term_sendkeys(buf, "3\<c-e>")
+  call VerifyScreenDump(buf, 'Test_linematch_diff_grouping_scroll1', {})
+  call term_sendkeys(buf, "3\<c-e>")
+  call VerifyScreenDump(buf, 'Test_linematch_diff_grouping_scroll2', {})
+
+endfunc
+
+
+
+func Test_linematch_line_limit_exceeded()
+  CheckScreendump
+  call delete('.Xdifile1.swp')
+  call delete('.Xdifile2.swp')
+  call WriteDiffFiles(0, [], [])
+  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
+  call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
+
+  call term_sendkeys(buf, ":set diffopt+=linematch:10\<CR>")
+  " a diff block will not be aligned with linematch because it's contents
+  " exceed 10 lines
+  call WriteDiffFiles(buf,
+        \ ['common line',
+        \ 'HIL',
+        \ '',
+        \ 'aABCabc',
+        \ 'aABCabc',
+        \ 'aABCabc',
+        \ 'aABCabc',
+        \ 'common line',
+        \ 'HIL',
+        \ 'common line',
+        \ 'something'],
+        \ ['common line',
+        \ 'DEF',
+        \ 'GHI',
+        \ 'something',
+        \ '',
+        \ 'aDEFabc',
+        \ 'xyz',
+        \ 'xyz',
+        \ 'xyz',
+        \ 'aDEFabc',
+        \ 'aDEFabc',
+        \ 'aDEFabc',
+        \ 'common line',
+        \ 'DEF',
+        \ 'GHI',
+        \ 'something else',
+        \ 'common line',
+        \ 'something'])
+  call VerifyScreenDump(buf, 'Test_linematch_line_limit_exceeded1', {})
+  " after increasing the count to 30, the limit is not exceeded, and the
+  " alignment algorithm will run on the largest diff block here
+  call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
+  call VerifyScreenDump(buf, 'Test_linematch_line_limit_exceeded2', {})
+
+endfunc
+
+func Test_linematch_3diffs()
+  CheckScreendump
+  call delete('.Xdifile1.swp')
+  call delete('.Xdifile2.swp')
+  call delete('.Xdifile3.swp')
+  call WriteDiffFiles3(0, [], [], [])
+  let buf = RunVimInTerminal('-d Xdifile1 Xdifile2 Xdifile3', {})
+  call term_sendkeys(buf, "1\<c-w>w:set autoread\<CR>")
+  call term_sendkeys(buf, "2\<c-w>w:set autoread\<CR>")
+  call term_sendkeys(buf, "3\<c-w>w:set autoread\<CR>")
+  call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
+  call WriteDiffFiles3(buf,
+        \ ["",
+        \ "  common line",
+        \ "      AAA",
+        \ "      AAA",
+        \ "      AAA"],
+        \ ["",
+        \ "  common line",
+        \ "  <<<<<<< HEAD",
+        \ "      AAA",
+        \ "      AAA",
+        \ "      AAA",
+        \ "  =======",
+        \ "      BBB",
+        \ "      BBB",
+        \ "      BBB",
+        \ "  >>>>>>> branch1"],
+        \ ["",
+        \ "  common line",
+        \ "      BBB",
+        \ "      BBB",
+        \ "      BBB"])
+  call VerifyScreenDump(buf, 'Test_linematch_3diffs1', {})
+
+endfunc
 " vim: shiftwidth=2 sts=2 expandtab
index 858034e6eaaac51f2c9d3bf6b5a8ae57008579f8..19c08b9f796f7c106e2d2c2adb2af5490a175d3b 100644 (file)
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1009,
 /**/
     1008,
 /**/
index 25c9d120d8ef2e2fbf3a597ebf99099bce4c5415..1cf7648215da1d56bfcaecaac7a43108c93ade5f 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -1992,6 +1992,7 @@ typedef int sock_T;
 // 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"