X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBufferView_pimpl.C;h=8144d511db9e24e0b42bd82ad1f4d0b78a362095;hb=de3c8e5b80effa940c92980032389c868f377d6b;hp=97b946aedfd33df953309d8caff27ff36dcffbd4;hpb=70d0ba900118ac7e253c1e1969fd7a3d64ec8e03;p=lyx.git diff --git a/src/BufferView_pimpl.C b/src/BufferView_pimpl.C index 97b946aedf..8144d511db 100644 --- a/src/BufferView_pimpl.C +++ b/src/BufferView_pimpl.C @@ -4,7 +4,7 @@ * Licence details can be found in the file COPYING. * * \author Asger Alstrup - * \author Alfredo Braustein + * \author Alfredo Braunstein * \author Lars Gullik Bjønnes * \author Jean-Marc Lasgouttes * \author Angus Leeming @@ -29,9 +29,10 @@ #include "factory.h" #include "FloatList.h" #include "funcrequest.h" +#include "FuncStatus.h" #include "gettext.h" #include "intl.h" -#include "iterators.h" +#include "insetiterator.h" #include "lyx_cb.h" // added for Dispatch functions #include "lyx_main.h" #include "lyxfind.h" @@ -42,11 +43,13 @@ #include "paragraph.h" #include "paragraph_funcs.h" #include "ParagraphParameters.h" +#include "pariterator.h" +#include "rowpainter.h" #include "undo.h" #include "vspace.h" -#include "insets/insetfloatlist.h" #include "insets/insetref.h" +#include "insets/insettext.h" #include "frontends/Alert.h" #include "frontends/Dialogs.h" @@ -59,29 +62,29 @@ #include "graphics/Previews.h" -#include "mathed/formulabase.h" - #include "support/filetools.h" +#include "support/forkedcontr.h" #include "support/globbing.h" #include "support/path_defines.h" #include "support/tostr.h" +#include "support/types.h" #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::ForkedcallsController; using lyx::support::IsDirWriteable; using lyx::support::MakeDisplayPath; using lyx::support::strToUnsignedInt; using lyx::support::system_lyxdir; using std::endl; +using std::istringstream; using std::make_pair; using std::min; using std::string; @@ -111,9 +114,9 @@ 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), + : bv_(&bv), owner_(owner), buffer_(0), cursor_timeout(400), using_xterm_cursor(false), cursor_(bv) { xsel_cache_.set = false; @@ -160,13 +163,33 @@ 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::setBuffer, this, (Buffer *)0)); } @@ -182,13 +205,10 @@ void BufferView::Pimpl::disconnectBuffer() } -bool BufferView::Pimpl::newFile(string const & filename, - string const & tname, - bool isNamed) +void BufferView::Pimpl::newFile(string const & filename, string const & tname, + bool isNamed) { - Buffer * b = ::newFile(filename, tname, isNamed); - buffer(b); - return true; + setBuffer(::newFile(filename, tname, isNamed)); } @@ -213,14 +233,13 @@ bool BufferView::Pimpl::loadLyXFile(string const & filename, bool tolastfiles) text, 0, 1, _("&Revert"), _("&Switch to document")); if (ret != 0) { - buffer(bufferlist.getBuffer(s)); + setBuffer(bufferlist.getBuffer(s)); return true; - } else { - // FIXME: should be LFUN_REVERT - if (!bufferlist.close(bufferlist.getBuffer(s), false)) - return false; - // Fall through to new load. (Asger) } + // FIXME: should be LFUN_REVERT + if (!bufferlist.close(bufferlist.getBuffer(s), false)) + return false; + // Fall through to new load. (Asger) } Buffer * b; @@ -245,7 +264,7 @@ bool BufferView::Pimpl::loadLyXFile(string const & filename, bool tolastfiles) return false; } - buffer(b); + setBuffer(b); bv_->showErrorList(_("Parse")); if (tolastfiles) @@ -285,50 +304,45 @@ int BufferView::Pimpl::top_y() const } -void BufferView::Pimpl::buffer(Buffer * b) +void BufferView::Pimpl::setBuffer(Buffer * b) { lyxerr[Debug::INFO] << "Setting buffer in BufferView (" << b << ')' << endl; - if (buffer_) { + if (buffer_) disconnectBuffer(); - //delete bv_->text(); - //bv_->setText(0); - } // set current buffer buffer_ = b; + // reset old cursor top_y_ = 0; + cursor_ = LCursor(*bv_); // if we're quitting lyx, don't bother updating stuff if (quitting) return; - // if we are closing the buffer, use the first buffer as current - if (!buffer_) - buffer_ = bufferlist.first(); - if (buffer_) { lyxerr[Debug::INFO] << "Buffer addr: " << buffer_ << endl; connectBuffer(*buffer_); + cursor_.push(buffer_->inset()); + cursor_.resetAnchor(); 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) - resizeCurrentBuffer(); - - // FIXME: needed when ? - fitCursor(); + //if (bv_->text() == 0) + // resizeCurrentBuffer(); // Buffer-dependent dialogs should be updated or // hidden. This should go here because some dialogs (eg ToC) // require bv_->text. owner_->getDialogs().updateBufferDependent(true); + owner_->setLayout(bv_->text()->getPar(0).layout()->name()); } else { lyxerr[Debug::INFO] << " No Buffer!" << endl; + // we are closing the buffer, use the first buffer as current + buffer_ = bufferlist.first(); owner_->getDialogs().hideBufferDependent(); } @@ -339,23 +353,23 @@ void BufferView::Pimpl::buffer(Buffer * b) owner_->updateLayoutChoice(); owner_->updateWindowTitle(); - // Don't forget to update the Layout - if (buffer_) - owner_->setLayout(bv_->text()->cursorPar()->layout()->name()); - - if (lyx::graphics::Previews::activated() && buffer_) + if (buffer_ && lyx::graphics::Previews::status() != LyXRC::PREVIEW_OFF) lyx::graphics::Previews::get().generateBufferPreviews(*buffer_); } bool BufferView::Pimpl::fitCursor() { - lyxerr << "BufferView::Pimpl::fitCursor." << endl; - if (screen().fitCursor(bv_)) { - updateScrollbar(); - return true; - } - return false; + // to get the correct y cursor info + lyxerr << "BufferView::fitCursor" << std::endl; + lyx::par_type const pit = bv_->cursor().bottom().par(); + bv_->text()->redoParagraph(pit); + refreshPar(*bv_, *bv_->text(), pit); + + if (!screen().fitCursor(bv_)) + return false; + updateScrollbar(); + return true; } @@ -373,56 +387,15 @@ void BufferView::Pimpl::redoCurrentBuffer() void BufferView::Pimpl::resizeCurrentBuffer() { lyxerr[Debug::INFO] << "resizeCurrentBuffer" << endl; - - int par = -1; - int selstartpar = -1; - int selendpar = -1; - - pos_type pos = 0; - pos_type selstartpos = 0; - pos_type selendpos = 0; - bool sel = false; - bool mark_set = false; - owner_->busy(true); - owner_->message(_("Formatting document...")); LyXText * text = bv_->text(); - lyxerr << "### resizeCurrentBuffer: text " << text << endl; if (!text) return; - par = bv_->cursor().par(); - pos = bv_->cursor().pos(); - selstartpar = bv_->selStart().par(); - selstartpos = bv_->selStart().pos(); - selendpar = bv_->selEnd().par(); - selendpos = bv_->selEnd().pos(); - sel = bv_->selection().set(); - mark_set = bv_->selection().mark(); - text->textwidth_ = bv_->workWidth(); - text->fullRebreak(); + text->init(bv_); update(); - - if (par != -1) { - bv_->selection().set(true); - // At this point just to avoid the Delete-Empty-Paragraph- - // Mechanism when setting the cursor. - bv_->selection().mark(mark_set); - if (sel) { - text->setCursor(selstartpar, selstartpos); - bv_->resetAnchor(); - text->setCursor(selendpar, selendpos); - bv_->setSelection(); - text->setCursor(par, pos); - } else { - text->setCursor(par, pos); - bv_->resetAnchor(); - bv_->selection().set(false); - } - } - fitCursor(); switchKeyMap(); @@ -439,16 +412,19 @@ void BufferView::Pimpl::updateScrollbar() { if (!bv_->text()) { lyxerr[Debug::GUI] << "no text in updateScrollbar" << endl; + lyxerr << "no text in updateScrollbar" << endl; workarea().setScrollbarParams(0, 0, 0); return; } LyXText const & t = *bv_->text(); - lyxerr[Debug::GUI] << "Updating scrollbar: h " << t.height << ", top_y() " - << top_y() << ", default height " << defaultRowHeight() << endl; + lyxerr[Debug::GUI] + << "Updating scrollbar: height: " << t.height() + << " top_y: " << top_y() + << " default height " << defaultRowHeight() << endl; - workarea().setScrollbarParams(t.height, top_y(), defaultRowHeight()); + workarea().setScrollbarParams(t.height(), top_y(), defaultRowHeight()); } @@ -471,11 +447,14 @@ void BufferView::Pimpl::scrollDocView(int value) int const first = top_y() + height; int const last = top_y() + workarea().workHeight() - height; + bv_->cursor().reset(bv_->buffer()->inset()); LyXText * text = bv_->text(); - if (text->cursorY() < first) - text->setCursorFromCoordinates(0, first); - else if (text->cursorY() > last) - text->setCursorFromCoordinates(0, last); + int y = text->cursorY(bv_->cursor().front()); + if (y < first) + y = first; + if (y > last) + y = last; + text->setCursorFromCoordinates(bv_->cursor(), 0, y); owner_->updateLayoutChoice(); } @@ -493,13 +472,13 @@ void BufferView::Pimpl::scroll(int lines) 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); + new_top_y = std::min(t->height() - 4 * line_height, new_top_y); new_top_y = std::max(0, new_top_y); scrollDocView(new_top_y); // Update the scrollbar. - workarea().setScrollbarParams(t->height, top_y(), defaultRowHeight()); + workarea().setScrollbarParams(t->height(), top_y(), defaultRowHeight()); } @@ -529,24 +508,24 @@ void BufferView::Pimpl::selectionRequested() if (!available()) return; - LyXText * text = bv_->getLyXText(); + LCursor & cur = bv_->cursor(); - if (!bv_->selection().set()) { + if (!cur.selection()) { xsel_cache_.set = false; return; } if (!xsel_cache_.set || - bv_->cursor() != xsel_cache_.cursor || - bv_->anchor() != xsel_cache_.anchor) + cur.back() != xsel_cache_.cursor || + cur.anchor_.back() != xsel_cache_.anchor) { - xsel_cache_.cursor = bv_->cursor(); - xsel_cache_.anchor = bv_->anchor(); - xsel_cache_.set = bv_->selection().set(); - sel = text->selectionAsString(*bv_->buffer(), false); + xsel_cache_.cursor = cur.back(); + xsel_cache_.anchor = cur.anchor_.back(); + xsel_cache_.set = cur.selection(); + sel = cur.selectionAsString(false); if (!sel.empty()) workarea().putClipboard(sel); - } + } } @@ -554,7 +533,7 @@ void BufferView::Pimpl::selectionLost() { if (available()) { screen().hideCursor(); - bv_->clearSelection(); + bv_->cursor().clearSelection(); xsel_cache_.set = false; } } @@ -572,11 +551,9 @@ void BufferView::Pimpl::workAreaResize() work_area_width = workarea().workWidth(); work_area_height = workarea().workHeight(); - if (buffer_ != 0) { - if (widthChange) { - // The visible LyXView need a resize - resizeCurrentBuffer(); - } + if (buffer_ && widthChange) { + // The visible LyXView need a resize + resizeCurrentBuffer(); } if (widthChange || heightChange) @@ -590,33 +567,43 @@ void BufferView::Pimpl::workAreaResize() void BufferView::Pimpl::update() { - //lyxerr << "BufferView::update()" << endl; + //lyxerr << "BufferView::Pimpl::update(), buffer: " << buffer_ << endl; // fix cursor coordinate cache in case something went wrong // check needed to survive LyX startup - if (bv_->getLyXText()) { + if (buffer_) { + // update macro store + buffer_->buildMacros(); + // update all 'visible' paragraphs - ParagraphList::iterator beg; - ParagraphList::iterator end; + lyx::par_type beg, end; getParsInRange(buffer_->paragraphs(), top_y(), top_y() + workarea().workHeight(), beg, end); bv_->text()->redoParagraphs(beg, end); + + // and the scrollbar updateScrollbar(); } screen().redraw(*bv_); + bv_->owner()->view_state_changed(); } // Callback for cursor timer void BufferView::Pimpl::cursorToggle() { - if (!buffer_) { - cursor_timeout.restart(); - return; + if (buffer_) { + screen().toggleCursor(*bv_); + + // Use this opportunity to deal with any child processes that + // have finished but are waiting to communicate this fact + // to the rest of LyX. + ForkedcallsController & fcc = ForkedcallsController::get(); + if (fcc.processesCompleted()) + fcc.handleCompletedProcesses(); } - screen().toggleCursor(*bv_); cursor_timeout.restart(); } @@ -633,12 +620,13 @@ Change const BufferView::Pimpl::getCurrentChange() return Change(Change::UNCHANGED); LyXText * text = bv_->getLyXText(); + LCursor & cur = bv_->cursor(); - if (!bv_->selection().set()) + if (!cur.selection()) return Change(Change::UNCHANGED); - return text->getPar(bv_->selStart()) - ->lookupChangeFull(bv_->selStart().pos()); + return text->getPar(cur.selBegin().par()). + lookupChangeFull(cur.selBegin().pos()); } @@ -646,9 +634,10 @@ void BufferView::Pimpl::savePosition(unsigned int i) { if (i >= saved_positions_num) return; + BOOST_ASSERT(bv_->cursor().inTexted()); saved_positions[i] = Position(buffer_->fileName(), - bv_->text()->cursorPar()->id(), - bv_->text()->cursor().pos()); + bv_->cursor().paragraph().id(), + bv_->cursor().pos()); if (i > 0) owner_->message(bformat(_("Saved bookmark %1$s"), tostr(i))); } @@ -661,7 +650,7 @@ void BufferView::Pimpl::restorePosition(unsigned int i) string const fname = saved_positions[i].filename; - bv_->clearSelection(); + bv_->cursor().clearSelection(); if (fname != buffer_->fileName()) { Buffer * b = 0; @@ -672,15 +661,15 @@ void BufferView::Pimpl::restorePosition(unsigned int i) ::loadLyXFile(b, fname); // don't ask, just load it } if (b) - buffer(b); + setBuffer(b); } ParIterator par = buffer_->getParFromID(saved_positions[i].par_id); if (par == buffer_->par_iterator_end()) return; - bv_->text()->setCursor(par.pit(), - min(par->size(), saved_positions[i].par_pos)); + bv_->text()->setCursor(bv_->cursor(), par.pit(), + min(par->size(), saved_positions[i].par_pos)); if (i > 0) owner_->message(bformat(_("Moved to bookmark %1$s"), tostr(i))); @@ -713,9 +702,11 @@ void BufferView::Pimpl::center() { LyXText * text = bv_->text(); - bv_->clearSelection(); + bv_->cursor().clearSelection(); int const half_height = workarea().workHeight() / 2; - int new_y = std::max(0, text->cursorY() - half_height); + int new_y = text->cursorY(bv_->cursor().front()) - half_height; + if (new_y < 0) + new_y = 0; // FIXME: look at this comment again ... // This updates top_y() but means the fitCursor() call @@ -725,7 +716,7 @@ void BufferView::Pimpl::center() // to do it manually. Any operation that does a 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() + // pretty obfuscated way of updating text->top_y() top_y(new_y); } @@ -736,58 +727,27 @@ void BufferView::Pimpl::stuffClipboard(string const & stuff) const } -InsetOld * BufferView::Pimpl::getInsetByCode(InsetOld::Code code) +InsetBase * BufferView::Pimpl::getInsetByCode(InsetBase::Code code) { -#if 0 - CursorSlice cursor = bv_->getLyXText()->cursor; - Buffer::inset_iterator it = - find_if(Buffer::inset_iterator( - cursorPar(), cursor().pos()), - buffer_->inset_iterator_end(), - lyx::compare_memfun(&Inset::lyxCode, code)); - return it != buffer_->inset_iterator_end() ? (*it) : 0; -#else +#ifdef WITH_WARNINGS +#warning Does not work for mathed. (Still true?) +#endif // Ok, this is a little bit too brute force but it // should work for now. Better infrastructure is coming. (Lgb) - - Buffer * b = bv_->buffer(); - LyXText * text = bv_->getLyXText(); - - Buffer::inset_iterator beg = b->inset_iterator_begin(); - Buffer::inset_iterator end = b->inset_iterator_end(); - - bool cursor_par_seen = false; - - for (; beg != end; ++beg) { - if (beg.getPar() == text->cursorPar()) { - cursor_par_seen = true; - } - if (cursor_par_seen) { - if (beg.getPar() == text->cursorPar() - && beg.getPos() >= text->cursor().pos()) { - break; - } else if (beg.getPar() != text->cursorPar()) { - break; - } - } - - } - if (beg != end) { - // Now find the first inset that matches code. - for (; beg != end; ++beg) { - if (beg->lyxCode() == code) { - return &(*beg); - } - } + LCursor & cur = bv_->cursor(); + DocIterator it = cur; + for (it.forwardInset(); it; it.forwardInset()) { + BOOST_ASSERT(it.nextInset()); + if (it.nextInset()->lyxCode() == code) + return it.nextInset(); } return 0; -#endif } -void BufferView::Pimpl::MenuInsertLyXFile(string const & filen) +void BufferView::Pimpl::MenuInsertLyXFile(string const & filenm) { - string filename = filen; + string filename = filenm; if (filename.empty()) { // Launch a file browser @@ -841,8 +801,8 @@ void BufferView::Pimpl::MenuInsertLyXFile(string const & filen) void BufferView::Pimpl::trackChanges() { - Buffer * buf(bv_->buffer()); - bool const tracking(buf->params().tracking_changes); + Buffer * buf = bv_->buffer(); + bool const tracking = buf->params().tracking_changes; if (!tracking) { ParIterator const end = buf->par_iterator_end(); @@ -854,8 +814,10 @@ void BufferView::Pimpl::trackChanges() buf->undostack().clear(); } else { update(); - bv_->text()->setCursor(0, 0); + bv_->text()->setCursor(bv_->cursor(), 0, 0); +#ifdef WITH_WARNINGS #warning changes FIXME +#endif bool found = lyx::find::findNextChange(bv_); if (found) { owner_->getDialogs().show("changes"); @@ -871,222 +833,208 @@ void BufferView::Pimpl::trackChanges() buf->redostack().clear(); } -#warning remove me -LCursor theTempCursor(0); - -namespace { - InsetOld * insetFromCoords(BufferView * bv, int x, int y) - { - lyxerr << "insetFromCoords" << endl; - LyXText * text = bv->text(); - InsetOld * inset = 0; - theTempCursor = LCursor(bv); - 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(static_cast(inset)); - } - lyxerr << "theTempCursor: " << theTempCursor << endl; - return inset; +bool BufferView::Pimpl::workAreaDispatch(FuncRequest const & cmd0) +{ + //lyxerr << "BufferView::Pimpl::workAreaDispatch: request: " + // << cmd << std::endl; + // this is only called for mouse related events including + // LFUN_FILE_OPEN generated by drag-and-drop. + FuncRequest cmd = cmd0; + + // handle drag&drop + if (cmd.action == LFUN_FILE_OPEN) { + owner_->dispatch(cmd); + return true; } -} + cmd.y += bv_->top_y(); + if (!bv_->buffer()) + return false; + LCursor cur(*bv_); + cur.push(bv_->buffer()->inset()); + cur.selection() = bv_->cursor().selection(); -bool BufferView::Pimpl::workAreaDispatch(FuncRequest const & cmd) -{ - switch (cmd.action) { - case LFUN_MOUSE_MOTION: { - if (!available()) - return false; - FuncRequest cmd1 = cmd; - UpdatableInset * inset = bv_->fullCursor().innerInset(); - DispatchResult res; - if (inset) { - cmd1.x -= inset->x(); - cmd1.y -= inset->y(); - res = inset->dispatch(*bv_, cmd1); - } else { - cmd1.y += bv_->top_y(); - res = bv_->fullCursor().innerText()->dispatch(*bv_, cmd1); - } + // Doesn't go through lyxfunc, so we need to update + // the layout choice etc. ourselves - if (bv_->fitCursor() || res.update()) { - bv_->update(); - bv_->fullCursor().updatePos(); - } + // e.g. Qt mouse press when no buffer + if (!available()) + return false; - return true; + screen().hideCursor(); + + // Either the inset under the cursor or the + // surrounding LyXText will handle this event. + + // Build temporary cursor. + InsetBase * inset = bv_->text()->editXY(cur, cmd.x, cmd.y); + lyxerr << "hit inset at tip: " << inset << endl; + lyxerr << "created temp cursor:\n" << cur << endl; + + // Put anchor at the same position. + cur.resetAnchor(); + + // Try to dispatch to an non-editable inset near this position + // 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)' + DispatchResult res; + 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 (!res.dispatched()) + res = cur.dispatch(cmd); + + if (res.dispatched()) { + // Redraw if requested or necessary. + if (fitCursor() || res.update()) + update(); } - case LFUN_MOUSE_PRESS: - case LFUN_MOUSE_RELEASE: - case LFUN_MOUSE_DOUBLE: - case LFUN_MOUSE_TRIPLE: { - // We pass those directly to the Bufferview, since - // otherwise selection handling breaks down + // see workAreaKeyPress + cursor_timeout.restart(); + screen().showCursor(*bv_); - // Doesn't go through lyxfunc, so we need to update - // the layout choice etc. ourselves + // skip these when selecting + if (cmd.action != LFUN_MOUSE_MOTION) { + owner_->updateLayoutChoice(); + owner_->updateToolbar(); + } - // e.g. Qt mouse press when no buffer - if (!available()) - return false; + // 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 true; +} - screen().hideCursor(); - // 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(*bv_, cmd2); - if (res.update()) { - bv_->update(); - bv_->fullCursor().updatePos(); - } - res.update(false); - switch (res.val()) { - case FINISHED: - case FINISHED_RIGHT: - case FINISHED_UP: - case FINISHED_DOWN: - theTempCursor.pop(); - bv_->fullCursor(theTempCursor); - bv_->fullCursor().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; - } - } +FuncStatus BufferView::Pimpl::getStatus(FuncRequest const & cmd) +{ + Buffer * buf = bv_->buffer(); - // otherwise set cursor to surrounding LyXText - if (!res.dispatched()) { - lyxerr << "temp cursor is: " << theTempCursor << endl; - lyxerr << "dispatching " << cmd - << " to surrounding LyXText " - << theTempCursor.innerText() << endl; - bv_->fullCursor(theTempCursor); - FuncRequest cmd1 = cmd; - cmd1.y += bv_->top_y(); - res = bv_->fullCursor().innerText()->dispatch(*bv_, cmd1); - if (bv_->fitCursor() || res.update()) - bv_->update(); - - //return DispatchResult(true, true); - } - // see workAreaKeyPress - cursor_timeout.restart(); - screen().showCursor(*bv_); + FuncStatus flag; - // skip these when selecting - if (cmd.action != LFUN_MOUSE_MOTION) { - owner_->updateLayoutChoice(); - owner_->updateToolbar(); - } + switch (cmd.action) { - // 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 true; - } + case LFUN_UNDO: + flag.enabled(!buf->undostack().empty()); + break; + case LFUN_REDO: + flag.enabled(!buf->redostack().empty()); + break; + case LFUN_FILE_INSERT: + case LFUN_FILE_INSERT_ASCII_PARA: + case LFUN_FILE_INSERT_ASCII: + case LFUN_FONT_STATE: + case LFUN_INSERT_LABEL: + case LFUN_BOOKMARK_SAVE: + case LFUN_REF_GOTO: + case LFUN_WORD_FIND: + case LFUN_WORD_REPLACE: + case LFUN_MARK_OFF: + case LFUN_MARK_ON: + case LFUN_SETMARK: + case LFUN_CENTER: + case LFUN_BEGINNINGBUFSEL: + case LFUN_ENDBUFSEL: + flag.enabled(true); + break; + case LFUN_BOOKMARK_GOTO: + flag.enabled(bv_->isSavedPosition(strToUnsignedInt(cmd.argument))); + break; + case LFUN_TRACK_CHANGES: + flag.enabled(true); + flag.setOnOff(buf->params().tracking_changes); + break; + case LFUN_MERGE_CHANGES: + case LFUN_ACCEPT_CHANGE: // what about these two + case LFUN_REJECT_CHANGE: // what about these two + case LFUN_ACCEPT_ALL_CHANGES: + case LFUN_REJECT_ALL_CHANGES: + flag.enabled(buf && buf->params().tracking_changes); + break; default: - owner_->dispatch(cmd); - return true; + flag.enabled(false); } + + return flag; } -bool BufferView::Pimpl::dispatch(FuncRequest const & ev) + +bool BufferView::Pimpl::dispatch(FuncRequest const & cmd) { + //lyxerr << "BufferView::Pimpl::dispatch cmd: " << cmd << std::endl; // Make sure that the cached BufferView is correct. lyxerr[Debug::ACTION] << "BufferView::Pimpl::Dispatch:" - << " action[" << ev.action << ']' - << " arg[" << ev.argument << ']' - << " x[" << ev.x << ']' - << " y[" << ev.y << ']' - << " button[" << ev.button() << ']' + << " action[" << cmd.action << ']' + << " arg[" << cmd.argument << ']' + << " x[" << cmd.x << ']' + << " y[" << cmd.y << ']' + << " button[" << cmd.button() << ']' << endl; - LyXTextClass const & tclass = buffer_->params().getLyXTextClass(); + LCursor & cur = bv_->cursor(); - switch (ev.action) { + switch (cmd.action) { - case LFUN_SCROLL_INSET: - // this is not handled here as this function is only active - // if we have a locking_inset and that one is (or contains) - // a tabular-inset + case LFUN_UNDO: + if (available()) { + cur.message(_("Undo")); + cur.clearSelection(); + if (!textUndo(*bv_)) + cur.message(_("No further undo information")); + update(); + switchKeyMap(); + } + break; + + case LFUN_REDO: + if (available()) { + cur.message(_("Redo")); + cur.clearSelection(); + if (!textRedo(*bv_)) + cur.message(_("No further redo information")); + update(); + switchKeyMap(); + } break; case LFUN_FILE_INSERT: - MenuInsertLyXFile(ev.argument); + MenuInsertLyXFile(cmd.argument); break; case LFUN_FILE_INSERT_ASCII_PARA: - InsertAsciiFile(bv_, ev.argument, true); + InsertAsciiFile(bv_, cmd.argument, true); break; case LFUN_FILE_INSERT_ASCII: - InsertAsciiFile(bv_, ev.argument, false); + InsertAsciiFile(bv_, cmd.argument, false); break; case LFUN_FONT_STATE: - owner_->getLyXFunc().setMessage(currentState(bv_)); + cur.message(cur.currentState()); break; - case LFUN_INSERT_LABEL: { - // Try and generate a valid label - string const contents = ev.argument.empty() ? - getPossibleLabel(*bv_) : ev.argument; - InsetCommandParams icp("label", contents); - string data = InsetCommandMailer::params2string("label", icp); - owner_->getDialogs().show("label", data, 0); - break; - } - case LFUN_BOOKMARK_SAVE: - savePosition(strToUnsignedInt(ev.argument)); + savePosition(strToUnsignedInt(cmd.argument)); break; case LFUN_BOOKMARK_GOTO: - restorePosition(strToUnsignedInt(ev.argument)); + restorePosition(strToUnsignedInt(cmd.argument)); break; case LFUN_REF_GOTO: { - string label = ev.argument; + string label = cmd.argument; if (label.empty()) { InsetRef * inset = - static_cast(getInsetByCode(InsetOld::REF_CODE)); + static_cast(getInsetByCode(InsetBase::REF_CODE)); if (inset) { label = inset->getContents(); savePosition(0); @@ -1095,102 +1043,6 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & ev) if (!label.empty()) bv_->gotoLabel(label); - } - break; - - // --- accented characters --------------------------- - - case LFUN_UMLAUT: - case LFUN_CIRCUMFLEX: - case LFUN_GRAVE: - case LFUN_ACUTE: - case LFUN_TILDE: - case LFUN_CEDILLA: - case LFUN_MACRON: - case LFUN_DOT: - case LFUN_UNDERDOT: - case LFUN_UNDERBAR: - case LFUN_CARON: - case LFUN_SPECIAL_CARON: - case LFUN_BREVE: - case LFUN_TIE: - case LFUN_HUNG_UMLAUT: - case LFUN_CIRCLE: - case LFUN_OGONEK: - if (ev.argument.empty()) { - // As always... - owner_->getLyXFunc().handleKeyFunc(ev.action); - } else { - owner_->getLyXFunc().handleKeyFunc(ev.action); - owner_->getIntl().getTransManager() - .TranslateAndInsert(ev.argument[0], bv_->getLyXText()); - update(); - } - break; - - case LFUN_MATH_MACRO: - case LFUN_MATH_DELIM: - case LFUN_INSERT_MATRIX: - case LFUN_INSERT_MATH: - 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(*bv_, ev); - break; - - case LFUN_INSET_INSERT: { - // Same as above. - BOOST_ASSERT(false); - InsetOld * inset = createInset(bv_, ev); - if (!inset || !insertInset(inset)) - delete inset; - break; - } - - case LFUN_FLOAT_LIST: - if (tclass.floats().typeExist(ev.argument)) { - InsetOld * inset = new InsetFloatList(ev.argument); - if (!insertInset(inset, tclass.defaultLayoutName())) - delete inset; - } else { - lyxerr << "Non-existent float type: " - << ev.argument << endl; - } - break; - - case LFUN_LAYOUT_PARAGRAPH: { - string data; - params2string(*bv_->getLyXText()->cursorPar(), data); - data = "show\n" + data; - bv_->owner()->getDialogs().show("paragraph", data); - break; - } - - case LFUN_PARAGRAPH_UPDATE: - updateParagraphDialog(); - break; - - case LFUN_PARAGRAPH_APPLY: - setParagraphParams(*bv_, ev.argument); - break; - - case LFUN_THESAURUS_ENTRY: { - string arg = ev.argument; - - if (arg.empty()) { - 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); - // FIXME: where is getLyXText()->unselect(bv_) ? - } - } - - bv_->owner()->getDialogs().show("thesaurus", arg); break; } @@ -1203,161 +1055,82 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & ev) break; case LFUN_ACCEPT_ALL_CHANGES: { - bv_->text()->setCursor(0, 0); + bv_->cursor().reset(bv_->buffer()->inset()); +#ifdef WITH_WARNINGS #warning FIXME changes +#endif while (lyx::find::findNextChange(bv_)) - bv_->getLyXText()->acceptChange(); + bv_->getLyXText()->acceptChange(bv_->cursor()); update(); break; } case LFUN_REJECT_ALL_CHANGES: { - bv_->text()->setCursor(0, 0); + bv_->cursor().reset(bv_->buffer()->inset()); +#ifdef WITH_WARNINGS #warning FIXME changes +#endif while (lyx::find::findNextChange(bv_)) - bv_->getLyXText()->rejectChange(); - update(); - break; - } - - case LFUN_ACCEPT_CHANGE: { - bv_->getLyXText()->acceptChange(); - update(); - break; - } - - case LFUN_REJECT_CHANGE: { - bv_->getLyXText()->rejectChange(); - update(); + bv_->getLyXText()->rejectChange(bv_->cursor()); break; } case LFUN_WORD_FIND: - lyx::find::find(bv_, ev); + lyx::find::find(bv_, cmd); break; case LFUN_WORD_REPLACE: - lyx::find::replace(bv_, ev); + lyx::find::replace(bv_, cmd); break; case LFUN_MARK_OFF: - bv_->clearSelection(); - bv_->update(); - bv_->resetAnchor(); - ev.message(N_("Mark off")); + cur.clearSelection(); + cur.resetAnchor(); + cur.message(N_("Mark off")); break; case LFUN_MARK_ON: - bv_->clearSelection(); - bv_->selection().mark(true); - bv_->update(); - bv_->resetAnchor(); - ev.message(N_("Mark on")); + cur.clearSelection(); + cur.mark() = true; + cur.resetAnchor(); + cur.message(N_("Mark on")); break; case LFUN_SETMARK: - bv_->clearSelection(); - if (bv_->selection().mark()) { - ev.message(N_("Mark removed")); + cur.clearSelection(); + if (cur.mark()) { + cur.mark() = false; + cur.message(N_("Mark removed")); } else { - bv_->selection().mark(true); - ev.message(N_("Mark set")); + cur.mark() = true; + cur.message(N_("Mark set")); } - bv_->resetAnchor(); - bv_->update(); + cur.resetAnchor(); break; - case LFUN_UNKNOWN_ACTION: - ev.errorMessage(N_("Unknown function!")); + case LFUN_CENTER: + bv_->center(); break; - default: - return bv_->getLyXText()->dispatch(*bv_, ev).dispatched(); - } // end of switch - - return true; -} - - -bool BufferView::Pimpl::insertInset(InsetOld * inset, string const & lout) -{ - // not quite sure if we want this... - bv_->text()->recUndo(bv_->text()->cursor().par()); - freezeUndo(); - - bv_->clearSelection(); - if (!lout.empty()) { - 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(); - bool hasLayout = tclass.hasLayout(lres); - - bv_->text()->setLayout(hasLayout ? lres : tclass.defaultLayoutName()); - bv_->text()->setParagraph(Spacing(), LYX_ALIGN_LAYOUT, string(), 0); - } - bv_->fullCursor().innerText()->insertInset(inset); - unFreezeUndo(); - return true; -} - - -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; + case LFUN_BEGINNINGBUFSEL: + bv_->cursor().reset(bv_->buffer()->inset()); + if (!cur.selection()) + cur.resetAnchor(); + bv_->text()->cursorTop(cur); + finishUndo(); + break; - // FIXME + case LFUN_ENDBUFSEL: + bv_->cursor().reset(bv_->buffer()->inset()); + if (!cur.selection()) + cur.resetAnchor(); + bv_->text()->cursorBottom(cur); + finishUndo(); + break; - // 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()); - } - } + default: + return false; } - bv_->text()->setCursorIntern(cur.par(), cur.pos()); - return need_update; -} - -void BufferView::Pimpl::updateParagraphDialog() -{ - if (!bv_->owner()->getDialogs().visible("paragraph")) - return; - Paragraph const & par = *bv_->getLyXText()->cursorPar(); - 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); + return true; }