]> git.lyx.org Git - lyx.git/blobdiff - src/Compare.cpp
Fix for bug #7360. Patch from Nemah, posted to bug report.
[lyx.git] / src / Compare.cpp
index a6d925752af44bda5868192bf914c719129a7bad..f5d1d5476110fd8fe2594b30a793e50528907a88 100644 (file)
 
 #include "BufferParams.h"
 #include "Changes.h"
+#include "Font.h"
 
 #include "insets/InsetText.h"
 
 #include "support/lassert.h"   
+#include "support/qstring_helpers.h"
 
 #include <boost/next_prior.hpp>
 
-#include <cmath>
-
 using namespace std;
 using namespace lyx::support;
 
@@ -219,7 +219,7 @@ class Compare::Impl {
 public:
        ///
        Impl(Compare const & compare) 
-               : abort_(false), compare_(compare)
+               : abort_(false), compare_(compare), recursion_level_(0), D_(0)
        {}
 
        ///
@@ -234,6 +234,14 @@ public:
        /// Set to true to cancel the algorithm
        bool abort_;
 
+       ///
+       QString status() {
+               QString status;
+               status += toqstr("recursion level:") + " " + QString::number(recursion_level_)
+                       + " " + toqstr("differences:") + " " + QString::number(D_);
+               return status;
+       }
+
 private:
        /// Finds the middle snake and returns the length of the
        /// shortest edit script.
@@ -322,6 +330,10 @@ private:
        compl_vector<DocIterator> nrp;
        compl_vector<DocIterator> ors;
        compl_vector<DocIterator> nrs;
+       
+       /// The number of differences in the path the algorithm
+       /// is currently processing.
+       int D_;
 };
 
 /////////////////////////////////////////////////////////////////////
@@ -335,6 +347,15 @@ Compare::Compare(Buffer const * new_buf, Buffer const * old_buf,
        : new_buffer(new_buf), old_buffer(old_buf), dest_buffer(dest_buf),
          options_(options), pimpl_(new Impl(*this))
 {
+       connect(&status_timer_, SIGNAL(timeout()),
+               this, SLOT(doStatusMessage()));
+       status_timer_.start(1000);
+}
+
+
+void Compare::doStatusMessage()
+{
+       statusMessage(pimpl_->status());
 }
 
 
@@ -347,6 +368,8 @@ void Compare::run()
        dest_buffer->params() = options_.settings_from_new
                ? new_buffer->params() : old_buffer->params();
        
+       doStatusMessage();
+
        // do the real work
        if (!doCompare())
                return;
@@ -422,6 +445,13 @@ static bool equal(Inset const * i_o, Inset const * i_n)
 
 
 static bool equal(DocIterator & o, DocIterator & n) {
+       // Explicitly check for this, so we won't call
+       // Paragraph::getChar for the last pos.
+       bool const o_lastpos = o.pos() == o.lastpos();
+       bool const n_lastpos = n.pos() == n.lastpos();
+       if (o_lastpos || n_lastpos)
+               return o_lastpos && n_lastpos;
+
        Paragraph const & old_par = o.text()->getPar(o.pit());
        Paragraph const & new_par = n.text()->getPar(n.pit());
 
@@ -496,6 +526,7 @@ void Compare::Impl::furthestDpathKdiagonal(int D, int k,
        // Where do we take the step from ?
        int const kk = vertical_step ? k + 1 : k - 1;
        DocPair p(op[kk], np[kk]);
+       DocPair const s(os[kk], ns[kk]);
 
        // If D==0 we simulate a vertical step from (0,-1) by doing nothing.
        if (D != 0) {
@@ -517,8 +548,8 @@ void Compare::Impl::furthestDpathKdiagonal(int D, int k,
                ns[k] = p.n;
        } else {
                // Copy last snake from the previous step
-               os[k] = os[kk];
-               ns[k] = ns[kk];
+               os[k] = s.o;
+               ns[k] = s.n;
        }
 
        //Record new position
@@ -601,10 +632,13 @@ int Compare::Impl::findMiddleSnake(DocRangePair const & rp,
        ors.reset(DocIterator());
        nrs.reset(DocIterator());
 
+       // In the formula below, the "+ 1" ensures we round like ceil()
+       int const D_max = (M_ + N_ + 1)/2;
        // D is the number of horizontal and vertical steps, i.e.
        // different characters in the old and new chunk.
-       int const D_max = ceil(((double)M_ + N_)/2);
        for (int D = 0; D <= D_max; ++D) {
+               // to be used in the status messages
+               D_ = D; 
 
                // Forward and reverse paths
                for (int f = 0; f < 2; ++f) {
@@ -625,6 +659,8 @@ int Compare::Impl::findMiddleSnake(DocRangePair const & rp,
                                                return 2 * D - odd_offset_;
                                        }
                                }
+                               if (abort_)
+                                       return 0;
                        }
                }
        }
@@ -656,7 +692,9 @@ bool Compare::Impl::diff(Buffer const * new_buf, Buffer const * old_buf,
        processSnake(snake);
        
        // Start the recursive algorithm
-       diff_i(rp);
+       DocRangePair rp_new(from, rp.to());
+       if (!rp_new.o.empty() || !rp_new.n.empty())
+               diff_i(rp_new);
 
        for (pit_type p = 0; p < (pit_type)dest_pars_->size(); ++p) {
                (*dest_pars_)[p].setBuffer(const_cast<Buffer &>(*dest_buf));
@@ -669,6 +707,9 @@ bool Compare::Impl::diff(Buffer const * new_buf, Buffer const * old_buf,
 
 void Compare::Impl::diff_i(DocRangePair const & rp)
 {
+       if (abort_)
+               return;
+
        // The middle snake
        DocPair middle_snake;