OSDN Git Service

PATCH: [ 1525417 ] Move MovedBlock code to own file
authorKimmo Varis <kimmov@gmail.com>
Thu, 20 Jul 2006 06:54:23 +0000 (06:54 +0000)
committerKimmo Varis <kimmov@gmail.com>
Thu, 20 Jul 2006 06:54:23 +0000 (06:54 +0000)
Src/Changes.txt
Src/DiffWrapper.cpp
Src/Merge.dsp
Src/MovedBlocks.cpp [new file with mode: 0644]

index e4f5256..0fae832 100644 (file)
@@ -5,6 +5,9 @@ Add new items to top.
 2006-07-20 Kimmo
  PATCH: [ 1525013 ] Add description for ASP.NET filter
   Filters: ASPNET.flt
+ PATCH: [ 1525417 ] Move MovedBlock code to own file
+  Src: DiffWrapper.cpp Merge.dsp
+  Src new file: MovedBlocks.cpp
 
 2006-07-19 Kimmo
  BUG: [ 1198248 ] version copyright symbol needs review
index fa76e40..141facf 100644 (file)
@@ -1498,355 +1498,6 @@ DiffFileData::UniFileBom::UniFileBom(int fd)
        _lseek(fd, tmp, SEEK_SET);
 }
 
-/** @brief Create int array with size elements, and set initial entries to initvalue */
-#if 0
-static int * NewIntArray(int size, int initvalue)
-{
-       int * arr = new int[size];
-       for (int i=0; i<size; ++i)
-               arr[i] = initvalue;
-       return arr;
-}
-#endif
-
-class IntSet
-{
-public:
-       void Add(int val) { m_map.SetAt(val, 1); }
-       void Remove(int val) { m_map.RemoveKey(val); }
-       int count() const { return m_map.GetCount(); }
-       bool isPresent(int val) const { int parm; return !!m_map.Lookup(val, parm); }
-       int getSingle() const 
-       {
-               int val, parm;
-               POSITION pos = m_map.GetStartPosition();
-               m_map.GetNextAssoc(pos, val, parm); 
-               return val; 
-       }
-
-private:
-       CMap<int, int, int, int> m_map;
-};
-
-/** 
- * @brief  Set of equivalent lines
- * This uses diffutils line numbers, which are counted from the prefix
- */
-struct EqGroup
-{
-       IntSet m_lines0; // equivalent lines on side#0
-       IntSet m_lines1; // equivalent lines on side#1
-
-       bool isPerfectMatch() const { return m_lines0.count()==1 && m_lines1.count()==1; }
-};
-
-
-/** @brief  Maps equivalency code to equivalency group */
-class CodeToGroupMap : public CTypedPtrMap<CMapPtrToPtr, void*, EqGroup *>
-{
-public:
-       /** @brief Add a line to the appropriate equivalency group */
-       void Add(int lineno, int eqcode, int nside)
-       {
-               EqGroup * pgroup = 0;
-               if (!Lookup((void *)eqcode, pgroup))
-               {
-                       pgroup = new EqGroup;
-                       SetAt((void *)eqcode, pgroup);
-               }
-               if (nside)
-                       pgroup->m_lines1.Add(lineno);
-               else
-                       pgroup->m_lines0.Add(lineno);
-       }
-
-       /** @brief Return the appropriate equivalency group */
-       EqGroup * find(int eqcode)
-       {
-               EqGroup * pgroup=0;
-               Lookup((void *)eqcode, pgroup);
-               return pgroup;
-       }
-
-       ~CodeToGroupMap()
-       {
-               for (POSITION pos = GetStartPosition(); pos; )
-               {
-                       void * v=0;
-                       EqGroup * pgroup=0;
-                       GetNextAssoc(pos, v, pgroup);
-                       delete pgroup;
-               }
-       }
-};
-
-/*
- WinMerge moved block code
- This is called by diffutils code, by diff_2_files routine
- read_files earlier computed the hash chains ("equivs" file variable) and freed them,
- but the equivs numerics are still available in each line
-
- match1 set by scan from line0 to deleted
- match0 set by scan from line1 to inserted
-
-*/
-extern "C" void moved_block_analysis(struct change ** pscript, struct file_data fd[])
-{
-       // Hash all altered lines
-       CodeToGroupMap map;
-
-       struct change * script = *pscript;
-       struct change *p,*e;
-       for (e = script; e; e = p)
-       {
-               p = e->link;
-               int i=0;
-               for (i=e->line0; i-(e->line0) < (e->deleted); ++i)
-                       map.Add(i, fd[0].equivs[i], 0);
-               for (i=e->line1; i-(e->line1) < (e->inserted); ++i)
-                       map.Add(i, fd[1].equivs[i], 1);
-       }
-
-
-       // Scan through diff blocks, finding moved sections from left side
-       // and splitting them out
-       // That is, we actually fragment diff blocks as we find moved sections
-       for (e = script; e; e = p)
-       {
-               // scan down block for a match
-               p = e->link;
-               EqGroup * pgroup = 0;
-               int i=0;
-               for (i=e->line0; i-(e->line0) < (e->deleted); ++i)
-               {
-                       EqGroup * tempgroup = map.find(fd[0].equivs[i]);
-                       if (tempgroup->isPerfectMatch())
-                       {
-                               pgroup = tempgroup;
-                               break;
-                       }
-               }
-
-               // if no match, go to next diff block
-               if (!pgroup)
-                       continue;
-
-               // found a match
-               int j = pgroup->m_lines1.getSingle();
-               // Ok, now our moved block is the single line i,j
-
-               // extend moved block upward as far as possible
-               int i1 = i-1;
-               int j1 = j-1;
-               for ( ; i1>=e->line0; --i1, --j1)
-               {
-                       EqGroup * pgroup0 = map.find(fd[0].equivs[i1]);
-                       EqGroup * pgroup1 = map.find(fd[1].equivs[j1]);
-                       if (pgroup0 != pgroup1)
-                               break;
-                       pgroup0->m_lines0.Remove(i1);
-                       pgroup1->m_lines1.Remove(j1);
-               }
-               ++i1;
-               ++j1;
-               // Ok, now our moved block is i1->i, j1->j
-
-               // extend moved block downward as far as possible
-               int i2 = i+1;
-               int j2 = j+1;
-               for ( ; i2-(e->line0) < (e->deleted); ++i2,++j2)
-               {
-                       EqGroup * pgroup0 = map.find(fd[0].equivs[i2]);
-                       EqGroup * pgroup1 = map.find(fd[1].equivs[j2]);
-                       if (pgroup0 != pgroup1)
-                               break;
-                       pgroup0->m_lines0.Remove(i2);
-                       pgroup1->m_lines1.Remove(j2);
-               }
-               --i2;
-               --j2;
-               // Ok, now our moved block is i1->i2,j1->j2
-
-               ASSERT(i2-i1 >= 0);
-               ASSERT(i2-i1 == j2-j1);
-
-               int prefix = i1 - (e->line0);
-               if (prefix)
-               {
-                       // break e (current change) into two pieces
-                       // first part is the prefix, before the moved part
-                       // that stays in e
-                       // second part is the moved part & anything after it
-                       // that goes in newob
-                       // leave the right side (e->inserted) on e
-                       // so no right side on newob
-                       // newob will be the moved part only, later after we split off any suffix from it
-                       struct change *newob = (struct change *) xmalloc (sizeof (struct change));
-                       memset(newob, 0, sizeof(*newob));
-
-                       newob->line0 = i1;
-                       newob->line1 = e->line1 + e->inserted;
-                       newob->inserted = 0;
-                       newob->deleted = e->deleted - prefix;
-                       newob->link = e->link;
-                       newob->match0 = -1;
-                       newob->match1 = -1;
-
-                       e->deleted = prefix;
-                       e->link = newob;
-
-                       // now make e point to the moved part (& any suffix)
-                       e = newob;
-               }
-               // now e points to a moved diff chunk with no prefix, but maybe a suffix
-
-               e->match1 = j1;
-
-               int suffix = (e->deleted) - (i2-(e->line0)) - 1;
-               if (suffix)
-               {
-                       // break off any suffix from e
-                       // newob will be the suffix, and will get all the right side
-                       struct change *newob = (struct change *) xmalloc (sizeof (struct change));
-                       memset(newob, 0, sizeof(*newob));
-
-                       newob->line0 = i2+1;
-                       newob->line1 = e->line1;
-                       newob->inserted = e->inserted;
-                       newob->deleted = suffix;
-                       newob->link = e->link;
-                       newob->match0 = -1;
-                       newob->match1 = -1;
-
-                       e->inserted = 0;
-                       e->deleted -= suffix;
-                       e->link = newob;
-
-                       p = newob; // next block to scan
-               }
-       }
-
-       // Scan through diff blocks, finding moved sections from right side
-       // and splitting them out
-       // That is, we actually fragment diff blocks as we find moved sections
-       for (e = script; e; e = p)
-       {
-               // scan down block for a match
-               p = e->link;
-               EqGroup * pgroup = 0;
-               int j=0;
-               for (j=e->line1; j-(e->line1) < (e->inserted); ++j)
-               {
-                       EqGroup * tempgroup = map.find(fd[1].equivs[j]);
-                       if (tempgroup->isPerfectMatch())
-                       {
-                               pgroup = tempgroup;
-                               break;
-                       }
-               }
-
-               // if no match, go to next diff block
-               if (!pgroup)
-                       continue;
-
-               // found a match
-               int i = pgroup->m_lines0.getSingle();
-               // Ok, now our moved block is the single line i,j
-
-               // extend moved block upward as far as possible
-               int i1 = i-1;
-               int j1 = j-1;
-               for ( ; j1>=e->line1; --i1, --j1)
-               {
-                       EqGroup * pgroup0 = map.find(fd[0].equivs[i1]);
-                       EqGroup * pgroup1 = map.find(fd[1].equivs[j1]);
-                       if (pgroup0 != pgroup1)
-                               break;
-                       pgroup0->m_lines0.Remove(i1);
-                       pgroup1->m_lines1.Remove(j1);
-               }
-               ++i1;
-               ++j1;
-               // Ok, now our moved block is i1->i, j1->j
-
-               // extend moved block downward as far as possible
-               int i2 = i+1;
-               int j2 = j+1;
-               for ( ; j2-(e->line1) < (e->inserted); ++i2,++j2)
-               {
-                       EqGroup * pgroup0 = map.find(fd[0].equivs[i2]);
-                       EqGroup * pgroup1 = map.find(fd[1].equivs[j2]);
-                       if (pgroup0 != pgroup1)
-                               break;
-                       pgroup0->m_lines0.Remove(i2);
-                       pgroup1->m_lines1.Remove(j2);
-               }
-               --i2;
-               --j2;
-               // Ok, now our moved block is i1->i2,j1->j2
-
-               ASSERT(i2-i1 >= 0);
-               ASSERT(i2-i1 == j2-j1);
-
-               int prefix = j1 - (e->line1);
-               if (prefix)
-               {
-                       // break e (current change) into two pieces
-                       // first part is the prefix, before the moved part
-                       // that stays in e
-                       // second part is the moved part & anything after it
-                       // that goes in newob
-                       // leave the left side (e->deleted) on e
-                       // so no right side on newob
-                       // newob will be the moved part only, later after we split off any suffix from it
-                       struct change *newob = (struct change *) xmalloc (sizeof (struct change));
-                       memset(newob, 0, sizeof(*newob));
-
-                       newob->line0 = e->line0 + e->deleted;
-                       newob->line1 = j1;
-                       newob->inserted = e->inserted - prefix;
-                       newob->deleted = 0;
-                       newob->link = e->link;
-                       newob->match0 = -1;
-                       newob->match1 = -1;
-
-                       e->inserted = prefix;
-                       e->link = newob;
-
-                       // now make e point to the moved part (& any suffix)
-                       e = newob;
-               }
-               // now e points to a moved diff chunk with no prefix, but maybe a suffix
-
-               e->match0 = i1;
-
-               int suffix = (e->inserted) - (j2-(e->line1)) - 1;
-               if (suffix)
-               {
-                       // break off any suffix from e
-                       // newob will be the suffix, and will get all the left side
-                       struct change *newob = (struct change *) xmalloc (sizeof (struct change));
-                       memset(newob, 0, sizeof(*newob));
-
-                       newob->line0 = e->line0;
-                       newob->line1 = j2+1;
-                       newob->inserted = suffix;
-                       newob->deleted = e->deleted;
-                       newob->link = e->link;
-                       newob->match0 = -1;
-                       newob->match1 = e->match1;
-
-                       e->inserted -= suffix;
-                       e->deleted = 0;
-                       e->match1 = -1;
-                       e->link = newob;
-
-                       p = newob; // next block to scan
-               }
-       }
-
-}
-
 /**
  * @brief Invoke appropriate plugins for unpacking
  * return false if anything fails
index 1fb84ac..9e95afe 100644 (file)
@@ -574,6 +574,10 @@ SOURCE=.\Common\MessageBoxDialog.cpp
 # End Source File
 # Begin Source File
 
+SOURCE=.\MovedBlocks.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\Common\multiformatText.cpp
 # End Source File
 # Begin Source File
diff --git a/Src/MovedBlocks.cpp b/Src/MovedBlocks.cpp
new file mode 100644 (file)
index 0000000..6ab1265
--- /dev/null
@@ -0,0 +1,365 @@
+/////////////////////////////////////////////////////////////////////////////
+//    License (GPLv2+):
+//    This program is free software; you can redistribute it and/or modify
+//    it under the terms of the GNU General Public License as published by
+//    the Free Software Foundation; either version 2 of the License, or (at
+//    your option) any later version.
+//    
+//    This program is distributed in the hope that it will be useful, but
+//    WITHOUT ANY WARRANTY; without even the implied warranty of
+//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//    GNU General Public License for more details.
+//
+//    You should have received a copy of the GNU General Public License
+//    along with this program; if not, write to the Free Software
+//    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+/////////////////////////////////////////////////////////////////////////////
+/** 
+ * @file  MovedBlocks.cpp
+ *
+ * @brief Moved block detection code.
+ */
+// RCS ID line follows -- this is updated by CVS
+// $Id$
+
+#include "stdafx.h"
+#include "diff.h"
+
+
+class IntSet
+{
+public:
+       void Add(int val) { m_map.SetAt(val, 1); }
+       void Remove(int val) { m_map.RemoveKey(val); }
+       int count() const { return m_map.GetCount(); }
+       bool isPresent(int val) const { int parm; return !!m_map.Lookup(val, parm); }
+       int getSingle() const 
+       {
+               int val, parm;
+               POSITION pos = m_map.GetStartPosition();
+               m_map.GetNextAssoc(pos, val, parm); 
+               return val; 
+       }
+
+private:
+       CMap<int, int, int, int> m_map;
+};
+
+/** 
+ * @brief  Set of equivalent lines
+ * This uses diffutils line numbers, which are counted from the prefix
+ */
+struct EqGroup
+{
+       IntSet m_lines0; // equivalent lines on side#0
+       IntSet m_lines1; // equivalent lines on side#1
+
+       bool isPerfectMatch() const { return m_lines0.count()==1 && m_lines1.count()==1; }
+};
+
+
+/** @brief  Maps equivalency code to equivalency group */
+class CodeToGroupMap : public CTypedPtrMap<CMapPtrToPtr, void*, EqGroup *>
+{
+public:
+       /** @brief Add a line to the appropriate equivalency group */
+       void Add(int lineno, int eqcode, int nside)
+       {
+               EqGroup * pgroup = 0;
+               if (!Lookup((void *)eqcode, pgroup))
+               {
+                       pgroup = new EqGroup;
+                       SetAt((void *)eqcode, pgroup);
+               }
+               if (nside)
+                       pgroup->m_lines1.Add(lineno);
+               else
+                       pgroup->m_lines0.Add(lineno);
+       }
+
+       /** @brief Return the appropriate equivalency group */
+       EqGroup * find(int eqcode)
+       {
+               EqGroup * pgroup=0;
+               Lookup((void *)eqcode, pgroup);
+               return pgroup;
+       }
+
+       ~CodeToGroupMap()
+       {
+               for (POSITION pos = GetStartPosition(); pos; )
+               {
+                       void * v=0;
+                       EqGroup * pgroup=0;
+                       GetNextAssoc(pos, v, pgroup);
+                       delete pgroup;
+               }
+       }
+};
+
+/*
+ WinMerge moved block code
+ This is called by diffutils code, by diff_2_files routine (in ANALYZE.C)
+ read_files earlier computed the hash chains ("equivs" file variable) and freed them,
+ but the equivs numerics are still available in each line
+
+ match1 set by scan from line0 to deleted
+ match0 set by scan from line1 to inserted
+
+*/
+extern "C" void moved_block_analysis(struct change ** pscript, struct file_data fd[])
+{
+       // Hash all altered lines
+       CodeToGroupMap map;
+
+       struct change * script = *pscript;
+       struct change *p,*e;
+       for (e = script; e; e = p)
+       {
+               p = e->link;
+               int i=0;
+               for (i=e->line0; i-(e->line0) < (e->deleted); ++i)
+                       map.Add(i, fd[0].equivs[i], 0);
+               for (i=e->line1; i-(e->line1) < (e->inserted); ++i)
+                       map.Add(i, fd[1].equivs[i], 1);
+       }
+
+
+       // Scan through diff blocks, finding moved sections from left side
+       // and splitting them out
+       // That is, we actually fragment diff blocks as we find moved sections
+       for (e = script; e; e = p)
+       {
+               // scan down block for a match
+               p = e->link;
+               EqGroup * pgroup = 0;
+               int i=0;
+               for (i=e->line0; i-(e->line0) < (e->deleted); ++i)
+               {
+                       EqGroup * tempgroup = map.find(fd[0].equivs[i]);
+                       if (tempgroup->isPerfectMatch())
+                       {
+                               pgroup = tempgroup;
+                               break;
+                       }
+               }
+
+               // if no match, go to next diff block
+               if (!pgroup)
+                       continue;
+
+               // found a match
+               int j = pgroup->m_lines1.getSingle();
+               // Ok, now our moved block is the single line i,j
+
+               // extend moved block upward as far as possible
+               int i1 = i-1;
+               int j1 = j-1;
+               for ( ; i1>=e->line0; --i1, --j1)
+               {
+                       EqGroup * pgroup0 = map.find(fd[0].equivs[i1]);
+                       EqGroup * pgroup1 = map.find(fd[1].equivs[j1]);
+                       if (pgroup0 != pgroup1)
+                               break;
+                       pgroup0->m_lines0.Remove(i1);
+                       pgroup1->m_lines1.Remove(j1);
+               }
+               ++i1;
+               ++j1;
+               // Ok, now our moved block is i1->i, j1->j
+
+               // extend moved block downward as far as possible
+               int i2 = i+1;
+               int j2 = j+1;
+               for ( ; i2-(e->line0) < (e->deleted); ++i2,++j2)
+               {
+                       EqGroup * pgroup0 = map.find(fd[0].equivs[i2]);
+                       EqGroup * pgroup1 = map.find(fd[1].equivs[j2]);
+                       if (pgroup0 != pgroup1)
+                               break;
+                       pgroup0->m_lines0.Remove(i2);
+                       pgroup1->m_lines1.Remove(j2);
+               }
+               --i2;
+               --j2;
+               // Ok, now our moved block is i1->i2,j1->j2
+
+               ASSERT(i2-i1 >= 0);
+               ASSERT(i2-i1 == j2-j1);
+
+               int prefix = i1 - (e->line0);
+               if (prefix)
+               {
+                       // break e (current change) into two pieces
+                       // first part is the prefix, before the moved part
+                       // that stays in e
+                       // second part is the moved part & anything after it
+                       // that goes in newob
+                       // leave the right side (e->inserted) on e
+                       // so no right side on newob
+                       // newob will be the moved part only, later after we split off any suffix from it
+                       struct change *newob = (struct change *) xmalloc (sizeof (struct change));
+                       memset(newob, 0, sizeof(*newob));
+
+                       newob->line0 = i1;
+                       newob->line1 = e->line1 + e->inserted;
+                       newob->inserted = 0;
+                       newob->deleted = e->deleted - prefix;
+                       newob->link = e->link;
+                       newob->match0 = -1;
+                       newob->match1 = -1;
+
+                       e->deleted = prefix;
+                       e->link = newob;
+
+                       // now make e point to the moved part (& any suffix)
+                       e = newob;
+               }
+               // now e points to a moved diff chunk with no prefix, but maybe a suffix
+
+               e->match1 = j1;
+
+               int suffix = (e->deleted) - (i2-(e->line0)) - 1;
+               if (suffix)
+               {
+                       // break off any suffix from e
+                       // newob will be the suffix, and will get all the right side
+                       struct change *newob = (struct change *) xmalloc (sizeof (struct change));
+                       memset(newob, 0, sizeof(*newob));
+
+                       newob->line0 = i2+1;
+                       newob->line1 = e->line1;
+                       newob->inserted = e->inserted;
+                       newob->deleted = suffix;
+                       newob->link = e->link;
+                       newob->match0 = -1;
+                       newob->match1 = -1;
+
+                       e->inserted = 0;
+                       e->deleted -= suffix;
+                       e->link = newob;
+
+                       p = newob; // next block to scan
+               }
+       }
+
+       // Scan through diff blocks, finding moved sections from right side
+       // and splitting them out
+       // That is, we actually fragment diff blocks as we find moved sections
+       for (e = script; e; e = p)
+       {
+               // scan down block for a match
+               p = e->link;
+               EqGroup * pgroup = 0;
+               int j=0;
+               for (j=e->line1; j-(e->line1) < (e->inserted); ++j)
+               {
+                       EqGroup * tempgroup = map.find(fd[1].equivs[j]);
+                       if (tempgroup->isPerfectMatch())
+                       {
+                               pgroup = tempgroup;
+                               break;
+                       }
+               }
+
+               // if no match, go to next diff block
+               if (!pgroup)
+                       continue;
+
+               // found a match
+               int i = pgroup->m_lines0.getSingle();
+               // Ok, now our moved block is the single line i,j
+
+               // extend moved block upward as far as possible
+               int i1 = i-1;
+               int j1 = j-1;
+               for ( ; j1>=e->line1; --i1, --j1)
+               {
+                       EqGroup * pgroup0 = map.find(fd[0].equivs[i1]);
+                       EqGroup * pgroup1 = map.find(fd[1].equivs[j1]);
+                       if (pgroup0 != pgroup1)
+                               break;
+                       pgroup0->m_lines0.Remove(i1);
+                       pgroup1->m_lines1.Remove(j1);
+               }
+               ++i1;
+               ++j1;
+               // Ok, now our moved block is i1->i, j1->j
+
+               // extend moved block downward as far as possible
+               int i2 = i+1;
+               int j2 = j+1;
+               for ( ; j2-(e->line1) < (e->inserted); ++i2,++j2)
+               {
+                       EqGroup * pgroup0 = map.find(fd[0].equivs[i2]);
+                       EqGroup * pgroup1 = map.find(fd[1].equivs[j2]);
+                       if (pgroup0 != pgroup1)
+                               break;
+                       pgroup0->m_lines0.Remove(i2);
+                       pgroup1->m_lines1.Remove(j2);
+               }
+               --i2;
+               --j2;
+               // Ok, now our moved block is i1->i2,j1->j2
+
+               ASSERT(i2-i1 >= 0);
+               ASSERT(i2-i1 == j2-j1);
+
+               int prefix = j1 - (e->line1);
+               if (prefix)
+               {
+                       // break e (current change) into two pieces
+                       // first part is the prefix, before the moved part
+                       // that stays in e
+                       // second part is the moved part & anything after it
+                       // that goes in newob
+                       // leave the left side (e->deleted) on e
+                       // so no right side on newob
+                       // newob will be the moved part only, later after we split off any suffix from it
+                       struct change *newob = (struct change *) xmalloc (sizeof (struct change));
+                       memset(newob, 0, sizeof(*newob));
+
+                       newob->line0 = e->line0 + e->deleted;
+                       newob->line1 = j1;
+                       newob->inserted = e->inserted - prefix;
+                       newob->deleted = 0;
+                       newob->link = e->link;
+                       newob->match0 = -1;
+                       newob->match1 = -1;
+
+                       e->inserted = prefix;
+                       e->link = newob;
+
+                       // now make e point to the moved part (& any suffix)
+                       e = newob;
+               }
+               // now e points to a moved diff chunk with no prefix, but maybe a suffix
+
+               e->match0 = i1;
+
+               int suffix = (e->inserted) - (j2-(e->line1)) - 1;
+               if (suffix)
+               {
+                       // break off any suffix from e
+                       // newob will be the suffix, and will get all the left side
+                       struct change *newob = (struct change *) xmalloc (sizeof (struct change));
+                       memset(newob, 0, sizeof(*newob));
+
+                       newob->line0 = e->line0;
+                       newob->line1 = j2+1;
+                       newob->inserted = suffix;
+                       newob->deleted = e->deleted;
+                       newob->link = e->link;
+                       newob->match0 = -1;
+                       newob->match1 = e->match1;
+
+                       e->inserted -= suffix;
+                       e->deleted = 0;
+                       e->match1 = -1;
+                       e->link = newob;
+
+                       p = newob; // next block to scan
+               }
+       }
+
+}