X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBufferView_pimpl.C;h=a6db146074e208901149c6ce67e2e3ea341febb0;hb=ccc5d5576437a7615f54bf1ed6e83e05bfbaaf78;hp=723cbad73c9f41915d70bdbd9f913562ec51142b;hpb=eaad9ff595befab46fba2909632201b923ba8189;p=lyx.git diff --git a/src/BufferView_pimpl.C b/src/BufferView_pimpl.C index 723cbad73c..a6db146074 100644 --- a/src/BufferView_pimpl.C +++ b/src/BufferView_pimpl.C @@ -19,19 +19,19 @@ #include #include "BufferView_pimpl.h" -#include "bufferlist.h" #include "buffer.h" #include "buffer_funcs.h" -#include "bufferview_funcs.h" -#include "lfuns.h" +#include "bufferlist.h" +#include "bufferparams.h" +#include "cursor.h" #include "debug.h" +#include "dispatchresult.h" #include "factory.h" #include "FloatList.h" #include "funcrequest.h" #include "gettext.h" #include "intl.h" #include "iterators.h" -#include "Lsstream.h" #include "lyx_cb.h" // added for Dispatch functions #include "lyx_main.h" #include "lyxfind.h" @@ -40,53 +40,52 @@ #include "lyxrc.h" #include "lastfiles.h" #include "paragraph.h" +#include "paragraph_funcs.h" #include "ParagraphParameters.h" -#include "TextCache.h" -#include "undo_funcs.h" +#include "undo.h" +#include "vspace.h" #include "insets/insetfloatlist.h" -#include "insets/insetgraphics.h" -#include "insets/insetinclude.h" #include "insets/insetref.h" -#include "insets/insettext.h" #include "frontends/Alert.h" #include "frontends/Dialogs.h" #include "frontends/FileDialog.h" #include "frontends/LyXView.h" #include "frontends/LyXScreenFactory.h" -#include "frontends/mouse_state.h" #include "frontends/screen.h" #include "frontends/WorkArea.h" #include "frontends/WorkAreaFactory.h" -#include "mathed/formulabase.h" - #include "graphics/Previews.h" -#include "support/LAssert.h" -#include "support/tostr.h" +#include "mathed/formulabase.h" + #include "support/filetools.h" +#include "support/globbing.h" #include "support/path_defines.h" +#include "support/tostr.h" #include -#include -#include -#include +using bv_funcs::currentState; + +using lyx::pos_type; +using lyx::support::AddPath; +using lyx::support::bformat; +using lyx::support::FileFilterList; +using lyx::support::FileSearch; +using lyx::support::IsDirWriteable; +using lyx::support::MakeDisplayPath; +using lyx::support::strToUnsignedInt; +using lyx::support::system_lyxdir; -using std::vector; -using std::find_if; -using std::find; -using std::pair; using std::endl; using std::make_pair; using std::min; +using std::string; -using lyx::pos_type; -using namespace lyx::support; -using namespace bv_funcs; extern BufferList bufferlist; @@ -112,11 +111,13 @@ boost::signals::connection lostcon; } // anon namespace -BufferView::Pimpl::Pimpl(BufferView * bv, LyXView * owner, +BufferView::Pimpl::Pimpl(BufferView & bv, LyXView * owner, int xpos, int ypos, int width, int height) - : bv_(bv), owner_(owner), buffer_(0), cursor_timeout(400), - using_xterm_cursor(false) + : bv_(&bv), owner_(owner), buffer_(0), cursor_timeout(400), + using_xterm_cursor(false), cursor_(bv) { + xsel_cache_.set = false; + workarea_.reset(WorkAreaFactory::create(xpos, ypos, width, height)); screen_.reset(LyXScreenFactory::create(workarea())); @@ -159,13 +160,20 @@ void BufferView::Pimpl::connectBuffer(Buffer & buf) if (errorConnection_.connected()) disconnectBuffer(); - errorConnection_ = buf.error.connect(boost::bind(&BufferView::Pimpl::addError, this, _1)); - messageConnection_ = buf.message.connect(boost::bind(&LyXView::message, owner_, _1)); - busyConnection_ = buf.busy.connect(boost::bind(&LyXView::busy, owner_, _1)); - titleConnection_ = buf.updateTitles.connect(boost::bind(&LyXView::updateWindowTitle, owner_)); - timerConnection_ = buf.resetAutosaveTimers.connect(boost::bind(&LyXView::resetAutosaveTimer, owner_)); - readonlyConnection_ = buf.readonly.connect(boost::bind(&BufferView::Pimpl::showReadonly, this, _1)); - closingConnection_ = buf.closing.connect(boost::bind(&BufferView::Pimpl::buffer, this, (Buffer *)0)); + errorConnection_ = + buf.error.connect(boost::bind(&BufferView::Pimpl::addError, this, _1)); + messageConnection_ = + buf.message.connect(boost::bind(&LyXView::message, owner_, _1)); + busyConnection_ = + buf.busy.connect(boost::bind(&LyXView::busy, owner_, _1)); + titleConnection_ = + buf.updateTitles.connect(boost::bind(&LyXView::updateWindowTitle, owner_)); + timerConnection_ = + buf.resetAutosaveTimers.connect(boost::bind(&LyXView::resetAutosaveTimer, owner_)); + readonlyConnection_ = + buf.readonly.connect(boost::bind(&BufferView::Pimpl::showReadonly, this, _1)); + closingConnection_ = + buf.closing.connect(boost::bind(&BufferView::Pimpl::buffer, this, (Buffer *)0)); } @@ -248,7 +256,7 @@ bool BufferView::Pimpl::loadLyXFile(string const & filename, bool tolastfiles) bv_->showErrorList(_("Parse")); if (tolastfiles) - lastfiles->newFile(b->fileName()); + LyX::ref().lastfiles().newFile(b->fileName()); return true; } @@ -272,26 +280,33 @@ Painter & BufferView::Pimpl::painter() const } +void BufferView::Pimpl::top_y(int y) +{ + top_y_ = y; +} + + +int BufferView::Pimpl::top_y() const +{ + return top_y_; +} + + void BufferView::Pimpl::buffer(Buffer * b) { lyxerr[Debug::INFO] << "Setting buffer in BufferView (" << b << ')' << endl; if (buffer_) { disconnectBuffer(); - // Put the old text into the TextCache, but - // only if the buffer is still loaded. - // Also set the owner of the test to 0 - // bv_->text->owner(0); - textcache.add(buffer_, workarea().workWidth(), bv_->text); - if (lyxerr.debugging()) - textcache.show(lyxerr, "BufferView::buffer"); - - bv_->text = 0; + //delete bv_->text(); + //bv_->setText(0); } // set current buffer buffer_ = b; + top_y_ = 0; + // if we're quitting lyx, don't bother updating stuff if (quitting) return; @@ -304,12 +319,16 @@ void BufferView::Pimpl::buffer(Buffer * b) lyxerr[Debug::INFO] << "Buffer addr: " << buffer_ << endl; connectBuffer(*buffer_); + buffer_->text().init(bv_); + buffer_->text().textwidth_ = workarea().workWidth(); + buffer_->text().fullRebreak(); + // If we don't have a text object for this, we make one - if (bv_->text == 0) + if (bv_->text() == 0) resizeCurrentBuffer(); // FIXME: needed when ? - bv_->text->top_y(screen().topCursorVisible(bv_->text)); + fitCursor(); // Buffer-dependent dialogs should be updated or // hidden. This should go here because some dialogs (eg ToC) @@ -318,13 +337,6 @@ void BufferView::Pimpl::buffer(Buffer * b) } else { lyxerr[Debug::INFO] << " No Buffer!" << endl; owner_->getDialogs().hideBufferDependent(); - - // Also remove all remaining text's from the testcache. - // (there should not be any!) (if there is any it is a - // bug!) - if (lyxerr.debugging()) - textcache.show(lyxerr, "buffer delete all"); - textcache.clear(); } update(); @@ -334,12 +346,9 @@ void BufferView::Pimpl::buffer(Buffer * b) owner_->updateLayoutChoice(); owner_->updateWindowTitle(); - if (buffer_) { - // Don't forget to update the Layout - string const layoutname = - bv_->text->cursor.par()->layout()->name(); - owner_->setLayout(layoutname); - } + // Don't forget to update the Layout + if (buffer_) + owner_->setLayout(bv_->text()->cursorPar()->layout()->name()); if (lyx::graphics::Previews::activated() && buffer_) lyx::graphics::Previews::get().generateBufferPreviews(*buffer_); @@ -348,33 +357,22 @@ void BufferView::Pimpl::buffer(Buffer * b) bool BufferView::Pimpl::fitCursor() { - bool ret; - - if (bv_->theLockingInset()) { - bv_->theLockingInset()->fitInsetCursor(bv_); - ret = true; - } else { - ret = screen().fitCursor(bv_->text, bv_); + lyxerr << "BufferView::Pimpl::fitCursor." << endl; + if (screen().fitCursor(bv_)) { + updateScrollbar(); + return true; } - - //dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE)); - - // We need to always update, in case we did a - // paste and we stayed anchored to a row, but - // the actual height of the doc changed ... - updateScrollbar(); - return ret; + return false; } void BufferView::Pimpl::redoCurrentBuffer() { lyxerr[Debug::INFO] << "BufferView::redoCurrentBuffer" << endl; - if (buffer_ && bv_->text) { + if (buffer_ && bv_->text()) { resizeCurrentBuffer(); updateScrollbar(); owner_->updateLayoutChoice(); - update(); } } @@ -383,84 +381,57 @@ void BufferView::Pimpl::resizeCurrentBuffer() { lyxerr[Debug::INFO] << "resizeCurrentBuffer" << endl; - ParagraphList::iterator par; - ParagraphList::iterator selstartpar; - ParagraphList::iterator selendpar; - UpdatableInset * the_locking_inset = 0; + int par = -1; + int selstartpar = -1; + int selendpar = -1; pos_type pos = 0; pos_type selstartpos = 0; pos_type selendpos = 0; - bool selection = false; + bool sel = false; bool mark_set = false; owner_->busy(true); owner_->message(_("Formatting document...")); - if (bv_->text) { - par = bv_->text->cursor.par(); - pos = bv_->text->cursor.pos(); - selstartpar = bv_->text->selection.start.par(); - selstartpos = bv_->text->selection.start.pos(); - selendpar = bv_->text->selection.end.par(); - selendpos = bv_->text->selection.end.pos(); - selection = bv_->text->selection.set(); - mark_set = bv_->text->selection.mark(); - the_locking_inset = bv_->theLockingInset(); - bv_->text->fullRebreak(); - update(); - } else { - lyxerr << "text not available!" << endl; - // See if we have a text in TextCache that fits - // the new buffer_ with the correct width. - bv_->text = textcache.findFit(buffer_, workarea().workWidth()); - if (bv_->text) { - lyxerr << "text in cache!" << endl; - if (lyxerr.debugging()) { - lyxerr << "Found a LyXText that fits:" << endl; - textcache.show(lyxerr, make_pair(buffer_, make_pair(workarea().workWidth(), bv_->text))); - } - // Set the owner of the newly found text - // bv_->text->owner(bv_); - if (lyxerr.debugging()) - textcache.show(lyxerr, "resizeCurrentBuffer"); - } else { - lyxerr << "no text in cache!" << endl; - bv_->text = new LyXText(bv_, 0, false, bv_->buffer()->paragraphs); - bv_->text->init(bv_); - } - - par = bv_->text->ownerParagraphs().end(); - selstartpar = bv_->text->ownerParagraphs().end(); - selendpar = bv_->text->ownerParagraphs().end(); - } + LyXText * text = bv_->text(); + lyxerr << "### resizeCurrentBuffer: text " << text << endl; + if (!text) + return; -#warning does not help much - bv_->text->redoParagraphs(bv_->text->ownerParagraphs().begin(), - bv_->text->ownerParagraphs().end()); + LCursor & cur = bv_->cursor(); + par = cur.par(); + pos = cur.pos(); + selstartpar = cur.selStart().par(); + selstartpos = cur.selStart().pos(); + selendpar = cur.selEnd().par(); + selendpos = cur.selEnd().pos(); + sel = cur.selection(); + mark_set = cur.mark(); + text->textwidth_ = bv_->workWidth(); + text->fullRebreak(); + update(); - if (par != bv_->text->ownerParagraphs().end()) { - bv_->text->selection.set(true); + if (par != -1) { + cur.selection() = true; // At this point just to avoid the Delete-Empty-Paragraph- // Mechanism when setting the cursor. - bv_->text->selection.mark(mark_set); - if (selection) { - bv_->text->setCursor(selstartpar, selstartpos); - bv_->text->selection.cursor = bv_->text->cursor; - bv_->text->setCursor(selendpar, selendpos); - bv_->text->setSelection(); - bv_->text->setCursor(par, pos); + cur.mark() = mark_set; + if (sel) { + text->setCursor(selstartpar, selstartpos); + cur.resetAnchor(); + text->setCursor(selendpar, selendpos); + cur.setSelection(); + text->setCursor(par, pos); } else { - bv_->text->setCursor(par, pos); - bv_->text->selection.cursor = bv_->text->cursor; - bv_->text->selection.set(false); + text->setCursor(par, pos); + cur.resetAnchor(); + cur.selection() = false; } - // remake the inset locking - bv_->theLockingInset(the_locking_inset); } - bv_->text->top_y(screen().topCursorVisible(bv_->text)); + fitCursor(); switchKeyMap(); owner_->busy(false); @@ -474,18 +445,18 @@ void BufferView::Pimpl::resizeCurrentBuffer() void BufferView::Pimpl::updateScrollbar() { - if (!bv_->text) { + if (!bv_->text()) { lyxerr[Debug::GUI] << "no text in updateScrollbar" << endl; workarea().setScrollbarParams(0, 0, 0); return; } - LyXText const & t = *bv_->text; + LyXText const & t = *bv_->text(); lyxerr[Debug::GUI] << "Updating scrollbar: h " << t.height << ", top_y() " - << t.top_y() << ", default height " << defaultRowHeight() << endl; + << top_y() << ", default height " << defaultRowHeight() << endl; - workarea().setScrollbarParams(t.height, t.top_y(), defaultRowHeight()); + workarea().setScrollbarParams(t.height, top_y(), defaultRowHeight()); } @@ -498,20 +469,20 @@ void BufferView::Pimpl::scrollDocView(int value) screen().hideCursor(); - bv_->text->top_y(value); + top_y(value); screen().redraw(*bv_); if (!lyxrc.cursor_follows_scrollbar) return; int const height = defaultRowHeight(); - int const first = int((bv_->text->top_y() + height)); - int const last = int((bv_->text->top_y() + workarea().workHeight() - height)); + int const first = top_y() + height; + int const last = top_y() + workarea().workHeight() - height; - LyXText * text = bv_->text; - if (text->cursor.y() < first) + LyXText * text = bv_->text(); + if (text->cursorY() < first) text->setCursorFromCoordinates(0, first); - else if (text->cursor.y() > last) + else if (text->cursorY() > last) text->setCursorFromCoordinates(0, last); owner_->updateLayoutChoice(); @@ -520,15 +491,14 @@ void BufferView::Pimpl::scrollDocView(int value) void BufferView::Pimpl::scroll(int lines) { - if (!buffer_) { + if (!buffer_) return; - } - LyXText const * t = bv_->text; + LyXText const * t = bv_->text(); int const line_height = defaultRowHeight(); // The new absolute coordinate - int new_top_y = t->top_y() + lines * line_height; + int new_top_y = top_y() + lines * line_height; // Restrict to a valid value new_top_y = std::min(t->height - 4 * line_height, new_top_y); @@ -537,7 +507,7 @@ void BufferView::Pimpl::scroll(int lines) scrollDocView(new_top_y); // Update the scrollbar. - workarea().setScrollbarParams(t->height, t->top_y(), defaultRowHeight()); + workarea().setScrollbarParams(t->height, top_y(), defaultRowHeight()); } @@ -567,22 +537,24 @@ void BufferView::Pimpl::selectionRequested() if (!available()) return; - LyXText * text = bv_->getLyXText(); + LCursor & cur = bv_->cursor(); - if (text->selection.set() && - (!bv_->text->xsel_cache.set() || - text->selection.start != bv_->text->xsel_cache.start || - text->selection.end != bv_->text->xsel_cache.end)) - { - bv_->text->xsel_cache = text->selection; - sel = text->selectionAsString(bv_->buffer(), false); - } else if (!text->selection.set()) { - sel = string(); - bv_->text->xsel_cache.set(false); - } - if (!sel.empty()) { - workarea().putClipboard(sel); + if (!cur.selection()) { + xsel_cache_.set = false; + return; } + + if (!xsel_cache_.set || + cur.cursor_.back() != xsel_cache_.cursor || + cur.anchor_.back() != xsel_cache_.anchor) + { + xsel_cache_.cursor = cur.cursor_.back(); + xsel_cache_.anchor = cur.anchor_.back(); + xsel_cache_.set = cur.selection(); + sel = bv_->getLyXText()->selectionAsString(*bv_->buffer(), false); + if (!sel.empty()) + workarea().putClipboard(sel); + } } @@ -590,8 +562,8 @@ void BufferView::Pimpl::selectionLost() { if (available()) { screen().hideCursor(); - bv_->getLyXText()->clearSelection(); - bv_->text->xsel_cache.set(false); + bv_->cursor().clearSelection(); + xsel_cache_.set = false; } } @@ -612,16 +584,6 @@ void BufferView::Pimpl::workAreaResize() if (widthChange) { // The visible LyXView need a resize resizeCurrentBuffer(); - - // Remove all texts from the textcache - // This is not _really_ what we want to do. What - // we really want to do is to delete in textcache - // that does not have a BufferView with matching - // width, but as long as we have only one BufferView - // deleting all gives the same result. - if (lyxerr.debugging()) - textcache.show(lyxerr, "Expose delete all"); - textcache.clear(); } } @@ -636,12 +598,19 @@ void BufferView::Pimpl::workAreaResize() void BufferView::Pimpl::update() { - lyxerr << "BufferView::update()" << endl; + //lyxerr << "BufferView::update()" << endl; // fix cursor coordinate cache in case something went wrong + + // check needed to survive LyX startup if (bv_->getLyXText()) { - // check needed to survive LyX startup - bv_->getLyXText()->redoCursor(); - fitCursor(); + // update all 'visible' paragraphs + ParagraphList::iterator beg; + ParagraphList::iterator end; + getParsInRange(buffer_->paragraphs(), + top_y(), top_y() + workarea().workHeight(), + beg, end); + bv_->text()->redoParagraphs(beg, end); + updateScrollbar(); } screen().redraw(*bv_); } @@ -656,37 +625,29 @@ void BufferView::Pimpl::cursorToggle() } screen().toggleCursor(*bv_); - cursor_timeout.restart(); } bool BufferView::Pimpl::available() const { - if (buffer_ && bv_->text) - return true; - return false; + return buffer_ && bv_->text(); } Change const BufferView::Pimpl::getCurrentChange() { - if (!bv_->buffer()->params.tracking_changes) + if (!bv_->buffer()->params().tracking_changes) return Change(Change::UNCHANGED); LyXText * text = bv_->getLyXText(); + LCursor & cur = bv_->cursor(); - if (!text->selection.set()) + if (!cur.selection()) return Change(Change::UNCHANGED); - LyXCursor const & cur = text->selection.start; - return cur.par()->lookupChangeFull(cur.pos()); -} - - -void BufferView::Pimpl::beforeChange(LyXText * text) -{ - text->clearSelection(); + return text->getPar(cur.selStart()) + ->lookupChangeFull(cur.selStart().pos()); } @@ -695,8 +656,8 @@ void BufferView::Pimpl::savePosition(unsigned int i) if (i >= saved_positions_num) return; saved_positions[i] = Position(buffer_->fileName(), - bv_->text->cursor.par()->id(), - bv_->text->cursor.pos()); + bv_->text()->cursorPar()->id(), + bv_->text()->cursor().pos()); if (i > 0) owner_->message(bformat(_("Saved bookmark %1$s"), tostr(i))); } @@ -709,17 +670,17 @@ void BufferView::Pimpl::restorePosition(unsigned int i) string const fname = saved_positions[i].filename; - beforeChange(bv_->text); + bv_->cursor().clearSelection(); if (fname != buffer_->fileName()) { - Buffer * b; + Buffer * b = 0; if (bufferlist.exists(fname)) b = bufferlist.getBuffer(fname); else { b = bufferlist.newBuffer(fname); ::loadLyXFile(b, fname); // don't ask, just load it } - if (b != 0) + if (b) buffer(b); } @@ -727,10 +688,9 @@ void BufferView::Pimpl::restorePosition(unsigned int i) if (par == buffer_->par_iterator_end()) return; - bv_->text->setCursor(par.pit(), + bv_->text()->setCursor(par.pit(), min(par->size(), saved_positions[i].par_pos)); - update(); if (i > 0) owner_->message(bformat(_("Moved to bookmark %1$s"), tostr(i))); } @@ -738,10 +698,7 @@ void BufferView::Pimpl::restorePosition(unsigned int i) bool BufferView::Pimpl::isSavedPosition(unsigned int i) { - if (i >= saved_positions_num) - return false; - - return !saved_positions[i].filename.empty(); + return i < saved_positions_num && !saved_positions[i].filename.empty(); } @@ -750,44 +707,26 @@ void BufferView::Pimpl::switchKeyMap() if (!lyxrc.rtl_support) return; - LyXText * text = bv_->getLyXText(); - if (text->real_current_font.isRightToLeft() - && !(bv_->theLockingInset() - && bv_->theLockingInset()->lyxCode() == InsetOld::ERT_CODE)) - { - if (owner_->getIntl().keymap == Intl::PRIMARY) - owner_->getIntl().KeyMapSec(); + Intl & intl = owner_->getIntl(); + if (bv_->getLyXText()->real_current_font.isRightToLeft()) { + if (intl.keymap == Intl::PRIMARY) + intl.KeyMapSec(); } else { - if (owner_->getIntl().keymap == Intl::SECONDARY) - owner_->getIntl().KeyMapPrim(); - } -} - - -void BufferView::Pimpl::insetUnlock() -{ - if (bv_->theLockingInset()) { - bv_->theLockingInset()->insetUnlock(bv_); - bv_->theLockingInset(0); - finishUndo(); + if (intl.keymap == Intl::SECONDARY) + intl.KeyMapPrim(); } } void BufferView::Pimpl::center() { - LyXText * text = bv_->text; + LyXText * text = bv_->text(); - beforeChange(text); + bv_->cursor().clearSelection(); int const half_height = workarea().workHeight() / 2; - int new_y = 0; - - if (text->cursor.y() > half_height) - new_y = text->cursor.y() - half_height; + int new_y = std::max(0, text->cursorY() - half_height); // FIXME: look at this comment again ... - - // FIXME: can we do this w/o calling screen directly ? // This updates top_y() but means the fitCursor() call // from the update(FITCUR) doesn't realise that we might // have moved (e.g. from GOTOPARAGRAPH), so doesn't cause @@ -796,9 +735,7 @@ void BufferView::Pimpl::center() // and also might have moved top_y() must make sure to call // updateScrollbar() currently. Never mind that this is a // pretty obfuscated way of updating t->top_y() - text->top_y(new_y); - //screen().draw(); - update(); + top_y(new_y); } @@ -808,19 +745,13 @@ void BufferView::Pimpl::stuffClipboard(string const & stuff) const } -/* - * Dispatch functions for actions which can be valid for BufferView->text - * and/or InsetText->text!!! - */ - - InsetOld * BufferView::Pimpl::getInsetByCode(InsetOld::Code code) { #if 0 - LyXCursor cursor = bv_->getLyXText()->cursor; + CursorSlice cursor = bv_->getLyXText()->cursor; Buffer::inset_iterator it = find_if(Buffer::inset_iterator( - cursor.par(), cursor.pos()), + cursorPar(), cursor().pos()), buffer_->inset_iterator_end(), lyx::compare_memfun(&Inset::lyxCode, code)); return it != buffer_->inset_iterator_end() ? (*it) : 0; @@ -829,7 +760,7 @@ InsetOld * BufferView::Pimpl::getInsetByCode(InsetOld::Code code) // should work for now. Better infrastructure is coming. (Lgb) Buffer * b = bv_->buffer(); - LyXCursor cursor = bv_->getLyXText()->cursor; + LyXText * text = bv_->getLyXText(); Buffer::inset_iterator beg = b->inset_iterator_begin(); Buffer::inset_iterator end = b->inset_iterator_end(); @@ -837,14 +768,14 @@ InsetOld * BufferView::Pimpl::getInsetByCode(InsetOld::Code code) bool cursor_par_seen = false; for (; beg != end; ++beg) { - if (beg.getPar() == cursor.par()) { + if (beg.getPar() == text->cursorPar()) { cursor_par_seen = true; } if (cursor_par_seen) { - if (beg.getPar() == cursor.par() - && beg.getPos() >= cursor.pos()) { + if (beg.getPar() == text->cursorPar() + && beg.getPos() >= text->cursor().pos()) { break; - } else if (beg.getPar() != cursor.par()) { + } else if (beg.getPar() != text->cursorPar()) { break; } } @@ -887,7 +818,8 @@ void BufferView::Pimpl::MenuInsertLyXFile(string const & filen) FileDialog::Result result = fileDlg.open(initpath, - _("*.lyx| LyX Documents (*.lyx)")); + FileFilterList(_("LyX Documents (*.lyx)")), + string()); if (result.first == FileDialog::Later) return; @@ -919,22 +851,20 @@ void BufferView::Pimpl::MenuInsertLyXFile(string const & filen) void BufferView::Pimpl::trackChanges() { Buffer * buf(bv_->buffer()); - bool const tracking(buf->params.tracking_changes); + bool const tracking(buf->params().tracking_changes); if (!tracking) { ParIterator const end = buf->par_iterator_end(); for (ParIterator it = buf->par_iterator_begin(); it != end; ++it) it->trackChanges(); - buf->params.tracking_changes = true; + buf->params().tracking_changes = true; // we cannot allow undos beyond the freeze point - buf->undostack.clear(); + buf->undostack().clear(); } else { update(); - bv_->text->setCursor(buf->paragraphs.begin(), 0); + bv_->text()->setCursor(0, 0); #warning changes FIXME - //moveCursorUpdate(false); - bool found = lyx::find::findNextChange(bv_); if (found) { owner_->getDialogs().show("changes"); @@ -944,22 +874,80 @@ void BufferView::Pimpl::trackChanges() ParIterator const end = buf->par_iterator_end(); for (ParIterator it = buf->par_iterator_begin(); it != end; ++it) it->untrackChanges(); - buf->params.tracking_changes = false; + buf->params().tracking_changes = false; + } + + buf->redostack().clear(); +} + +#warning remove me +CursorBase theTempCursor; + +namespace { + + InsetOld * insetFromCoords(BufferView * bv, int x, int y) + { + lyxerr << "insetFromCoords" << endl; + LyXText * text = bv->text(); + InsetOld * inset = 0; + theTempCursor.clear(); + while (true) { + InsetOld * const inset_hit = text->checkInsetHit(x, y); + if (!inset_hit) { + lyxerr << "no further inset hit" << endl; + break; + } + inset = inset_hit; + if (!inset->descendable()) { + lyxerr << "not descendable" << endl; + break; + } + int const cell = inset->getCell(x, y + bv->top_y()); + if (cell == -1) + break; + text = inset_hit->getText(cell); + lyxerr << "Hit inset: " << inset << " at x: " << x + << " text: " << text << " y: " << y << endl; + theTempCursor.push_back(CursorSlice(inset)); + } + //lyxerr << "theTempCursor: " << theTempCursor << endl; + return inset; } - buf->redostack.clear(); } -bool BufferView::Pimpl::workAreaDispatch(FuncRequest const & ev) +bool BufferView::Pimpl::workAreaDispatch(FuncRequest const & cmd) { - switch (ev.action) { + LCursor & cur = bv_->cursor(); + switch (cmd.action) { + case LFUN_MOUSE_MOTION: { + if (!available()) + return false; + FuncRequest cmd1 = cmd; + InsetBase * inset = cur.inset(); + DispatchResult res; + if (inset) { + cmd1.x -= inset->x(); + cmd1.y -= inset->y(); + res = inset->dispatch(cur, cmd1); + } else { + cmd1.y += bv_->top_y(); + res = cur.innerText()->dispatch(cur, cmd1); + } + + if (bv_->fitCursor() || res.update()) { + bv_->update(); + cur.updatePos(); + } + + return true; + } + case LFUN_MOUSE_PRESS: - case LFUN_MOUSE_MOTION: case LFUN_MOUSE_RELEASE: case LFUN_MOUSE_DOUBLE: - case LFUN_MOUSE_TRIPLE: - { + case LFUN_MOUSE_TRIPLE: { // We pass those directly to the Bufferview, since // otherwise selection handling breaks down @@ -972,37 +960,86 @@ bool BufferView::Pimpl::workAreaDispatch(FuncRequest const & ev) screen().hideCursor(); - bool const res = dispatch(ev); - + // either the inset under the cursor or the surrounding LyXText will + // handle this event. + + // built temporary path to inset + InsetOld * inset = insetFromCoords(bv_, cmd.x, cmd.y); + DispatchResult res; + + // try to dispatch to that inset + if (inset) { + FuncRequest cmd2 = cmd; + lyxerr << "dispatching action " << cmd2.action + << " to inset " << inset << endl; + cmd2.x -= inset->x(); + cmd2.y -= inset->y(); + res = inset->dispatch(cur, cmd2); + if (res.update()) { + bv_->update(); + cur.updatePos(); + } + res.update(false); + switch (res.val()) { + case FINISHED: + case FINISHED_RIGHT: + case FINISHED_UP: + case FINISHED_DOWN: + theTempCursor.pop_back(); + cur.cursor_ = theTempCursor; + cur.innerText() + ->setCursorFromCoordinates(cmd.x, top_y() + cmd.y); + if (bv_->fitCursor()) + bv_->update(); + return true; + default: + lyxerr << "not dispatched by inner inset val: " << res.val() << endl; + break; + } + } + + // otherwise set cursor to surrounding LyXText + if (!res.dispatched()) { + //lyxerr << "temp cursor is: " << theTempCursor << endl; + //lyxerr << "dispatching " << cmd + // << " to surrounding LyXText " + // << theTempCursor.innerText() << endl; + cur.cursor_ = theTempCursor; + FuncRequest cmd1 = cmd; + cmd1.y += bv_->top_y(); + res = cur.innerText()->dispatch(cur, cmd1); + if (bv_->fitCursor() || res.update()) + bv_->update(); + + //return DispatchResult(true, true); + } // see workAreaKeyPress cursor_timeout.restart(); screen().showCursor(*bv_); - // FIXME: we should skip these when selecting - owner_->updateLayoutChoice(); - owner_->updateToolbar(); - fitCursor(); + // skip these when selecting + if (cmd.action != LFUN_MOUSE_MOTION) { + owner_->updateLayoutChoice(); + owner_->updateToolbar(); + } // slight hack: this is only called currently when we // clicked somewhere, so we force through the display // of the new status here. owner_->clearMessage(); - - return res; + return true; } + default: - owner_->dispatch(ev); + owner_->dispatch(cmd); return true; } } -bool BufferView::Pimpl::dispatch(FuncRequest const & ev_in) +bool BufferView::Pimpl::dispatch(FuncRequest const & ev) { // Make sure that the cached BufferView is correct. - FuncRequest ev = ev_in; - ev.setView(bv_); - lyxerr[Debug::ACTION] << "BufferView::Pimpl::Dispatch:" << " action[" << ev.action << ']' << " arg[" << ev.argument << ']' @@ -1011,7 +1048,8 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & ev_in) << " button[" << ev.button() << ']' << endl; - LyXTextClass const & tclass = buffer_->params.getLyXTextClass(); + LyXTextClass const & tclass = buffer_->params().getLyXTextClass(); + LCursor & cur = bv_->cursor(); switch (ev.action) { @@ -1033,57 +1071,6 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & ev_in) InsertAsciiFile(bv_, ev.argument, false); break; - case LFUN_LANGUAGE: - lang(bv_, ev.argument); - switchKeyMap(); - owner_->view_state_changed(); - break; - - case LFUN_EMPH: - emph(bv_); - owner_->view_state_changed(); - break; - - case LFUN_BOLD: - bold(bv_); - owner_->view_state_changed(); - break; - - case LFUN_NOUN: - noun(bv_); - owner_->view_state_changed(); - break; - - case LFUN_CODE: - code(bv_); - owner_->view_state_changed(); - break; - - case LFUN_SANS: - sans(bv_); - owner_->view_state_changed(); - break; - - case LFUN_ROMAN: - roman(bv_); - owner_->view_state_changed(); - break; - - case LFUN_DEFAULT: - styleReset(bv_); - owner_->view_state_changed(); - break; - - case LFUN_UNDERLINE: - underline(bv_); - owner_->view_state_changed(); - break; - - case LFUN_FONT_SIZE: - fontSize(bv_, ev.argument); - owner_->view_state_changed(); - break; - case LFUN_FONT_STATE: owner_->getLyXFunc().setMessage(currentState(bv_)); break; @@ -1095,8 +1082,8 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & ev_in) InsetCommandParams icp("label", contents); string data = InsetCommandMailer::params2string("label", icp); owner_->getDialogs().show("label", data, 0); + break; } - break; case LFUN_BOOKMARK_SAVE: savePosition(strToUnsignedInt(ev.argument)); @@ -1159,43 +1146,17 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & ev_in) case LFUN_MATH_IMPORT_SELECTION: // Imports LaTeX from the X selection case LFUN_MATH_DISPLAY: // Open or create a displayed math inset case LFUN_MATH_MODE: // Open or create an inlined math inset - mathDispatch(ev); + mathDispatch(cur, ev); break; - case LFUN_INSET_APPLY: { - string const name = ev.getArg(0); - - InsetBase * inset = owner_->getDialogs().getOpenInset(name); - if (inset) { - // This works both for 'original' and 'mathed' insets. - // Note that the localDispatch performs updateInset - // also. - FuncRequest fr(bv_, LFUN_INSET_MODIFY, ev.argument); - inset->localDispatch(fr); - } else { - FuncRequest fr(bv_, LFUN_INSET_INSERT, ev.argument); - dispatch(fr); - } - } - break; - case LFUN_INSET_INSERT: { - InsetOld * inset = createInset(ev); - if (inset && insertInset(inset)) { - updateInset(); - - string const name = ev.getArg(0); - if (name == "bibitem") { - // We need to do a redraw because the maximum - // InsetBibitem width could have changed -#warning check whether the update() is needed at all - bv_->update(); - } - } else { + // Same as above. + BOOST_ASSERT(false); + InsetOld * inset = createInset(bv_, ev); + if (!inset || !insertInset(inset)) delete inset; - } + break; } - break; case LFUN_FLOAT_LIST: if (tclass.floats().typeExist(ev.argument)) { @@ -1210,55 +1171,39 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & ev_in) case LFUN_LAYOUT_PARAGRAPH: { string data; - params2string(*bv_->getLyXText()->cursor.par(), data); - + params2string(*bv_->getLyXText()->cursorPar(), data); data = "show\n" + data; bv_->owner()->getDialogs().show("paragraph", data); break; } - case LFUN_PARAGRAPH_UPDATE: { - if (!bv_->owner()->getDialogs().visible("paragraph")) - break; - Paragraph const & par = *bv_->getLyXText()->cursor.par(); - - string data; - params2string(par, data); - - // Will the paragraph accept changes from the dialog? - InsetOld * const inset = par.inInset(); - bool const accept = - !(inset && inset->forceDefaultParagraphs(inset)); - - data = "update " + tostr(accept) + '\n' + data; - bv_->owner()->getDialogs().update("paragraph", data); + case LFUN_PARAGRAPH_UPDATE: + updateParagraphDialog(); break; - } case LFUN_PARAGRAPH_APPLY: setParagraphParams(*bv_, ev.argument); break; - case LFUN_THESAURUS_ENTRY: - { + case LFUN_THESAURUS_ENTRY: { string arg = ev.argument; if (arg.empty()) { - arg = bv_->getLyXText()->selectionAsString(buffer_, + arg = bv_->getLyXText()->selectionAsString(*buffer_, false); // FIXME if (arg.size() > 100 || arg.empty()) { // Get word or selection bv_->getLyXText()->selectWordWhenUnderCursor(lyx::WHOLE_WORD); - arg = bv_->getLyXText()->selectionAsString(buffer_, false); + arg = bv_->getLyXText()->selectionAsString(*buffer_, false); // FIXME: where is getLyXText()->unselect(bv_) ? } } bv_->owner()->getDialogs().show("thesaurus", arg); - } break; + } case LFUN_TRACK_CHANGES: trackChanges(); @@ -1269,25 +1214,19 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & ev_in) break; case LFUN_ACCEPT_ALL_CHANGES: { - bv_->text->setCursor(bv_->buffer()->paragraphs.begin(), 0); + bv_->text()->setCursor(0, 0); #warning FIXME changes - //moveCursorUpdate(false); - while (lyx::find::findNextChange(bv_)) bv_->getLyXText()->acceptChange(); - update(); break; } case LFUN_REJECT_ALL_CHANGES: { - bv_->text->setCursor(bv_->buffer()->paragraphs.begin(), 0); + bv_->text()->setCursor(0, 0); #warning FIXME changes - //moveCursorUpdate(false); - while (lyx::find::findNextChange(bv_)) bv_->getLyXText()->rejectChange(); - update(); break; } @@ -1304,12 +1243,47 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & ev_in) break; } + case LFUN_WORD_FIND: + lyx::find::find(bv_, ev); + break; + + case LFUN_WORD_REPLACE: + lyx::find::replace(bv_, ev); + break; + + case LFUN_MARK_OFF: + cur.clearSelection(); + bv_->update(); + cur.resetAnchor(); + ev.message(N_("Mark off")); + break; + + case LFUN_MARK_ON: + cur.clearSelection(); + cur.mark() = true; + bv_->update(); + cur.resetAnchor(); + ev.message(N_("Mark on")); + break; + + case LFUN_SETMARK: + cur.clearSelection(); + if (cur.mark()) { + ev.message(N_("Mark removed")); + } else { + cur.mark() = true; + ev.message(N_("Mark set")); + } + cur.resetAnchor(); + bv_->update(); + break; + case LFUN_UNKNOWN_ACTION: ev.errorMessage(N_("Unknown function!")); break; default: - return bv_->getLyXText()->dispatch(FuncRequest(ev, bv_)); + return cur.dispatch(ev).dispatched(); } // end of switch return true; @@ -1318,68 +1292,83 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & ev_in) bool BufferView::Pimpl::insertInset(InsetOld * inset, string const & lout) { - // if we are in a locking inset we should try to insert the - // inset there otherwise this is a illegal function now - if (bv_->theLockingInset()) { - if (bv_->theLockingInset()->insetAllowed(inset)) - return bv_->theLockingInset()->insertInset(bv_, inset); - return false; - } - // not quite sure if we want this... - recordUndo(bv_, Undo::ATOMIC); + bv_->text()->recUndo(bv_->text()->cursor().par()); freezeUndo(); - beforeChange(bv_->text); + bv_->cursor().clearSelection(); if (!lout.empty()) { - bv_->text->breakParagraph(bv_->buffer()->paragraphs); + bv_->text()->breakParagraph(bv_->buffer()->paragraphs()); - if (!bv_->text->cursor.par()->empty()) { - bv_->text->cursorLeft(bv_); - bv_->text->breakParagraph(bv_->buffer()->paragraphs); + if (!bv_->text()->cursorPar()->empty()) { + bv_->text()->cursorLeft(bv_); + bv_->text()->breakParagraph(bv_->buffer()->paragraphs()); } string lres = lout; - LyXTextClass const & tclass = buffer_->params.getLyXTextClass(); + LyXTextClass const & tclass = buffer_->params().getLyXTextClass(); bool hasLayout = tclass.hasLayout(lres); - string lay = tclass.defaultLayoutName(); - if (hasLayout != false) { - // layout found - lay = lres; - } else { - // layout not fount using default - lay = tclass.defaultLayoutName(); - } + bv_->text()->setLayout(hasLayout ? lres : tclass.defaultLayoutName()); + bv_->text()->setParagraph(Spacing(), LYX_ALIGN_LAYOUT, string(), 0); + } + bv_->cursor().innerText()->insertInset(inset); + unFreezeUndo(); + return true; +} - bv_->text->setLayout(lay); - bv_->text->setParagraph(0, 0, - 0, 0, - VSpace(VSpace::NONE), VSpace(VSpace::NONE), - Spacing(), - LYX_ALIGN_LAYOUT, - string(), - 0); - } +bool BufferView::Pimpl::ChangeInsets(InsetOld::Code code, + string const & from, string const & to) +{ + bool need_update = false; + CursorSlice cur = bv_->text()->cursor(); + + ParIterator end = bv_->buffer()->par_iterator_end(); + for (ParIterator it = bv_->buffer()->par_iterator_begin(); + it != end; ++it) { + bool changed_inset = false; + for (InsetList::iterator it2 = it->insetlist.begin(); + it2 != it->insetlist.end(); ++it2) { + if (it2->inset->lyxCode() == code) { + InsetCommand * inset = static_cast(it2->inset); + if (inset->getContents() == from) { + inset->setContents(to); + changed_inset = true; + } + } + } + if (changed_inset) { + need_update = true; - bv_->text->insertInset(inset); - update(); + // FIXME - unFreezeUndo(); - return true; + // The test it.size() == 1 was needed to prevent crashes. + // How to set the cursor correctly when it.size() > 1 ?? + if (it.size() == 1) { + bv_->text()->setCursorIntern(bv_->text()->parOffset(it.pit()), 0); + bv_->text()->redoParagraph(bv_->text()->cursorPar()); + } + } + } + bv_->text()->setCursorIntern(cur.par(), cur.pos()); + return need_update; } -void BufferView::Pimpl::updateInset() +void BufferView::Pimpl::updateParagraphDialog() { - if (!available()) + if (!bv_->owner()->getDialogs().visible("paragraph")) return; + Paragraph const & par = *bv_->getLyXText()->cursorPar(); + string data; + params2string(par, data); - // this should not be needed, but it is... - //bv_->text->redoParagraph(bv_->text->cursor.par()); - //bv_->text->fullRebreak(); + // Will the paragraph accept changes from the dialog? + InsetOld * const inset = par.inInset(); + bool const accept = + !(inset && inset->forceDefaultParagraphs(inset)); - update(); - updateScrollbar(); + data = "update " + tostr(accept) + '\n' + data; + bv_->owner()->getDialogs().update("paragraph", data); }