X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBufferView.C;h=01cfc41d8eef8fbf3e737869f29d0133340a3e2b;hb=e94889a041628203c50b66b9a4add63210de6928;hp=8dfbdbb964d2520716b03903697603291963a26b;hpb=7fa3f39b0de1b3f72fdc402214a6e9293723f25a;p=lyx.git diff --git a/src/BufferView.C b/src/BufferView.C index 8dfbdbb964..01cfc41d8e 100644 --- a/src/BufferView.C +++ b/src/BufferView.C @@ -1,75 +1,80 @@ /** * \file BufferView.C - * Copyright 1995-2002 the LyX Team - * Read the file COPYING + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. * + * \author Alfredo Braunstein * \author Lars Gullik Bjønnes - * \author John Levon + * \author John Levon + * \author André Pönitz + * \author Jürgen Vigna + * + * Full author contact details are available in file CREDITS. */ #include #include "BufferView.h" -#include "BufferView_pimpl.h" -#include "LaTeX.h" -#include "ParagraphParameters.h" -#include "WordLangTuple.h" #include "buffer.h" #include "bufferlist.h" +#include "bufferparams.h" +#include "BufferView_pimpl.h" +#include "CutAndPaste.h" +#include "coordcache.h" #include "debug.h" +#include "funcrequest.h" +#include "FuncStatus.h" #include "gettext.h" -#include "errorlist.h" -#include "iterators.h" +#include "insetiterator.h" #include "language.h" -#include "lyxcursor.h" -#include "lyxlex.h" +#include "lyxlayout.h" #include "lyxtext.h" -#include "undo_funcs.h" -#include "changes.h" +#include "lyxtextclass.h" +#include "paragraph.h" #include "paragraph_funcs.h" +#include "pariterator.h" +#include "texrow.h" +#include "undo.h" +#include "WordLangTuple.h" #include "frontends/Alert.h" #include "frontends/Dialogs.h" #include "frontends/LyXView.h" -#include "frontends/WorkArea.h" #include "frontends/screen.h" +#include "frontends/WorkArea.h" #include "insets/insetcommand.h" // ChangeRefs -#include "insets/updatableinset.h" +#include "insets/insettext.h" + +using lyx::support::bformat; -#include "support/FileInfo.h" -#include "support/filetools.h" -#include "support/types.h" -#include "support/lyxalgo.h" // lyx_count +using lyx::cap::setSelectionRange; + +using std::distance; +using std::find; +using std::string; +using std::swap; +using std::vector; -#include extern BufferList bufferlist; -using lyx::pos_type; -using namespace lyx::support; -using std::pair; -using std::endl; -using std::ifstream; -using std::vector; -using std::find; -using std::count_if; +BufferView::BufferView(LyXView * owner, int width, int height) + : pimpl_(new Pimpl(*this, owner, width, height)) +{} -BufferView::BufferView(LyXView * owner, int xpos, int ypos, - int width, int height) - : pimpl_(new Pimpl(this, owner, xpos, ypos, width, height)) +BufferView::~BufferView() { - text = 0; + delete pimpl_; } -BufferView::~BufferView() +void BufferView::unsetXSel() { - delete text; - delete pimpl_; + pimpl_->xsel_cache_.set = false; } @@ -97,15 +102,15 @@ Painter & BufferView::painter() const } -void BufferView::buffer(Buffer * b) +void BufferView::setBuffer(Buffer * b) { - pimpl_->buffer(b); + pimpl_->setBuffer(b); } -bool BufferView::newFile(string const & fn, string const & tn, bool named) +void BufferView::newFile(string const & fn, string const & tn, bool named) { - return pimpl_->newFile(fn, tn, named); + pimpl_->newFile(fn, tn, named); } @@ -130,21 +135,15 @@ void BufferView::resize() } -void BufferView::repaint() -{ - pimpl_->repaint(); -} - - bool BufferView::fitCursor() { return pimpl_->fitCursor(); } -void BufferView::update() +void BufferView::update(Update::flags flags) { - pimpl_->update(); + pimpl_->update(flags); } @@ -160,12 +159,6 @@ void BufferView::scrollDocView(int value) } -void BufferView::redoCurrentBuffer() -{ - pimpl_->redoCurrentBuffer(); -} - - bool BufferView::available() const { return pimpl_->available(); @@ -178,12 +171,6 @@ Change const BufferView::getCurrentChange() } -void BufferView::beforeChange(LyXText * text) -{ - pimpl_->beforeChange(text); -} - - void BufferView::savePosition(unsigned int i) { pimpl_->savePosition(i); @@ -201,43 +188,23 @@ bool BufferView::isSavedPosition(unsigned int i) return pimpl_->isSavedPosition(i); } - -void BufferView::update(LyXText * text, UpdateCodes f) -{ - pimpl_->update(text, f); -} - - -void BufferView::update(UpdateCodes f) +void BufferView::saveSavedPositions() { - pimpl_->update(f); + return pimpl_->saveSavedPositions(); } - void BufferView::switchKeyMap() { pimpl_->switchKeyMap(); } -void BufferView::insetUnlock() -{ - pimpl_->insetUnlock(); -} - - int BufferView::workWidth() const { return pimpl_->workarea().workWidth(); } -void BufferView::toggleSelection(bool b) -{ - pimpl_->toggleSelection(b); -} - - void BufferView::center() { pimpl_->center(); @@ -256,11 +223,9 @@ void BufferView::stuffClipboard(string const & stuff) const } -BufferView::UpdateCodes operator|(BufferView::UpdateCodes uc1, - BufferView::UpdateCodes uc2) +FuncStatus BufferView::getStatus(FuncRequest const & cmd) { - return static_cast - (static_cast(uc1) | static_cast(uc2)); + return pimpl_->getStatus(cmd); } @@ -270,85 +235,54 @@ bool BufferView::dispatch(FuncRequest const & ev) } -void BufferView::scroll(int lines) +void BufferView::selectionRequested() { - pimpl_->scroll(lines); + pimpl_->selectionRequested(); } -// Inserts a file into current document -bool BufferView::insertLyXFile(string const & filen) - // - // Copyright CHT Software Service GmbH - // Uwe C. Schroeder - // - // Insert a LyXformat - file into current buffer - // - // Moved from lyx_cb.C (Lgb) +void BufferView::selectionLost() { - if (filen.empty()) - return false; - - string const fname = MakeAbsPath(filen); - - // check if file exist - FileInfo const fi(fname); - - if (!fi.readable()) { - string const file = MakeDisplayPath(fname, 50); - string const text = - bformat(_("The specified document\n%1$s\ncould not be read."), file); - Alert::error(_("Could not read document"), text); - return false; - } + pimpl_->selectionLost(); +} - beforeChange(text); - ifstream ifs(fname.c_str()); - if (!ifs) { - string const file = MakeDisplayPath(fname, 50); - string const text = - bformat(_("Could not open the specified document %1$s\n"), file); - Alert::error(_("Could not open file"), text); - return false; - } +void BufferView::workAreaResize() +{ + pimpl_->workAreaResize(); +} - int const c = ifs.peek(); - LyXLex lex(0, 0); - lex.setStream(ifs); +void BufferView::workAreaKeyPress(LyXKeySymPtr key, key_modifier::state state) +{ + pimpl_->workAreaKeyPress(key, state); +} - bool res = true; - text->breakParagraph(buffer()->paragraphs); +bool BufferView::workAreaDispatch(FuncRequest const & ev) +{ + return pimpl_->workAreaDispatch(ev); +} - if (c == '#') { - // FIXME: huh ? No we won't ! - lyxerr[Debug::INFO] << "Will insert file with header" << endl; - res = buffer()->readFile(lex, fname, ParagraphList::iterator(text->cursor.par())); - } else { - lyxerr[Debug::INFO] << "Will insert file without header" - << endl; - res = buffer()->readBody(lex, ParagraphList::iterator(text->cursor.par())); - } - resize(); - return res; +void BufferView::scroll(int lines) +{ + pimpl_->scroll(lines); } void BufferView::showErrorList(string const & action) const { if (getErrorList().size()) { - string const title = bformat(_("LyX: %1$s errors (%2$s)"), action, buffer()->fileName()); + string const title = bformat(_("%1$s Errors (%2$s)"), + action, buffer()->fileName()); owner()->getDialogs().show("errorlist", title); pimpl_->errorlist_.clear(); } } -ErrorList const & -BufferView::getErrorList() const +ErrorList const & BufferView::getErrorList() const { return pimpl_->errorlist_; } @@ -359,364 +293,147 @@ void BufferView::setCursorFromRow(int row) int tmpid = -1; int tmppos = -1; - buffer()->texrow.getIdFromRow(row, tmpid, tmppos); - - ParagraphList::iterator texrowpar; + buffer()->texrow().getIdFromRow(row, tmpid, tmppos); - if (tmpid == -1) { - texrowpar = text->ownerParagraphs().begin(); - tmppos = 0; - } else { - texrowpar = buffer()->getParFromID(tmpid).pit(); - } - text->setCursor(texrowpar, tmppos); -} - - -bool BufferView::insertInset(InsetOld * inset, string const & lout) -{ - return pimpl_->insertInset(inset, lout); + if (tmpid == -1) + text()->setCursor(cursor(), 0, 0); + else + text()->setCursor(cursor(), buffer()->getParFromID(tmpid).pit(), tmppos); } void BufferView::gotoLabel(string const & label) { - for (Buffer::inset_iterator it = buffer()->inset_iterator_begin(); - it != buffer()->inset_iterator_end(); ++it) { + for (InsetIterator it = inset_iterator_begin(buffer()->inset()); it; ++it) { vector labels; - it->getLabelList(labels); - if (find(labels.begin(),labels.end(),label) - != labels.end()) { - beforeChange(text); - text->setCursor(it.getPar(), it.getPos()); - text->selection.cursor = text->cursor; - update(text, BufferView::SELECT); + it->getLabelList(*buffer(), labels); + if (find(labels.begin(),labels.end(),label) != labels.end()) { + setCursor(it); + update(); return; } } } -void BufferView::undo() -{ - if (!available()) - return; - - owner()->message(_("Undo")); - beforeChange(text); - update(text, BufferView::SELECT); - if (!textUndo(this)) - owner()->message(_("No further undo information")); - else - update(text, BufferView::SELECT); - switchKeyMap(); -} - - -void BufferView::redo() +void BufferView::hideCursor() { - if (!available()) - return; - - owner()->message(_("Redo")); - beforeChange(text); - update(text, BufferView::SELECT); - if (!textRedo(this)) - owner()->message(_("No further redo information")); - else - update(text, BufferView::SELECT); - switchKeyMap(); + screen().hideCursor(); } - -// these functions are for the spellchecker -WordLangTuple const BufferView::nextWord(float & value) +LyXText * BufferView::getLyXText() { - if (!available()) { - value = 1; - return WordLangTuple(); - } - - return text->selectNextWordToSpellcheck(value); + LyXText * text = cursor().innerText(); + BOOST_ASSERT(text); + return text; } -void BufferView::selectLastWord() +LyXText const * BufferView::getLyXText() const { - if (!available()) - return; - - LyXCursor cur = text->selection.cursor; - beforeChange(text); - text->selection.cursor = cur; - text->selectSelectedWord(); - toggleSelection(false); - update(text, BufferView::SELECT); + LyXText const * text = cursor().innerText(); + BOOST_ASSERT(text); + return text; } -void BufferView::endOfSpellCheck() +void BufferView::haveSelection(bool sel) { - if (!available()) return; - - beforeChange(text); - text->selectSelectedWord(); - text->clearSelection(); - update(text, BufferView::SELECT); + pimpl_->workarea().haveSelection(sel); } -void BufferView::replaceWord(string const & replacestring) +int BufferView::workHeight() const { - if (!available()) - return; - - LyXText * tt = getLyXText(); - update(tt, BufferView::SELECT); - - // clear the selection (if there is any) - toggleSelection(false); - update(tt, BufferView::SELECT); - - // clear the selection (if there is any) - toggleSelection(false); - tt->replaceSelectionWithString(replacestring); - - tt->setSelectionRange(replacestring.length()); - - // Go back so that replacement string is also spellchecked - for (string::size_type i = 0; i < replacestring.length() + 1; ++i) { - tt->cursorLeft(this); - } - update(tt, BufferView::SELECT); - - // FIXME: should be done through LFUN - buffer()->markDirty(); - fitCursor(); -} -// End of spellchecker stuff - - -bool BufferView::lockInset(UpdatableInset * inset) -{ - if (!inset) - return false; - // don't relock if we're already locked - if (theLockingInset() == inset) - return true; - if (!theLockingInset()) { - // first check if it's the inset under the cursor we want lock - // should be most of the time - if (text->cursor.pos() < text->cursor.par()->size() - && text->cursor.par()->getChar(text->cursor.pos()) == - Paragraph::META_INSET) { - InsetOld * in = text->cursor.par()->getInset(text->cursor.pos()); - if (inset == in) { - theLockingInset(inset); - return true; - } - } - // Then do a deep look of the inset and lock the right one - int const id = inset->id(); - ParagraphList::iterator pit = buffer()->paragraphs.begin(); - ParagraphList::iterator pend = buffer()->paragraphs.end(); - for (; pit != pend; ++pit) { - InsetList::iterator it = pit->insetlist.begin(); - InsetList::iterator end = pit->insetlist.end(); - for (; it != end; ++it) { - if (it->inset == inset) { - text->setCursorIntern(pit, it->pos); - theLockingInset(inset); - return true; - } - if (it->inset->getInsetFromID(id)) { - text->setCursorIntern(pit, it->pos); - FuncRequest cmd(this, LFUN_INSET_EDIT, "left"); - it->inset->localDispatch(cmd); - return theLockingInset()->lockInsetInInset(this, inset); - } - } - } - return false; - } - return theLockingInset()->lockInsetInInset(this, inset); + return pimpl_->workarea().workHeight(); } -bool BufferView::fitLockedInsetCursor(int x, int y, int asc, int desc) +LyXText * BufferView::text() const { - if (theLockingInset() && available()) { - y += text->cursor.iy() + theLockingInset()->insetInInsetY(); - if (screen().fitManualCursor(this, text, x, y, asc, desc)) { - updateScrollbar(); - return true; - } - } - return false; + return buffer() ? &buffer()->text() : 0; } -void BufferView::hideCursor() +void BufferView::setCursor(DocIterator const & dit) { - screen().hideCursor(); -} - + size_t const n = dit.depth(); + for (size_t i = 0; i < n; ++i) + dit[i].inset().edit(cursor(), true); -int BufferView::unlockInset(UpdatableInset * inset) -{ - if (!inset) - return 0; - if (inset && theLockingInset() == inset) { - inset->insetUnlock(this); - theLockingInset(0); - // make sure we update the combo ! - owner()->setLayout(getLyXText()->cursor.par()->layout()->name()); - // Tell the paragraph dialog that we changed paragraph - dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE)); - finishUndo(); - return 0; - } else if (inset && theLockingInset() && - theLockingInset()->unlockInsetInInset(this, inset)) { - // Tell the paragraph dialog that we changed paragraph - dispatch(FuncRequest(LFUN_PARAGRAPH_UPDATE)); - // owner inset has updated the layout combo - finishUndo(); - return 0; - } - return 1; + cursor().setCursor(dit); + cursor().selection() = false; } -void BufferView::updateInset(InsetOld * inset) +void BufferView::mouseSetCursor(LCursor & cur) { - pimpl_->updateInset(inset); -} + BOOST_ASSERT(&cur.bv() == this); + // Has the cursor just left the inset? + if (&cursor().inset() != &cur.inset()) + cursor().inset().notifyCursorLeaves(cursor()); -bool BufferView::ChangeInsets(InsetOld::Code code, - string const & from, string const & to) -{ - bool need_update = false; - LyXCursor cursor = text->cursor; - LyXCursor tmpcursor = cursor; - cursor.par(tmpcursor.par()); - cursor.pos(tmpcursor.pos()); - - ParIterator end = buffer()->par_iterator_end(); - for (ParIterator it = 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; - - // FIXME - - // The test it.size()==1 was needed to prevent crashes. - // How to set the cursor corretly when it.size()>1 ?? - if (it.size() == 1) { - text->setCursorIntern(it.pit(), 0); - text->redoParagraphs(text->cursor, - boost::next(text->cursor.par())); - text->partialRebreak(); - } - } - } - text->setCursorIntern(cursor.par(), cursor.pos()); - return need_update; -} + // do the dEPM magic if needed + if (cursor().inTexted()) + cursor().text()->deleteEmptyParagraphMechanism(cur, cursor()); + cursor() = cur; + cursor().clearSelection(); + cursor().setTargetX(); + finishUndo(); -bool BufferView::ChangeRefsIfUnique(string const & from, string const & to) -{ - // Check if the label 'from' appears more than once - vector labels; - buffer()->getLabelList(labels); - - if (lyx::count(labels.begin(), labels.end(), from) > 1) - return false; - - return ChangeInsets(InsetOld::REF_CODE, from, to); } -UpdatableInset * BufferView::theLockingInset() const +void BufferView::putSelectionAt(DocIterator const & cur, + int length, bool backwards) { - // If NULL is not allowed we should put an Assert here. (Lgb) - if (text) - return text->the_locking_inset; - return 0; -} + cursor().clearSelection(); + setCursor(cur); -void BufferView::theLockingInset(UpdatableInset * inset) -{ - text->the_locking_inset = inset; + if (length) { + if (backwards) { + cursor().pos() += length; + cursor().setSelection(cursor(), -length); + } else + cursor().setSelection(cursor(), length); + } } -LyXText * BufferView::getLyXText() const +bool const BufferView::repaintAll() const { - if (theLockingInset()) { - LyXText * txt = theLockingInset()->getLyXText(this, true); - if (txt) - return txt; - } - return text; + return pimpl_->repaintAll(); } -LyXText * BufferView::getParentText(InsetOld * inset) const +void const BufferView::repaintAll(bool r) const { - if (inset->owner()) { - LyXText * txt = inset->getLyXText(this); - inset = inset->owner(); - while (inset && inset->getLyXText(this) == txt) - inset = inset->owner(); - if (inset) - return inset->getLyXText(this); - } - return text; + pimpl_->repaintAll(r); } -Language const * BufferView::getParentLanguage(InsetOld * inset) const +LCursor & BufferView::cursor() { - LyXText * text = getParentText(inset); - return text->cursor.par()->getFontSettings(buffer()->params, - text->cursor.pos()).language(); + return pimpl_->cursor_; } -Encoding const * BufferView::getEncoding() const +LCursor const & BufferView::cursor() const { - LyXText * t = getLyXText(); - if (!t) - return 0; - - LyXCursor const & c = t->cursor; - LyXFont const font = c.par()->getFont(buffer()->params, c.pos(), - outerFont(c.par(), t->ownerParagraphs())); - return font.language()->encoding(); + return pimpl_->cursor_; } -void BufferView::haveSelection(bool sel) +lyx::pit_type BufferView::anchor_ref() const { - pimpl_->workarea().haveSelection(sel); + return pimpl_->anchor_ref_; } -int BufferView::workHeight() const +int BufferView::offset_ref() const { - return pimpl_->workarea().workHeight(); + return pimpl_->offset_ref_; }