]> git.lyx.org Git - lyx.git/blobdiff - src/BufferView.C
* src/text3.C:
[lyx.git] / src / BufferView.C
index 39c8da3162fa7937a02aed839964b2219a31f679..2935ba27dc66b00f6686c0bb0a509387ba58cfd2 100644 (file)
@@ -197,7 +197,8 @@ void BufferView::setBuffer(Buffer * b)
                }
        }
 
-       update();
+       if (buffer_)
+               updateMetrics(false);    
 
        if (buffer_ && graphics::Previews::status() != LyXRC::PREVIEW_OFF)
                graphics::Previews::get().generateBufferPreviews(*buffer_);
@@ -278,7 +279,9 @@ bool BufferView::loadLyXFile(string const & filename, bool tolastfiles)
                                if (it.pit() == pit) {
                                        // restored pos may be bigger than it->size
                                        setCursor(makeDocIterator(it, min(pos, it->size())));
-                                       update(Update::FitCursor);
+                                       // No need to update the metrics if fitCursor returns false.
+                                       if (fitCursor())
+                                               updateMetrics(false);
                                        break;
                                }
                }
@@ -339,7 +342,7 @@ bool BufferView::multiParSel()
 }
 
 
-bool BufferView::update(Update::flags flags)
+std::pair<bool, bool> BufferView::update(Update::flags flags)
 {
        // This is close to a hot-path.
        if (lyxerr.debugging(Debug::DEBUG)) {
@@ -353,7 +356,7 @@ bool BufferView::update(Update::flags flags)
 
        // Check needed to survive LyX startup
        if (!buffer_)
-               return false;
+               return make_pair(false, false);
 
        if (lyxerr.debugging(Debug::WORKAREA)) {
                lyxerr[Debug::WORKAREA] << "BufferView::update" << std::endl;
@@ -362,15 +365,36 @@ bool BufferView::update(Update::flags flags)
        // Update macro store
        buffer_->buildMacros();
 
-       // First drawing step
-       updateMetrics(flags & Update::SinglePar);
-
+       // Now do the first drawing step if needed. This consists on updating
+       // the CoordCache in updateMetrics().
        // The second drawing step is done in WorkArea::redraw() if needed.
-       bool const need_second_step =
-               (flags & (Update::Force | Update::FitCursor | Update::MultiParSel))
-               && (fitCursor() || multiParSel());
 
-       return need_second_step;
+       // Case when no explicit update is requested.
+       if (!flags) {
+               // no need to do anything.
+               return make_pair(false, false);
+       }
+
+       if (flags == Update::FitCursor) {
+               bool const fit_cursor = fitCursor();
+               if (fit_cursor)
+                       updateMetrics(false);
+               // tell the frontend to update the screen.
+               return make_pair(fit_cursor, false);
+       }
+
+       bool full_metrics = flags & Update::Force;
+       if (flags & Update::MultiParSel)
+               full_metrics |= multiParSel();
+
+       bool const single_par = !full_metrics;
+       updateMetrics(single_par);
+
+       if (flags & Update::FitCursor && fitCursor())
+               updateMetrics(false);
+
+       // tell the frontend to update the screen.
+       return make_pair(true, single_par);
 }
 
 
@@ -460,6 +484,7 @@ void BufferView::scrollDocView(int value)
        t.redoParagraph(*this, anchor_ref_);
        int const h = t.getPar(anchor_ref_).height();
        offset_ref_ = int((bar * t.paragraphs().size() - anchor_ref_) * h);
+       updateMetrics(false);
 }
 
 
@@ -628,7 +653,11 @@ FuncStatus BufferView::getStatus(FuncRequest const & cmd)
        case LFUN_CHANGE_NEXT:
        case LFUN_ALL_CHANGES_ACCEPT:
        case LFUN_ALL_CHANGES_REJECT:
-               flag.enabled(buffer_); // FIXME: Change tracking (MG)
+               // TODO: context-sensitive enabling of LFUNs
+               // In principle, these command should only be enabled if there
+               // is a change in the document. However, without proper
+               // optimizations, this will inevitably result in poor performance.
+               flag.enabled(buffer_);
                break;
 
        case LFUN_BUFFER_TOGGLE_COMPRESSION: {
@@ -727,21 +756,34 @@ bool BufferView::dispatch(FuncRequest const & cmd)
 
        case LFUN_PARAGRAPH_GOTO: {
                int const id = convert<int>(to_utf8(cmd.argument()));
-               ParIterator par = buffer_->getParFromID(id);
-               if (par == buffer_->par_iterator_end()) {
-                       lyxerr[Debug::INFO] << "No matching paragraph found! ["
-                                           << id << ']' << endl;
-                       break;
-               } else {
-                       lyxerr[Debug::INFO] << "Paragraph " << par->id()
-                                           << " found." << endl;
+               int i = 0;
+               for (Buffer * b = buffer_; i == 0 || b != buffer_; b = theBufferList().next(b)) {
+                       ParIterator par = b->getParFromID(id);
+                       if (par == b->par_iterator_end()) {
+                               lyxerr[Debug::INFO]
+                                       << "No matching paragraph found! ["
+                                       << id << "]." << endl;
+                       } else {
+                               lyxerr[Debug::INFO]
+                                       << "Paragraph " << par->id()
+                                       << " found in buffer `"
+                                       << b->fileName() << "'." << endl;
+
+                               if (b == buffer_) {
+                                       // Set the cursor
+                                       setCursor(makeDocIterator(par, 0));
+                                       update();
+                                       switchKeyMap();
+                               } else {
+                                       // Switch to other buffer view and resend cmd
+                                       theLyXFunc().dispatch(FuncRequest(
+                                               LFUN_BUFFER_SWITCH, b->fileName()));
+                                       theLyXFunc().dispatch(cmd);
+                               }
+                               break;
+                       }
+                       ++i;
                }
-
-               // Set the cursor
-               setCursor(makeDocIterator(par, 0));
-
-               update();
-               switchKeyMap();
                break;
        }
 
@@ -993,7 +1035,7 @@ void BufferView::workAreaResize(int width, int height)
 }
 
 
-bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
+std::pair<bool, bool> BufferView::workAreaDispatch(FuncRequest const & cmd0)
 {
        //lyxerr << BOOST_CURRENT_FUNCTION << "[ cmd0 " << cmd0 << "]" << endl;
 
@@ -1001,26 +1043,21 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
        // LFUN_FILE_OPEN generated by drag-and-drop.
        FuncRequest cmd = cmd0;
 
+       // E.g. Qt mouse press when no buffer
        if (!buffer_)
-               return false;
+               return make_pair(false, false);
 
        LCursor cur(*this);
        cur.push(buffer_->inset());
        cur.selection() = cursor_.selection();
 
-       // Doesn't go through lyxfunc, so we need to update
-       // the layout choice etc. ourselves
-
-       // E.g. Qt mouse press when no buffer
-       if (!buffer_)
-               return false;
-
        // Either the inset under the cursor or the
        // surrounding LyXText will handle this event.
 
        // Build temporary cursor.
        cmd.y = min(max(cmd.y, -1), height_);
        InsetBase * inset = buffer_->text().editXY(cur, cmd.x, cmd.y);
+
        //lyxerr << BOOST_CURRENT_FUNCTION
        //       << " * hit inset at tip: " << inset << endl;
        //lyxerr << BOOST_CURRENT_FUNCTION
@@ -1033,23 +1070,21 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
        // via the temp cursor. If the inset wishes to change the real
        // cursor it has to do so explicitly by using
        //  cur.bv().cursor() = cur;  (or similar)
-       if (inset)
+       if (inset) {
                inset->dispatch(cur, cmd);
+       }
 
        // Now dispatch to the temporary cursor. If the real cursor should
        // be modified, the inset's dispatch has to do so explicitly.
        if (!cur.result().dispatched())
                cur.dispatch(cmd);
 
-       if (cur.result().dispatched()) {
-               // Redraw if requested or necessary.
-               if (cur.result().update())
-                       update(Update::FitCursor | Update::Force);
-               else
-                       update(Update::FitCursor | Update::MultiParSel);
-       }
+       // Redraw if requested and necessary.
+       if (cur.result().dispatched() && cur.result().update())
+               return update(cur.result().update());
 
-       return true;
+       // When the above and the inner function are fixed, we can do this:
+       return make_pair(false, false);
 }
 
 
@@ -1201,14 +1236,9 @@ ViewMetricsInfo const & BufferView::viewMetricsInfo()
 
 void BufferView::updateMetrics(bool singlepar)
 {
-       // FIXME (Abdel 19/10/2006):
-       // There's something fishy in tabular. The coord_cache_ is not
-       // correctly reconstructed when a character is trying to be inserted.
-       // Not clearing out the coord_cache_ fixes the crash but there is a
-       // bad side effect: buffer-begin and buffer-end do not update the screen.
-       //
-       // Remove old position cache
-       coord_cache_.clear();
+       // Clear out the position cache in case of full screen redraw.
+       if (!singlepar)
+               coord_cache_.clear();
 
        LyXText & buftext = buffer_->text();
        pit_type size = int(buftext.paragraphs().size());
@@ -1369,6 +1399,7 @@ void BufferView::menuInsertLyXFile(string const & filenm)
                ErrorList & el = buffer_->errorList("Parse");
                // Copy the inserted document error list into the current buffer one.
                el = buf.errorList("Parse");
+               recordUndo(cursor_);
                cap::pasteParagraphList(cursor_, buf.paragraphs(),
                                             buf.params().textclass, el);
                res = _("Document %1$s inserted.");