X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBufferView.C;h=d1d768ac36b652dc994091710f066efa08d17265;hb=c66d2f1ee555358a0a378bcdc9783a1306bd8990;hp=a448a86534cd91375f03ad40db31755749563a11;hpb=6ac15c5bb9eb7c692918c9bf753b283b8b573910;p=lyx.git diff --git a/src/BufferView.C b/src/BufferView.C index a448a86534..d1d768ac36 100644 --- a/src/BufferView.C +++ b/src/BufferView.C @@ -103,9 +103,6 @@ namespace Alert = frontend::Alert; namespace { -unsigned int const saved_positions_num = 20; - - /// Return an inset of this class if it exists at the current cursor position template T * getInsetByCode(LCursor & cur, InsetBase::Code code) @@ -123,23 +120,12 @@ T * getInsetByCode(LCursor & cur, InsetBase::Code code) BufferView::BufferView() - : buffer_(0), wh_(0), + : width_(0), height_(0), buffer_(0), wh_(0), cursor_(*this), multiparsel_cache_(false), anchor_ref_(0), offset_ref_(0), intl_(new Intl) { xsel_cache_.set = false; - - saved_positions.resize(saved_positions_num); - // load saved bookmarks - Session::BookmarkList & bmList = LyX::ref().session().loadBookmarks(); - for (Session::BookmarkList::iterator bm = bmList.begin(); - bm != bmList.end(); ++bm) - if (bm->get<0>() < saved_positions_num) - saved_positions[bm->get<0>()] = Position( bm->get<1>(), bm->get<2>(), bm->get<3>() ); - // and then clear them - bmList.clear(); - intl_->initKeyMapper(lyxrc.use_kbmap); } @@ -167,7 +153,7 @@ void BufferView::setBuffer(Buffer * b) buffer_->saveCursor(cursor_.selectionBegin(), cursor_.selectionEnd()); // current buffer is going to be switched-off, save cursor pos - LyX::ref().session().saveFilePosition(buffer_->fileName(), + LyX::ref().session().lastFilePos().save(buffer_->fileName(), boost::tie(cursor_.pit(), cursor_.pos()) ); } @@ -246,6 +232,7 @@ bool BufferView::loadLyXFile(string const & filename, bool tolastfiles) if (!theBufferList().close(theBufferList().getBuffer(s), false)) return false; // Fall through to new load. (Asger) + buffer_ = 0; } Buffer * b = 0; @@ -279,7 +266,7 @@ bool BufferView::loadLyXFile(string const & filename, bool tolastfiles) if (lyxrc.use_lastfilepos) { pit_type pit; pos_type pos; - boost::tie(pit, pos) = LyX::ref().session().loadFilePosition(s); + boost::tie(pit, pos) = LyX::ref().session().lastFilePos().load(s); // I am not sure how to separate the following part to a function // so I will leave this to Lars. // @@ -298,7 +285,7 @@ bool BufferView::loadLyXFile(string const & filename, bool tolastfiles) } if (tolastfiles) - LyX::ref().session().addLastFile(b->fileName()); + LyX::ref().session().lastFiles().add(b->fileName()); return true; } @@ -352,7 +339,7 @@ bool BufferView::multiParSel() } -bool BufferView::update(Update::flags flags) +std::pair BufferView::update(Update::flags flags) { // This is close to a hot-path. if (lyxerr.debugging(Debug::DEBUG)) { @@ -366,22 +353,40 @@ bool BufferView::update(Update::flags flags) // Check needed to survive LyX startup if (!buffer_) - return false; + return make_pair(false, false); - lyxerr[Debug::WORKAREA] << "BufferView::update" << std::endl; + if (lyxerr.debugging(Debug::WORKAREA)) { + lyxerr[Debug::WORKAREA] << "BufferView::update" << std::endl; + } // 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 & (Update::SinglePar | Update::Force))) { + if (fitCursor() || multiParSel()) { + // a CoordCache update is needed + updateMetrics(false); + // tell the frontend to update the screen. + return make_pair(true, false); + } + // no need to do anything. + return make_pair(false, false); + } + + // We are now in the case (Update::SinglePar | Update::Force) + bool single_par = flags & Update::SinglePar; + updateMetrics(single_par); + + // Don't forget to do check for fitCursor() and multiParSel(). + fitCursor(); + multiParSel(); + + return make_pair(true, single_par); } @@ -401,11 +406,13 @@ void BufferView::updateScrollbar() offset_ref_ = 0; } - lyxerr[Debug::GUI] - << BOOST_CURRENT_FUNCTION - << " Updating scrollbar: height: " << t.paragraphs().size() - << " curr par: " << cursor_.bottom().pit() - << " default height " << defaultRowHeight() << endl; + if (lyxerr.debugging(Debug::GUI)) { + lyxerr[Debug::GUI] + << BOOST_CURRENT_FUNCTION + << " Updating scrollbar: height: " << t.paragraphs().size() + << " curr par: " << cursor_.bottom().pit() + << " default height " << defaultRowHeight() << endl; + } // It would be better to fix the scrollbar to understand // values in [0..1] and divide everything by wh @@ -431,11 +438,14 @@ void BufferView::updateScrollbar() sumh += h2; nh++; } + + BOOST_ASSERT(nh); int const hav = sumh / nh; // More realistic average paragraph height if (hav > wh_) wh_ = hav; + BOOST_ASSERT(h); scrollbarParameters_.height = (parsize + 1) * wh_; scrollbarParameters_.position = anchor_ref_ * wh_ + int(offset_ref_ * wh_ / float(h)); scrollbarParameters_.lineScrollHeight = int(wh_ * defaultRowHeight() / float(h)); @@ -463,7 +473,7 @@ void BufferView::scrollDocView(int value) anchor_ref_ = int(bar * t.paragraphs().size()); if (anchor_ref_ > int(t.paragraphs().size()) - 1) anchor_ref_ = int(t.paragraphs().size()) - 1; - t.redoParagraph(anchor_ref_); + t.redoParagraph(*this, anchor_ref_); int const h = t.getPar(anchor_ref_).height(); offset_ref_ = int((bar * t.paragraphs().size() - anchor_ref_) * h); } @@ -510,74 +520,32 @@ Change const BufferView::getCurrentChange() const } -void BufferView::savePosition(unsigned int i) +void BufferView::saveBookmark(bool persistent) { - if (i >= saved_positions_num) - return; - BOOST_ASSERT(cursor_.inTexted()); - saved_positions[i] = Position(buffer_->fileName(), - cursor_.paragraph().id(), - cursor_.pos()); - if (i > 0) + LyX::ref().session().bookmarks().save( + buffer_->fileName(), + cursor_.paragraph().id(), + cursor_.pos(), + persistent + ); + if (persistent) // emit message signal. - message(bformat(_("Saved bookmark %1$d"), i)); + message(_("Save bookmark")); } -void BufferView::restorePosition(unsigned int i) +void BufferView::moveToPosition(int par_id, pos_type par_pos) { - if (i >= saved_positions_num) - return; - - string const fname = saved_positions[i].filename; - cursor_.clearSelection(); - if (fname != buffer_->fileName()) { - Buffer * b = 0; - if (theBufferList().exists(fname)) - b = theBufferList().getBuffer(fname); - else { - b = theBufferList().newBuffer(fname); - // Don't ask, just load it - lyx::loadLyXFile(b, fname); - } - if (b) - setBuffer(b); - } - - ParIterator par = buffer_->getParFromID(saved_positions[i].par_id); + ParIterator par = buffer_->getParFromID(par_id); if (par == buffer_->par_iterator_end()) return; - setCursor(makeDocIterator(par, min(par->size(), saved_positions[i].par_pos))); - - if (i > 0) - // emit message signal. - message(bformat(_("Moved to bookmark %1$d"), i)); + setCursor(makeDocIterator(par, min(par->size(), par_pos))); } -bool BufferView::isSavedPosition(unsigned int i) -{ - return i < saved_positions_num && !saved_positions[i].filename.empty(); -} - -void BufferView::saveSavedPositions() -{ - // save bookmarks. It is better to use the pit interface - // but I do not know how to effectively convert between - // par_id and pit. - for (unsigned int i=1; i < saved_positions_num; ++i) { - if ( isSavedPosition(i) ) - LyX::ref().session().saveBookmark( boost::tie( - i, - saved_positions[i].filename, - saved_positions[i].par_id, - saved_positions[i].par_pos) ); - } -} - void BufferView::switchKeyMap() { if (!lyxrc.rtl_support) @@ -603,7 +571,7 @@ void BufferView::center() { CursorSlice & bot = cursor_.bottom(); pit_type const pit = bot.pit(); - bot.text()->redoParagraph(pit); + bot.text()->redoParagraph(*this, pit); Paragraph const & par = bot.text()->paragraphs()[pit]; anchor_ref_ = pit; offset_ref_ = bv_funcs::coordOffset(*this, cursor_, cursor_.boundary()).y_ @@ -659,10 +627,6 @@ FuncStatus BufferView::getStatus(FuncRequest const & cmd) break; } - case LFUN_BOOKMARK_GOTO: - flag.enabled(isSavedPosition(convert(to_utf8(cmd.argument())))); - break; - case LFUN_CHANGES_TRACK: flag.enabled(true); flag.setOnOff(buffer_->params().trackChanges); @@ -756,11 +720,7 @@ bool BufferView::dispatch(FuncRequest const & cmd) break; case LFUN_BOOKMARK_SAVE: - savePosition(convert(to_utf8(cmd.argument()))); - break; - - case LFUN_BOOKMARK_GOTO: - restorePosition(convert(to_utf8(cmd.argument()))); + saveBookmark(convert(to_utf8(cmd.argument()))); break; case LFUN_LABEL_GOTO: { @@ -771,7 +731,8 @@ bool BufferView::dispatch(FuncRequest const & cmd) InsetBase::REF_CODE); if (inset) { label = inset->getParam("reference"); - savePosition(0); + // persistent=false: use temp_bookmark + saveBookmark(false); } } @@ -782,21 +743,34 @@ bool BufferView::dispatch(FuncRequest const & cmd) case LFUN_PARAGRAPH_GOTO: { int const id = convert(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; } @@ -1041,17 +1015,14 @@ void BufferView::workAreaResize(int width, int height) width_ = width; height_ = height; - if (buffer_ && widthChange) { - // The WorkArea content needs a resize + if (buffer_) resize(); - } - if (widthChange || heightChange) - update(); + update(); } -bool BufferView::workAreaDispatch(FuncRequest const & cmd0) +std::pair BufferView::workAreaDispatch(FuncRequest const & cmd0) { //lyxerr << BOOST_CURRENT_FUNCTION << "[ cmd0 " << cmd0 << "]" << endl; @@ -1059,26 +1030,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 @@ -1091,23 +1057,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); } @@ -1259,14 +1223,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()); @@ -1286,7 +1245,7 @@ void BufferView::updateMetrics(bool singlepar) // (if this paragraph contains insets etc., rebreaking will // recursively descend) if (!singlepar || pit == cursor_.bottom().pit()) - buftext.redoParagraph(pit); + buftext.redoParagraph(*this, pit); int y0 = buftext.getPar(pit).ascent() - offset_ref_; // Redo paragraphs above anchor if necessary; again, in Single Par @@ -1296,7 +1255,7 @@ void BufferView::updateMetrics(bool singlepar) y1 -= buftext.getPar(pit1).ascent(); --pit1; if (!singlepar || pit1 == cursor_.bottom().pit()) - buftext.redoParagraph(pit1); + buftext.redoParagraph(*this, pit1); y1 -= buftext.getPar(pit1).descent(); } @@ -1322,7 +1281,7 @@ void BufferView::updateMetrics(bool singlepar) y2 += buftext.getPar(pit2).descent(); ++pit2; if (!singlepar || pit2 == cursor_.bottom().pit()) - buftext.redoParagraph(pit2); + buftext.redoParagraph(*this, pit2); y2 += buftext.getPar(pit2).ascent(); } @@ -1365,6 +1324,7 @@ void BufferView::updateMetrics(bool singlepar) metrics_info_ = ViewMetricsInfo(pit1, pit2, y1, y2, singlepar, size); if (lyxerr.debugging(Debug::WORKAREA)) { + lyxerr[Debug::WORKAREA] << "BufferView::updateMetrics" << endl; coord_cache_.dump(); } } @@ -1426,6 +1386,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.");