X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FText3.cpp;h=0dd3b6492c96ee94fb1906e658d4fa0ae9533c95;hb=5b75a45bc1c590cca5ac2a3e539a741a4aede26a;hp=29f1d2154f79d64cbd0e66cf156ddce4e29dce37;hpb=c4feab5f1357c6c078ff0c9df5c38dcdd134c03b;p=lyx.git diff --git a/src/Text3.cpp b/src/Text3.cpp index 29f1d2154f..0dd3b6492c 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@ -37,25 +37,25 @@ #include "Language.h" #include "Layout.h" #include "LyXAction.h" -#include "LyXFunc.h" +#include "LyX.h" #include "Lexer.h" #include "LyXRC.h" #include "Paragraph.h" -#include "paragraph_funcs.h" #include "ParagraphParameters.h" +#include "SpellChecker.h" #include "TextClass.h" #include "TextMetrics.h" #include "VSpace.h" +#include "WordLangTuple.h" #include "frontends/Application.h" #include "frontends/Clipboard.h" -#include "frontends/LyXView.h" #include "frontends/Selection.h" -#include "frontends/WorkArea.h" #include "insets/InsetCollapsable.h" #include "insets/InsetCommand.h" #include "insets/InsetExternal.h" +#include "insets/InsetFloat.h" #include "insets/InsetFloatList.h" #include "insets/InsetGraphics.h" #include "insets/InsetGraphicsParams.h" @@ -63,6 +63,7 @@ #include "insets/InsetQuotes.h" #include "insets/InsetSpecialChar.h" #include "insets/InsetText.h" +#include "insets/InsetWrap.h" #include "support/convert.h" #include "support/debug.h" @@ -142,7 +143,7 @@ static void mathDispatch(Cursor & cur, FuncRequest const & cmd, bool display) #ifdef ENABLE_ASSERTIONS const int old_pos = cur.pos(); #endif - cur.insert(new InsetMathHull(hullSimple)); + cur.insert(new InsetMathHull(cur.buffer(), hullSimple)); #ifdef ENABLE_ASSERTIONS LASSERT(old_pos == cur.pos(), /**/); #endif @@ -166,7 +167,7 @@ static void mathDispatch(Cursor & cur, FuncRequest const & cmd, bool display) && sel.find(from_ascii("\\newlyxcommand")) == string::npos && sel.find(from_ascii("\\def")) == string::npos) { - InsetMathHull * formula = new InsetMathHull; + InsetMathHull * formula = new InsetMathHull(cur.buffer()); string const selstr = to_utf8(sel); istringstream is(selstr); Lexer lex; @@ -185,7 +186,7 @@ static void mathDispatch(Cursor & cur, FuncRequest const & cmd, bool display) } else cur.insert(formula); } else { - cur.insert(new MathMacroTemplate(sel)); + cur.insert(new MathMacroTemplate(cur.buffer(), sel)); } } if (valid) @@ -197,19 +198,20 @@ static void mathDispatch(Cursor & cur, FuncRequest const & cmd, bool display) void regexpDispatch(Cursor & cur, FuncRequest const & cmd) { - BOOST_ASSERT(cmd.action == LFUN_REGEXP_MODE); + LASSERT(cmd.action() == LFUN_REGEXP_MODE, return); if (cur.inRegexped()) { - cur.message(_("Already in regexp mode")); + cur.message(_("Already in regular expression mode")); return; } cur.recordUndo(); - docstring const save_selection = grabAndEraseSelection(cur); - selClearOrDel(cur); - // replaceSelection(cur); + docstring sel = cur.selectionAsString(false); + + // It may happen that sel is empty but there is a selection + replaceSelection(cur); - cur.insert(new InsetMathHull(hullRegexp)); + cur.insert(new InsetMathHull(cur.buffer(), hullRegexp)); cur.nextInset()->edit(cur, true); - cur.niceInsert(save_selection); + cur.niceInsert(sel); cur.message(_("Regexp editor mode")); } @@ -229,22 +231,22 @@ static bool doInsertInset(Cursor & cur, Text * text, { Buffer & buffer = cur.bv().buffer(); BufferParams const & bparams = buffer.params(); - Inset * inset = createInset(buffer, cmd); + Inset * inset = createInset(&buffer, cmd); if (!inset) return false; if (InsetCollapsable * ci = inset->asInsetCollapsable()) - ci->setLayout(bparams); + ci->setButtonLabel(); cur.recordUndo(); - if (cmd.action == LFUN_INDEX_INSERT) { + if (cmd.action() == LFUN_INDEX_INSERT) { docstring ds = subst(text->getStringToIndex(cur), '\n', ' '); text->insertInset(cur, inset); if (edit) inset->edit(cur, true); // Now put this into inset - static_cast(inset)-> - text().insertStringAsParagraphs(cur, ds); + cur.text()->insertStringAsLines(cur, ds, cur.current_font); + cur.leaveInset(*inset); return true; } @@ -267,16 +269,19 @@ static bool doInsertInset(Cursor & cur, Text * text, cur.clearSelection(); // bug 393 cur.finishUndo(); InsetText * insetText = dynamic_cast(inset); - if (insetText && (!insetText->allowMultiPar() || cur.lastpit() == 0)) { - // reset first par to default - cur.text()->paragraphs().begin() - ->setPlainOrDefaultLayout(bparams.documentClass()); - cur.pos() = 0; - cur.pit() = 0; - // Merge multiple paragraphs -- hack - while (cur.lastpit() > 0) - mergeParagraph(bparams, cur.text()->paragraphs(), 0); - cur.leaveInset(*inset); + if (insetText) { + insetText->fixParagraphsFont(); + if (!insetText->allowMultiPar() || cur.lastpit() == 0) { + // reset first par to default + cur.text()->paragraphs().begin() + ->setPlainOrDefaultLayout(bparams.documentClass()); + cur.pos() = 0; + cur.pit() = 0; + // Merge multiple paragraphs -- hack + while (cur.lastpit() > 0) + mergeParagraph(bparams, cur.text()->paragraphs(), 0); + cur.leaveInset(*inset); + } } else { cur.leaveInset(*inset); // reset surrounding par to default @@ -286,7 +291,6 @@ static bool doInsertInset(Cursor & cur, Text * text, : dc.defaultLayoutName(); text->setLayout(cur, layoutname); } - return true; } @@ -297,59 +301,6 @@ string const freefont2string() } -static void dragMove(Cursor & cur, int moveid, int movetoid) -{ - // Create pointers to buffers - Buffer & buf_move = *cur.buffer(); - DocIterator dit_move = buf_move.getParFromID(moveid); - DocIterator dit_dest = buf_move.getParFromID(movetoid); - - pit_type & pit_move = dit_move.pit(); - pit_type & pit_dest = dit_dest.pit(); - ParagraphList & pars = dit_move.text()->paragraphs(); - - // Create references to the paragraphs to be moved - ParagraphList::iterator const bgn = pars.begin(); - ParagraphList::iterator dest_start = boost::next(bgn, pit_dest); - - // The first paragraph of the area to be copied: - ParagraphList::iterator start = boost::next(bgn, pit_move); - // The final paragraph of area to be copied: - ParagraphList::iterator finish = start; - ParagraphList::iterator const end = pars.end(); - - // Move out (down) from this section header - if (finish != end) - ++finish; - - // Seek the one (on same level) below - int const thistoclevel = start->layout().toclevel; - for (; finish != end; ++finish) { - int const toclevel = finish->layout().toclevel; - if (toclevel != Layout::NOT_IN_TOC - && toclevel <= thistoclevel) - break; - } - - if (start == pars.begin() || start == dest_start) - // Nothing to move - return; - - pars.insert(dest_start, start, finish); - pars.erase(start, finish); - - // FIXME: This only really needs doing for the newly - // introduced paragraphs. Something like: - // pit_type const numpars = distance(start, finish); - // start = boost::next(bgn, pit); - // finish = boost::next(start, numpars); - // for (; start != finish; ++start) - // start->setBuffer(buf); - // But while this seems to work, it is kind of fragile. - buf_move.inset().setBuffer(buf_move); -} - - /// the type of outline operation enum OutlineOp { OutlineUp, // Move this header with text down @@ -387,10 +338,6 @@ static void outline(OutlineOp mode, Cursor & cur) break; } - // Do we need to set insets' buffer_ members, because we copied - // some stuff? We'll assume we do and reset it otherwise. - bool set_buffers = true; - switch (mode) { case OutlineUp: { if (start == pars.begin()) @@ -414,10 +361,8 @@ static void outline(OutlineOp mode, Cursor & cur) pit_type const len = distance(start, finish); pit_type const deletepit = pit + len; buf.undo().recordUndo(cur, ATOMIC_UNDO, newpit, deletepit - 1); - pars.insert(dest, start, finish); - start = boost::next(pars.begin(), deletepit); - pit = newpit; - pars.erase(start, finish); + pars.splice(dest, start, finish); + cur.pit() = newpit; break; } case OutlineDown: { @@ -435,12 +380,10 @@ static void outline(OutlineOp mode, Cursor & cur) } // One such was found: pit_type newpit = distance(bgn, dest); - pit_type const len = distance(start, finish); buf.undo().recordUndo(cur, ATOMIC_UNDO, pit, newpit - 1); - pars.insert(dest, start, finish); - start = boost::next(bgn, pit); - pit = newpit - len; - pars.erase(start, finish); + pit_type const len = distance(start, finish); + pars.splice(dest, start, finish); + cur.pit() = newpit - len; break; } case OutlineIn: { @@ -460,7 +403,6 @@ static void outline(OutlineOp mode, Cursor & cur) } } } - set_buffers = false; break; } case OutlineOut: { @@ -480,20 +422,9 @@ static void outline(OutlineOp mode, Cursor & cur) } } } - set_buffers = false; break; } } - if (set_buffers) - // FIXME This only really needs doing for the newly introduced - // paragraphs. Something like: - // pit_type const numpars = distance(start, finish); - // start = boost::next(bgn, pit); - // finish = boost::next(start, numpars); - // for (; start != finish; ++start) - // start->setBuffer(buf); - // But while this seems to work, it is kind of fragile. - buf.inset().setBuffer(buf); } @@ -505,8 +436,9 @@ void Text::number(Cursor & cur) } -bool Text::isRTL(Buffer const & buffer, Paragraph const & par) const +bool Text::isRTL(Paragraph const & par) const { + Buffer const & buffer = owner_->buffer(); return par.isRTL(buffer.params()); } @@ -515,6 +447,13 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) { LYXERR(Debug::ACTION, "Text::dispatch: cmd: " << cmd); + // Dispatch if the cursor is inside the text. It is not the + // case for context menus (bug 5797). + if (cur.text() != this) { + cur.undispatched(); + return; + } + BufferView * bv = &cur.bv(); TextMetrics * tm = &bv->textMetrics(this); if (!tm->contains(cur.pit())) { @@ -533,20 +472,21 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) bool sel = cur.selection(); // Signals that, even if needsUpdate == false, an update of the // cursor paragraph is required - bool singleParUpdate = lyxaction.funcHasFlag(cmd.action, + bool singleParUpdate = lyxaction.funcHasFlag(cmd.action(), LyXAction::SingleParUpdate); // Signals that a full-screen update is required - bool needsUpdate = !(lyxaction.funcHasFlag(cmd.action, + bool needsUpdate = !(lyxaction.funcHasFlag(cmd.action(), LyXAction::NoUpdate) || singleParUpdate); - switch (cmd.action) { + FuncCode const act = cmd.action(); + switch (act) { case LFUN_PARAGRAPH_MOVE_DOWN: { pit_type const pit = cur.pit(); recUndo(cur, pit, pit + 1); cur.finishUndo(); - swap(pars_[pit], pars_[pit + 1]); - cur.buffer()->updateLabels(); + pars_.swap(pit, pit + 1); + cur.buffer()->updateBuffer(); needsUpdate = true; ++cur.pit(); break; @@ -556,8 +496,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) pit_type const pit = cur.pit(); recUndo(cur, pit - 1, pit); cur.finishUndo(); - swap(pars_[pit], pars_[pit - 1]); - cur.buffer()->updateLabels(); + pars_.swap(pit, pit - 1); + cur.buffer()->updateBuffer(); --cur.pit(); needsUpdate = true; break; @@ -583,7 +523,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) par.params().startOfAppendix(start); // we can set the refreshing parameters now - cur.buffer()->updateLabels(); + cur.buffer()->updateBuffer(); break; } @@ -613,7 +553,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_BUFFER_BEGIN: case LFUN_BUFFER_BEGIN_SELECT: - needsUpdate |= cur.selHandle(cmd.action == LFUN_BUFFER_BEGIN_SELECT); + needsUpdate |= cur.selHandle(act == LFUN_BUFFER_BEGIN_SELECT); if (cur.depth() == 1) needsUpdate |= cursorTop(cur); else @@ -623,7 +563,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_BUFFER_END: case LFUN_BUFFER_END_SELECT: - needsUpdate |= cur.selHandle(cmd.action == LFUN_BUFFER_END_SELECT); + needsUpdate |= cur.selHandle(act == LFUN_BUFFER_END_SELECT); if (cur.depth() == 1) needsUpdate |= cursorBottom(cur); else @@ -633,8 +573,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_INSET_BEGIN: case LFUN_INSET_BEGIN_SELECT: - needsUpdate |= cur.selHandle(cmd.action == LFUN_INSET_BEGIN_SELECT); - if (cur.depth() == 1 || cur.pos() > 0) + needsUpdate |= cur.selHandle(act == LFUN_INSET_BEGIN_SELECT); + if (cur.depth() == 1 || !cur.top().at_begin()) needsUpdate |= cursorTop(cur); else cur.undispatched(); @@ -643,18 +583,30 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_INSET_END: case LFUN_INSET_END_SELECT: - needsUpdate |= cur.selHandle(cmd.action == LFUN_INSET_END_SELECT); - if (cur.depth() == 1 || cur.pos() < cur.lastpos()) + needsUpdate |= cur.selHandle(act == LFUN_INSET_END_SELECT); + if (cur.depth() == 1 || !cur.top().at_end()) needsUpdate |= cursorBottom(cur); else cur.undispatched(); cur.updateFlags(Update::FitCursor); break; + case LFUN_INSET_SELECT_ALL: + if (cur.depth() == 1 || !cur.selection() || !cur.selBegin().at_begin() + || !cur.selEnd().at_end()) { + needsUpdate |= cur.selHandle(false); + needsUpdate |= cursorTop(cur); + needsUpdate |= cur.selHandle(true); + needsUpdate |= cursorBottom(cur); + } else + cur.undispatched(); + cur.updateFlags(Update::FitCursor); + break; + case LFUN_CHAR_FORWARD: case LFUN_CHAR_FORWARD_SELECT: //LYXERR0(" LFUN_CHAR_FORWARD[SEL]:\n" << cur); - needsUpdate |= cur.selHandle(cmd.action == LFUN_CHAR_FORWARD_SELECT); + needsUpdate |= cur.selHandle(act == LFUN_CHAR_FORWARD_SELECT); needsUpdate |= cursorForward(cur); if (!needsUpdate && oldTopSlice == cur.top() @@ -680,7 +632,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_CHAR_BACKWARD: case LFUN_CHAR_BACKWARD_SELECT: //lyxerr << "handle LFUN_CHAR_BACKWARD[_SELECT]:\n" << cur << endl; - needsUpdate |= cur.selHandle(cmd.action == LFUN_CHAR_BACKWARD_SELECT); + needsUpdate |= cur.selHandle(act == LFUN_CHAR_BACKWARD_SELECT); needsUpdate |= cursorBackward(cur); if (!needsUpdate && oldTopSlice == cur.top() @@ -706,7 +658,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_CHAR_LEFT: case LFUN_CHAR_LEFT_SELECT: if (lyxrc.visual_cursor) { - needsUpdate |= cur.selHandle(cmd.action == LFUN_CHAR_LEFT_SELECT); + needsUpdate |= cur.selHandle(act == LFUN_CHAR_LEFT_SELECT); needsUpdate |= cursorVisLeft(cur); if (!needsUpdate && oldTopSlice == cur.top() && cur.boundary() == oldBoundary) { @@ -715,11 +667,11 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) } } else { if (reverseDirectionNeeded(cur)) { - cmd.action = cmd.action == LFUN_CHAR_LEFT_SELECT ? - LFUN_CHAR_FORWARD_SELECT : LFUN_CHAR_FORWARD; + cmd.setAction(cmd.action() == LFUN_CHAR_LEFT_SELECT ? + LFUN_CHAR_FORWARD_SELECT : LFUN_CHAR_FORWARD); } else { - cmd.action = cmd.action == LFUN_CHAR_LEFT_SELECT ? - LFUN_CHAR_BACKWARD_SELECT : LFUN_CHAR_BACKWARD; + cmd.setAction(cmd.action() == LFUN_CHAR_LEFT_SELECT ? + LFUN_CHAR_BACKWARD_SELECT : LFUN_CHAR_BACKWARD); } dispatch(cur, cmd); return; @@ -729,7 +681,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_CHAR_RIGHT: case LFUN_CHAR_RIGHT_SELECT: if (lyxrc.visual_cursor) { - needsUpdate |= cur.selHandle(cmd.action == LFUN_CHAR_RIGHT_SELECT); + needsUpdate |= cur.selHandle(cmd.action() == LFUN_CHAR_RIGHT_SELECT); needsUpdate |= cursorVisRight(cur); if (!needsUpdate && oldTopSlice == cur.top() && cur.boundary() == oldBoundary) { @@ -738,11 +690,11 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) } } else { if (reverseDirectionNeeded(cur)) { - cmd.action = cmd.action == LFUN_CHAR_RIGHT_SELECT ? - LFUN_CHAR_BACKWARD_SELECT : LFUN_CHAR_BACKWARD; + cmd.setAction(cmd.action() == LFUN_CHAR_RIGHT_SELECT ? + LFUN_CHAR_BACKWARD_SELECT : LFUN_CHAR_BACKWARD); } else { - cmd.action = cmd.action == LFUN_CHAR_RIGHT_SELECT ? - LFUN_CHAR_FORWARD_SELECT : LFUN_CHAR_FORWARD; + cmd.setAction(cmd.action() == LFUN_CHAR_RIGHT_SELECT ? + LFUN_CHAR_FORWARD_SELECT : LFUN_CHAR_FORWARD); } dispatch(cur, cmd); return; @@ -755,11 +707,11 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_UP: case LFUN_DOWN: { // stop/start the selection - bool select = cmd.action == LFUN_DOWN_SELECT || - cmd.action == LFUN_UP_SELECT; + bool select = cmd.action() == LFUN_DOWN_SELECT || + cmd.action() == LFUN_UP_SELECT; // move cursor up/down - bool up = cmd.action == LFUN_UP_SELECT || cmd.action == LFUN_UP; + bool up = cmd.action() == LFUN_UP_SELECT || cmd.action() == LFUN_UP; bool const atFirstOrLastRow = cur.atFirstOrLastRow(up); if (!atFirstOrLastRow) { @@ -781,25 +733,25 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_PARAGRAPH_UP: case LFUN_PARAGRAPH_UP_SELECT: - needsUpdate |= cur.selHandle(cmd.action == LFUN_PARAGRAPH_UP_SELECT); + needsUpdate |= cur.selHandle(cmd.action() == LFUN_PARAGRAPH_UP_SELECT); needsUpdate |= cursorUpParagraph(cur); break; case LFUN_PARAGRAPH_DOWN: case LFUN_PARAGRAPH_DOWN_SELECT: - needsUpdate |= cur.selHandle(cmd.action == LFUN_PARAGRAPH_DOWN_SELECT); + needsUpdate |= cur.selHandle(cmd.action() == LFUN_PARAGRAPH_DOWN_SELECT); needsUpdate |= cursorDownParagraph(cur); break; case LFUN_LINE_BEGIN: case LFUN_LINE_BEGIN_SELECT: - needsUpdate |= cur.selHandle(cmd.action == LFUN_LINE_BEGIN_SELECT); + needsUpdate |= cur.selHandle(cmd.action() == LFUN_LINE_BEGIN_SELECT); needsUpdate |= tm->cursorHome(cur); break; case LFUN_LINE_END: case LFUN_LINE_END_SELECT: - needsUpdate |= cur.selHandle(cmd.action == LFUN_LINE_END_SELECT); + needsUpdate |= cur.selHandle(cmd.action() == LFUN_LINE_END_SELECT); needsUpdate |= tm->cursorEnd(cur); break; @@ -841,7 +793,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_WORD_RIGHT: case LFUN_WORD_RIGHT_SELECT: if (lyxrc.visual_cursor) { - needsUpdate |= cur.selHandle(cmd.action == LFUN_WORD_RIGHT_SELECT); + needsUpdate |= cur.selHandle(cmd.action() == LFUN_WORD_RIGHT_SELECT); needsUpdate |= cursorVisRightOneWord(cur); if (!needsUpdate && oldTopSlice == cur.top() && cur.boundary() == oldBoundary) { @@ -850,11 +802,11 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) } } else { if (reverseDirectionNeeded(cur)) { - cmd.action = cmd.action == LFUN_WORD_RIGHT_SELECT ? - LFUN_WORD_BACKWARD_SELECT : LFUN_WORD_BACKWARD; + cmd.setAction(cmd.action() == LFUN_WORD_RIGHT_SELECT ? + LFUN_WORD_BACKWARD_SELECT : LFUN_WORD_BACKWARD); } else { - cmd.action = cmd.action == LFUN_WORD_RIGHT_SELECT ? - LFUN_WORD_FORWARD_SELECT : LFUN_WORD_FORWARD; + cmd.setAction(cmd.action() == LFUN_WORD_RIGHT_SELECT ? + LFUN_WORD_FORWARD_SELECT : LFUN_WORD_FORWARD); } dispatch(cur, cmd); return; @@ -863,14 +815,14 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_WORD_FORWARD: case LFUN_WORD_FORWARD_SELECT: - needsUpdate |= cur.selHandle(cmd.action == LFUN_WORD_FORWARD_SELECT); + needsUpdate |= cur.selHandle(cmd.action() == LFUN_WORD_FORWARD_SELECT); needsUpdate |= cursorForwardOneWord(cur); break; case LFUN_WORD_LEFT: case LFUN_WORD_LEFT_SELECT: if (lyxrc.visual_cursor) { - needsUpdate |= cur.selHandle(cmd.action == LFUN_WORD_LEFT_SELECT); + needsUpdate |= cur.selHandle(cmd.action() == LFUN_WORD_LEFT_SELECT); needsUpdate |= cursorVisLeftOneWord(cur); if (!needsUpdate && oldTopSlice == cur.top() && cur.boundary() == oldBoundary) { @@ -879,11 +831,11 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) } } else { if (reverseDirectionNeeded(cur)) { - cmd.action = cmd.action == LFUN_WORD_LEFT_SELECT ? - LFUN_WORD_FORWARD_SELECT : LFUN_WORD_FORWARD; + cmd.setAction(cmd.action() == LFUN_WORD_LEFT_SELECT ? + LFUN_WORD_FORWARD_SELECT : LFUN_WORD_FORWARD); } else { - cmd.action = cmd.action == LFUN_WORD_LEFT_SELECT ? - LFUN_WORD_BACKWARD_SELECT : LFUN_WORD_BACKWARD; + cmd.setAction(cmd.action() == LFUN_WORD_LEFT_SELECT ? + LFUN_WORD_BACKWARD_SELECT : LFUN_WORD_BACKWARD); } dispatch(cur, cmd); return; @@ -892,7 +844,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_WORD_BACKWARD: case LFUN_WORD_BACKWARD_SELECT: - needsUpdate |= cur.selHandle(cmd.action == LFUN_WORD_BACKWARD_SELECT); + needsUpdate |= cur.selHandle(cmd.action() == LFUN_WORD_BACKWARD_SELECT); needsUpdate |= cursorBackwardOneWord(cur); break; @@ -920,6 +872,91 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) break; } + case LFUN_TAB_INSERT: { + bool const multi_par_selection = cur.selection() && + cur.selBegin().pit() != cur.selEnd().pit(); + if (multi_par_selection) { + // If there is a multi-paragraph selection, a tab is inserted + // at the beginning of each paragraph. + cur.recordUndoSelection(); + pit_type const pit_end = cur.selEnd().pit(); + for (pit_type pit = cur.selBegin().pit(); pit <= pit_end; pit++) { + pars_[pit].insertChar(0, '\t', + bv->buffer().params().trackChanges); + // Update the selection pos to make sure the selection does not + // change as the inserted tab will increase the logical pos. + if (cur.realAnchor().pit() == pit) + cur.realAnchor().forwardPos(); + if (cur.pit() == pit) + cur.forwardPos(); + } + cur.finishUndo(); + } else { + // Maybe we shouldn't allow tabs within a line, because they + // are not (yet) aligned as one might do expect. + FuncRequest cmd(LFUN_SELF_INSERT, from_ascii("\t")); + dispatch(cur, cmd); + } + break; + } + + case LFUN_TAB_DELETE: { + bool const tc = bv->buffer().params().trackChanges; + if (cur.selection()) { + // If there is a selection, a tab (if present) is removed from + // the beginning of each paragraph. + cur.recordUndoSelection(); + pit_type const pit_end = cur.selEnd().pit(); + for (pit_type pit = cur.selBegin().pit(); pit <= pit_end; pit++) { + Paragraph & par = paragraphs()[pit]; + if (par.getChar(0) == '\t') { + if (cur.pit() == pit) + cur.posBackward(); + if (cur.realAnchor().pit() == pit && cur.realAnchor().pos() > 0 ) + cur.realAnchor().backwardPos(); + + par.eraseChar(0, tc); + } else + // If no tab was present, try to remove up to four spaces. + for (int n_spaces = 0; + par.getChar(0) == ' ' && n_spaces < 4; ++n_spaces) { + if (cur.pit() == pit) + cur.posBackward(); + if (cur.realAnchor().pit() == pit && cur.realAnchor().pos() > 0 ) + cur.realAnchor().backwardPos(); + + par.eraseChar(0, tc); + } + } + cur.finishUndo(); + } else { + // If there is no selection, try to remove a tab or some spaces + // before the position of the cursor. + Paragraph & par = paragraphs()[cur.pit()]; + pos_type const pos = cur.pos(); + + if (pos == 0) + break; + + char_type const c = par.getChar(pos - 1); + cur.recordUndo(); + if (c == '\t') { + cur.posBackward(); + par.eraseChar(cur.pos(), tc); + } else + for (int n_spaces = 0; + cur.pos() > 0 + && par.getChar(cur.pos() - 1) == ' ' + && n_spaces < 4; + ++n_spaces) { + cur.posBackward(); + par.eraseChar(cur.pos(), tc); + } + cur.finishUndo(); + } + break; + } + case LFUN_CHAR_DELETE_FORWARD: if (!cur.selection()) { if (cur.pos() == cur.paragraph().size()) @@ -959,49 +996,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) cur.resetAnchor(); break; - // TODO - // With the creation of LFUN_PARAGRAPH_PARAMS, this is now redundant, - // as its duties can be performed there. Should it be removed?? - // FIXME For now, it can just dispatch LFUN_PARAGRAPH_PARAMS... - case LFUN_PARAGRAPH_SPACING: { - Paragraph & par = cur.paragraph(); - Spacing::Space cur_spacing = par.params().spacing().getSpace(); - string cur_value = "1.0"; - if (cur_spacing == Spacing::Other) - cur_value = par.params().spacing().getValueAsString(); - - istringstream is(to_utf8(cmd.argument())); - string tmp; - is >> tmp; - Spacing::Space new_spacing = cur_spacing; - string new_value = cur_value; - if (tmp.empty()) { - lyxerr << "Missing argument to `paragraph-spacing'" - << endl; - } else if (tmp == "single") { - new_spacing = Spacing::Single; - } else if (tmp == "onehalf") { - new_spacing = Spacing::Onehalf; - } else if (tmp == "double") { - new_spacing = Spacing::Double; - } else if (tmp == "other") { - new_spacing = Spacing::Other; - string tmpval = "0.0"; - is >> tmpval; - lyxerr << "new_value = " << tmpval << endl; - if (tmpval != "0.0") - new_value = tmpval; - } else if (tmp == "default") { - new_spacing = Spacing::Default; - } else { - lyxerr << to_utf8(_("Unknown spacing argument: ")) - << to_utf8(cmd.argument()) << endl; - } - if (cur_spacing != new_spacing || cur_value != new_value) - par.params().spacing(Spacing(new_spacing, new_value)); - break; - } - case LFUN_INSET_INSERT: { cur.recordUndo(); @@ -1009,13 +1003,13 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) // before inserting into the document. See bug #5626. bool loaded = bv->buffer().isFullyLoaded(); bv->buffer().setFullyLoaded(false); - Inset * inset = createInset(bv->buffer(), cmd); + Inset * inset = createInset(&bv->buffer(), cmd); bv->buffer().setFullyLoaded(loaded); if (inset) { // FIXME (Abdel 01/02/2006): // What follows would be a partial fix for bug 2154: - // http://bugzilla.lyx.org/show_bug.cgi?id=2154 + // http://www.lyx.org/trac/ticket/2154 // This automatically put the label inset _after_ a // numbered section. It should be possible to extend the mechanism // to any kind of LateX environement. @@ -1052,26 +1046,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) } case LFUN_INSET_DISSOLVE: { - // first, try if there's an inset at cursor - // FIXME: this first part should be moved to - // a LFUN_NEXT_INSET_DISSOLVE, or be called via - // some generic "next-inset inset-dissolve" - Inset * inset = cur.nextInset(); - if (inset && inset->isActive()) { - Cursor tmpcur = cur; - tmpcur.pushBackward(*inset); - inset->dispatch(tmpcur, cmd); - if (tmpcur.result().dispatched()) { - cur.dispatched(); - break; - } - } - // if it did not work, try the underlying inset - if (dissolveInset(cur)) { + if (dissolveInset(cur)) needsUpdate = true; - break; - } - // if it did not work, do nothing. break; } @@ -1236,7 +1212,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) if (layout.empty()) layout = tclass.defaultLayoutName(); - if (para.forcePlainLayout()) + if (owner_->forcePlainLayout()) // in this case only the empty layout is allowed layout = tclass.plainLayoutName(); else if (para.usePlainLayout()) { @@ -1327,7 +1303,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) pos_type pos = cur.pos(); BufferParams const & bufparams = bv->buffer().params(); Layout const & style = par.layout(); - InsetLayout const & ilayout = cur.inset().getLayout(bufparams); + InsetLayout const & ilayout = cur.inset().getLayout(); if (!style.pass_thru && !ilayout.isPassThru() && par.getFontSettings(bufparams, pos).language()->lang() != "hebrew") { // this avoids a double undo @@ -1344,7 +1320,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) else c = par.getChar(pos - 1); string arg = to_utf8(cmd.argument()); - cur.insert(new InsetQuotes(bv->buffer(), c, (arg == "single") + cur.insert(new InsetQuotes(cur.buffer(), c, (arg == "single") ? InsetQuotes::SingleQuotes : InsetQuotes::DoubleQuotes)); cur.posForward(); } @@ -1379,14 +1355,17 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) break; // Single-click on work area - case LFUN_MOUSE_PRESS: + case LFUN_MOUSE_PRESS: { // We are not marking a selection with the keyboard in any case. - cur.bv().cursor().setMark(false); + Cursor & bvcur = cur.bv().cursor(); + bvcur.setMark(false); switch (cmd.button()) { case mouse_button::button1: // Set the cursor if (!bv->mouseSetCursor(cur, cmd.argument() == "region-select")) cur.updateFlags(Update::SinglePar | Update::FitCursor); + if (bvcur.wordSelection()) + selectWord(bvcur, WHOLE_WORD); break; case mouse_button::button2: @@ -1399,7 +1378,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) break; case mouse_button::button3: { - Cursor const & bvcur = cur.bv().cursor(); // Don't do anything if we right-click a // selection, a context menu will popup. if (bvcur.selection() && cur >= bvcur.selectionBegin() @@ -1416,7 +1394,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) break; } // switch (cmd.button()) break; - + } case LFUN_MOUSE_MOTION: { // Mouse motion with right or middle mouse do nothing for now. if (cmd.button() != mouse_button::button1) { @@ -1425,26 +1403,26 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) } // ignore motions deeper nested than the real anchor Cursor & bvcur = cur.bv().cursor(); - if (!bvcur.anchor_.hasPart(cur)) { + if (!bvcur.realAnchor().hasPart(cur)) { cur.undispatched(); break; } CursorSlice old = bvcur.top(); int const wh = bv->workHeight(); - int const y = max(0, min(wh - 1, cmd.y)); + int const y = max(0, min(wh - 1, cmd.y())); - tm->setCursorFromCoordinates(cur, cmd.x, y); - cur.setTargetX(cmd.x); - if (cmd.y >= wh) + tm->setCursorFromCoordinates(cur, cmd.x(), y); + cur.setTargetX(cmd.x()); + if (cmd.y() >= wh) lyx::dispatch(FuncRequest(LFUN_DOWN_SELECT)); - else if (cmd.y < 0) + else if (cmd.y() < 0) lyx::dispatch(FuncRequest(LFUN_UP_SELECT)); // This is to allow jumping over large insets if (cur.top() == old) { - if (cmd.y >= wh) + if (cmd.y() >= wh) lyx::dispatch(FuncRequest(LFUN_DOWN_SELECT)); - else if (cmd.y < 0) + else if (cmd.y() < 0) lyx::dispatch(FuncRequest(LFUN_UP_SELECT)); } // We continue with our existing selection or start a new one, so don't @@ -1571,9 +1549,9 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) docstring ds = cur.selectionAsString(false); cutSelection(cur, true, false); FuncRequest cmd0(cmd, ds); - inset = createInset(cur.bv().buffer(), cmd0); + inset = createInset(cur.buffer(), cmd0); } else { - inset = createInset(cur.bv().buffer(), cmd); + inset = createInset(cur.buffer(), cmd); } if (!inset) break; @@ -1594,13 +1572,14 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_MARGINALNOTE_INSERT: case LFUN_OPTIONAL_INSERT: case LFUN_INDEX_INSERT: + case LFUN_PREVIEW_INSERT: // Open the inset, and move the current selection // inside it. doInsertInset(cur, this, cmd, true, true); cur.posForward(); // Some insets are numbered, others are shown in the outline pane so // let's update the labels and the toc backend. - bv->buffer().updateLabels(); + bv->buffer().updateBuffer(); break; case LFUN_TABULAR_INSERT: @@ -1633,7 +1612,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) // add a separate paragraph for the caption inset pars.push_back(Paragraph()); - pars.back().setInsetOwner(&pars[0].inInset()); + pars.back().setInsetOwner(&cur.text()->inset()); pars.back().setPlainOrDefaultLayout(tclass); int cap_pit = pars.size() - 1; @@ -1642,7 +1621,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) // the graphics (or table). if (!content) { pars.push_back(Paragraph()); - pars.back().setInsetOwner(&pars[0].inInset()); + pars.back().setInsetOwner(&cur.text()->inset()); pars.back().setPlainOrDefaultLayout(tclass); } @@ -1654,7 +1633,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) // date metrics. FuncRequest cmd_caption(LFUN_CAPTION_INSERT); doInsertInset(cur, cur.text(), cmd_caption, true, false); - bv->buffer().updateLabels(); + bv->buffer().updateBuffer(); cur.updateFlags(Update::Force); // FIXME: When leaving the Float (or Wrap) inset we should // delete any empty paragraph left above or below the @@ -1729,7 +1708,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) MacroType type = MacroTypeNewcommand; if (s2 == "def") type = MacroTypeDef; - MathMacroTemplate * inset = new MathMacroTemplate(from_utf8(token(s, ' ', 0)), nargs, false, type); + MathMacroTemplate * inset = new MathMacroTemplate(cur.buffer(), + from_utf8(token(s, ' ', 0)), nargs, false, type); inset->setBuffer(bv->buffer()); insertInset(cur, inset); @@ -1751,12 +1731,13 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) break; case LFUN_MATH_INSERT: + case LFUN_MATH_AMS_MATRIX: case LFUN_MATH_MATRIX: case LFUN_MATH_DELIM: case LFUN_MATH_BIGDELIM: { cur.recordUndo(); cap::replaceSelection(cur); - cur.insert(new InsetMathHull(hullSimple)); + cur.insert(new InsetMathHull(cur.buffer(), hullSimple)); checkAndActivateInset(cur, true); LASSERT(cur.inMathed(), /**/); cur.dispatch(cmd); @@ -1953,7 +1934,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_ACCENT_HUNGARIAN_UMLAUT: case LFUN_ACCENT_CIRCLE: case LFUN_ACCENT_OGONEK: - theLyXFunc().handleKeyFunc(cmd.action); + theApp()->handleKeyFunc(cmd.action()); if (!cmd.argument().empty()) // FIXME: Are all these characters encoded in one byte in utf8? bv->translateAndInsert(cmd.argument()[0], this, cur); @@ -1982,7 +1963,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) setParagraphs(cur, p); // FIXME This should be simplified when InsetFloatList takes a // Buffer in its constructor. - InsetFloatList * ifl = new InsetFloatList(to_utf8(cmd.argument())); + InsetFloatList * ifl = new InsetFloatList(cur.buffer(), to_utf8(cmd.argument())); ifl->setBuffer(bv->buffer()); insertInset(cur, ifl); cur.posForward(); @@ -2019,6 +2000,44 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) break; } + case LFUN_SPELLING_ADD: { + docstring word = from_utf8(cmd.getArg(0)); + Language * lang; + if (word.empty()) { + word = cur.selectionAsString(false); + // FIXME + if (word.size() > 100 || word.empty()) { + // Get word or selection + selectWordWhenUnderCursor(cur, WHOLE_WORD); + word = cur.selectionAsString(false); + } + lang = const_cast(cur.getFont().language()); + } else + lang = const_cast(languages.getLanguage(cmd.getArg(1))); + WordLangTuple wl(word, lang); + theSpellChecker()->insert(wl); + break; + } + + case LFUN_SPELLING_IGNORE: { + docstring word = from_utf8(cmd.getArg(0)); + Language * lang; + if (word.empty()) { + word = cur.selectionAsString(false); + // FIXME + if (word.size() > 100 || word.empty()) { + // Get word or selection + selectWordWhenUnderCursor(cur, WHOLE_WORD); + word = cur.selectionAsString(false); + } + lang = const_cast(cur.getFont().language()); + } else + lang = const_cast(languages.getLanguage(cmd.getArg(1))); + WordLangTuple wl(word, lang); + theSpellChecker()->accept(wl); + break; + } + case LFUN_PARAGRAPH_PARAMS_APPLY: { // Given data, an encoding of the ParagraphParameters // generated in the Paragraph dialog, this function sets @@ -2055,38 +2074,28 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_OUTLINE_UP: outline(OutlineUp, cur); setCursor(cur, cur.pit(), 0); - cur.buffer()->updateLabels(); + cur.buffer()->updateBuffer(); needsUpdate = true; break; case LFUN_OUTLINE_DOWN: outline(OutlineDown, cur); setCursor(cur, cur.pit(), 0); - cur.buffer()->updateLabels(); + cur.buffer()->updateBuffer(); needsUpdate = true; break; case LFUN_OUTLINE_IN: outline(OutlineIn, cur); - cur.buffer()->updateLabels(); + cur.buffer()->updateBuffer(); needsUpdate = true; break; case LFUN_OUTLINE_OUT: outline(OutlineOut, cur); - cur.buffer()->updateLabels(); - needsUpdate = true; - break; - - case LFUN_OUTLINE_DRAGMOVE: { - int const move_id = convert(cmd.getArg(0)); - int const move_to_id = convert(cmd.getArg(1)); - dragMove(cur, move_id, move_to_id); - setCursor(cur, cur.pit(), 0); - cur.buffer()->updateLabels(); + cur.buffer()->updateBuffer(); needsUpdate = true; break; - } default: LYXERR(Debug::ACTION, "Command " << cmd << " not DISPATCHED by Text"); @@ -2094,10 +2103,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) break; } - if (lyxrc.spellcheck_continuously && cur.inTexted()) - // Take this opportunity to spellcheck current word. - cur.paragraph().isMisspelled(cur.pos()); - needsUpdate |= (cur.pos() != cur.lastpos()) && cur.selection(); // FIXME: The cursor flag is reset two lines below @@ -2123,7 +2128,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) if (!needsUpdate && &oldTopSlice.inset() == &cur.inset() && oldTopSlice.idx() == cur.idx() - && !sel // sel is a backup of cur.selection() at the biginning of the function. + && !sel // sel is a backup of cur.selection() at the beginning of the function. && !cur.selection()) // FIXME: it would be better if we could just do this // @@ -2149,7 +2154,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, bool enable = true; InsetCode code = NO_CODE; - switch (cmd.action) { + switch (cmd.action()) { case LFUN_DEPTH_DECREMENT: enable = changeDepthAllowed(cur, DEC_DEPTH); @@ -2236,20 +2241,60 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, break; case LFUN_FLOAT_INSERT: case LFUN_FLOAT_WIDE_INSERT: + // FIXME: If there is a selection, we should check whether there + // are floats in the selection, but this has performance issues, see + // LFUN_CHANGE_ACCEPT/REJECT. code = FLOAT_CODE; - // not allowed in description items - enable = !inDescriptionItem(cur); + if (inDescriptionItem(cur)) + // not allowed in description items + enable = false; + else { + InsetCode const inset_code = cur.inset().lyxCode(); + + // algorithm floats cannot be put in another float + if (to_utf8(cmd.argument()) == "algorithm") { + enable = inset_code != WRAP_CODE && inset_code != FLOAT_CODE; + break; + } + + // for figures and tables: only allow in another + // float or wrap if it is of the same type and + // not a subfloat already + if(cur.inset().lyxCode() == code) { + InsetFloat const & ins = + static_cast(cur.inset()); + enable = ins.params().type == to_utf8(cmd.argument()) + && !ins.params().subfloat; + } else if(cur.inset().lyxCode() == WRAP_CODE) { + InsetWrap const & ins = + static_cast(cur.inset()); + enable = ins.params().type == to_utf8(cmd.argument()); + } + } break; case LFUN_WRAP_INSERT: code = WRAP_CODE; // not allowed in description items enable = !inDescriptionItem(cur); break; - case LFUN_FLOAT_LIST_INSERT: + case LFUN_FLOAT_LIST_INSERT: { code = FLOAT_LIST_CODE; // not allowed in description items enable = !inDescriptionItem(cur); + if (enable) { + FloatList const & floats = cur.buffer()->params().documentClass().floats(); + FloatList::const_iterator cit = floats[to_ascii(cmd.argument())]; + // make sure we know about such floats + if (cit == floats.end() || + // and that we know how to generate a list of them + (!cit->second.needsFloatPkg() && cit->second.listCommand().empty())) { + flag.setUnknown(true); + // probably not necessary, but... + enable = false; + } + } break; + } case LFUN_CAPTION_INSERT: code = CAPTION_CODE; // not allowed in description items @@ -2290,6 +2335,9 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_LABEL_INSERT: code = LABEL_CODE; break; + case LFUN_LINE_INSERT: + code = LINE_CODE; + break; case LFUN_INFO_INSERT: code = INFO_CODE; break; @@ -2342,6 +2390,27 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, if (cur.inTexted()) code = SPACE_CODE; break; + case LFUN_PREVIEW_INSERT: + code = PREVIEW_CODE; + break; + + case LFUN_MATH_INSERT: + case LFUN_MATH_AMS_MATRIX: + case LFUN_MATH_MATRIX: + case LFUN_MATH_DELIM: + case LFUN_MATH_BIGDELIM: + case LFUN_MATH_DISPLAY: + case LFUN_MATH_MODE: + case LFUN_MATH_MACRO: + case LFUN_MATH_SUBSCRIPT: + case LFUN_MATH_SUPERSCRIPT: + code = MATH_HULL_CODE; + break; + + case LFUN_REGEXP_MODE: + code = MATH_HULL_CODE; + enable = cur.buffer()->isInternal() && !cur.inRegexped(); + break; case LFUN_INSET_MODIFY: // We need to disable this, because we may get called for a @@ -2353,31 +2422,38 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_FONT_EMPH: flag.setOnOff(fontinfo.emph() == FONT_ON); + enable = !cur.inset().getLayout().isPassThru(); break; case LFUN_FONT_ITAL: flag.setOnOff(fontinfo.shape() == ITALIC_SHAPE); + enable = !cur.inset().getLayout().isPassThru(); break; case LFUN_FONT_NOUN: flag.setOnOff(fontinfo.noun() == FONT_ON); + enable = !cur.inset().getLayout().isPassThru(); break; case LFUN_FONT_BOLD: case LFUN_FONT_BOLDSYMBOL: flag.setOnOff(fontinfo.series() == BOLD_SERIES); + enable = !cur.inset().getLayout().isPassThru(); break; case LFUN_FONT_SANS: flag.setOnOff(fontinfo.family() == SANS_FAMILY); + enable = !cur.inset().getLayout().isPassThru(); break; case LFUN_FONT_ROMAN: flag.setOnOff(fontinfo.family() == ROMAN_FAMILY); + enable = !cur.inset().getLayout().isPassThru(); break; case LFUN_FONT_TYPEWRITER: flag.setOnOff(fontinfo.family() == TYPEWRITER_FAMILY); + enable = !cur.inset().getLayout().isPassThru(); break; case LFUN_CUT: @@ -2440,21 +2516,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, enable = cur.pit() < cur.lastpit() && !cur.selection(); break; - case LFUN_INSET_DISSOLVE: - if (!cmd.argument().empty()) { - InsetLayout const & il = cur.inset().getLayout(cur.buffer()->params()); - InsetLayout::InsetLyXType const type = - translateLyXType(to_utf8(cmd.argument())); - enable = cur.inset().lyxCode() == FLEX_CODE - && il.lyxtype() == type; - } else { - enable = ((!isMainText(cur.bv().buffer()) - && cur.inset().nargs() == 1) - || (cur.nextInset() - && cur.nextInset()->nargs() == 1)); - } - break; - case LFUN_CHANGE_ACCEPT: case LFUN_CHANGE_REJECT: // In principle, these LFUNs should only be enabled if there @@ -2462,10 +2523,9 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, // However, without proper optimizations, this will inevitably // result in unacceptable performance - just imagine a user who // wants to select the complete content of a long document. - if (!cur.selection()) { - Change const & change = cur.paragraph().lookupChange(cur.pos()); - enable = change.changed(); - } else + if (!cur.selection()) + enable = cur.paragraph().isChanged(cur.pos()); + else // TODO: context-sensitive enabling of LFUN_CHANGE_ACCEPT/REJECT // for selections. enable = true; @@ -2475,9 +2535,8 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_OUTLINE_DOWN: case LFUN_OUTLINE_IN: case LFUN_OUTLINE_OUT: - case LFUN_OUTLINE_DRAGMOVE: // FIXME: LyX is not ready for outlining within inset. - enable = isMainText(cur.bv().buffer()) + enable = isMainText() && cur.paragraph().layout().toclevel != Layout::NOT_IN_TOC; break; @@ -2486,6 +2545,11 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, enable = (cur.pos() > cur.paragraph().beginOfBody()); break; + case LFUN_TAB_INSERT: + case LFUN_TAB_DELETE: + enable = cur.inset().getLayout().isPassThru(); + break; + case LFUN_SET_GRAPHICS_GROUP: { InsetGraphics * ins = graphics::getCurrentGraphicsInset(cur); if (!ins) @@ -2497,17 +2561,10 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_NEWPAGE_INSERT: // not allowed in description items + code = NEWPAGE_CODE; enable = !inDescriptionItem(cur); break; - case LFUN_MATH_INSERT: - case LFUN_MATH_MATRIX: - case LFUN_MATH_DELIM: - case LFUN_MATH_BIGDELIM: - // not allowed in ERT, for example. - enable = cur.inset().insetAllowed(MATH_CODE); - break; - case LFUN_DATE_INSERT: { string const format = cmd.argument().empty() ? lyxrc.date_insert_format : to_utf8(cmd.argument()); @@ -2515,6 +2572,61 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, break; } + case LFUN_LANGUAGE: + enable = !cur.inset().getLayout().isPassThru(); + flag.setOnOff(to_utf8(cmd.argument()) == cur.real_current_font.language()->lang()); + break; + + case LFUN_BREAK_PARAGRAPH: + enable = cur.inset().getLayout().isMultiPar(); + break; + + case LFUN_SPELLING_ADD: + case LFUN_SPELLING_IGNORE: + enable = theSpellChecker(); + break; + + case LFUN_LAYOUT: + enable = !cur.inset().forcePlainLayout(); + break; + + case LFUN_LAYOUT_PARAGRAPH: + case LFUN_PARAGRAPH_PARAMS: + case LFUN_PARAGRAPH_PARAMS_APPLY: + case LFUN_PARAGRAPH_UPDATE: + enable = cur.inset().allowParagraphCustomization(); + break; + + // FIXME: why are accent lfuns forbidden with pass_thru layouts? + case LFUN_ACCENT_ACUTE: + case LFUN_ACCENT_BREVE: + case LFUN_ACCENT_CARON: + case LFUN_ACCENT_CEDILLA: + case LFUN_ACCENT_CIRCLE: + case LFUN_ACCENT_CIRCUMFLEX: + case LFUN_ACCENT_DOT: + case LFUN_ACCENT_GRAVE: + case LFUN_ACCENT_HUNGARIAN_UMLAUT: + case LFUN_ACCENT_MACRON: + case LFUN_ACCENT_OGONEK: + case LFUN_ACCENT_TIE: + case LFUN_ACCENT_TILDE: + case LFUN_ACCENT_UMLAUT: + case LFUN_ACCENT_UNDERBAR: + case LFUN_ACCENT_UNDERDOT: + case LFUN_FONT_DEFAULT: + case LFUN_FONT_FRAK: + case LFUN_FONT_SIZE: + case LFUN_FONT_STATE: + case LFUN_FONT_UNDERLINE: + case LFUN_FONT_STRIKEOUT: + case LFUN_FONT_UULINE: + case LFUN_FONT_UWAVE: + case LFUN_TEXTSTYLE_APPLY: + case LFUN_TEXTSTYLE_UPDATE: + enable = !cur.inset().getLayout().isPassThru(); + break; + case LFUN_WORD_DELETE_FORWARD: case LFUN_WORD_DELETE_BACKWARD: case LFUN_LINE_DELETE: @@ -2544,14 +2656,21 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_WORD_LEFT_SELECT: case LFUN_WORD_SELECT: case LFUN_SECTION_SELECT: + case LFUN_BUFFER_BEGIN: + case LFUN_BUFFER_END: + case LFUN_BUFFER_BEGIN_SELECT: + case LFUN_BUFFER_END_SELECT: + case LFUN_INSET_BEGIN: + case LFUN_INSET_END: + case LFUN_INSET_BEGIN_SELECT: + case LFUN_INSET_END_SELECT: + case LFUN_INSET_SELECT_ALL: case LFUN_PARAGRAPH_UP: case LFUN_PARAGRAPH_DOWN: case LFUN_LINE_BEGIN: case LFUN_LINE_END: case LFUN_CHAR_DELETE_FORWARD: case LFUN_CHAR_DELETE_BACKWARD: - case LFUN_BREAK_PARAGRAPH: - case LFUN_PARAGRAPH_SPACING: case LFUN_INSET_INSERT: case LFUN_WORD_UPCASE: case LFUN_WORD_LOWCASE: @@ -2560,54 +2679,10 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_SERVER_GET_XY: case LFUN_SERVER_SET_XY: case LFUN_SERVER_GET_LAYOUT: - case LFUN_LAYOUT: case LFUN_SELF_INSERT: - case LFUN_LINE_INSERT: - case LFUN_MATH_DISPLAY: - case LFUN_MATH_MODE: - case LFUN_MATH_MACRO: - case LFUN_MATH_SUBSCRIPT: - case LFUN_MATH_SUPERSCRIPT: - case LFUN_FONT_DEFAULT: - case LFUN_FONT_UNDERLINE: - case LFUN_FONT_STRIKEOUT: - case LFUN_FONT_UULINE: - case LFUN_FONT_UWAVE: - case LFUN_FONT_SIZE: - case LFUN_LANGUAGE: - case LFUN_TEXTSTYLE_APPLY: - case LFUN_TEXTSTYLE_UPDATE: - case LFUN_LAYOUT_PARAGRAPH: - case LFUN_PARAGRAPH_UPDATE: - case LFUN_ACCENT_UMLAUT: - case LFUN_ACCENT_CIRCUMFLEX: - case LFUN_ACCENT_GRAVE: - case LFUN_ACCENT_ACUTE: - case LFUN_ACCENT_TILDE: - case LFUN_ACCENT_CEDILLA: - case LFUN_ACCENT_MACRON: - case LFUN_ACCENT_DOT: - case LFUN_ACCENT_UNDERDOT: - case LFUN_ACCENT_UNDERBAR: - case LFUN_ACCENT_CARON: - case LFUN_ACCENT_BREVE: - case LFUN_ACCENT_TIE: - case LFUN_ACCENT_HUNGARIAN_UMLAUT: - case LFUN_ACCENT_CIRCLE: - case LFUN_ACCENT_OGONEK: + case LFUN_UNICODE_INSERT: case LFUN_THESAURUS_ENTRY: - case LFUN_PARAGRAPH_PARAMS_APPLY: - case LFUN_PARAGRAPH_PARAMS: case LFUN_ESCAPE: - case LFUN_BUFFER_BEGIN: - case LFUN_BUFFER_END: - case LFUN_BUFFER_BEGIN_SELECT: - case LFUN_BUFFER_END_SELECT: - case LFUN_INSET_BEGIN: - case LFUN_INSET_END: - case LFUN_INSET_BEGIN_SELECT: - case LFUN_INSET_END_SELECT: - case LFUN_UNICODE_INSERT: // these are handled in our dispatch() enable = true; break; @@ -2617,7 +2692,9 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, } if (code != NO_CODE - && (cur.empty() || !cur.inset().insetAllowed(code))) + && (cur.empty() + || !cur.inset().insetAllowed(code) + || cur.paragraph().layout().pass_thru)) enable = false; flag.setEnabled(enable); @@ -2632,9 +2709,9 @@ void Text::pasteString(Cursor & cur, docstring const & clip, if (!clip.empty()) { cur.recordUndo(); if (asParagraphs) - insertStringAsParagraphs(cur, clip); + insertStringAsParagraphs(cur, clip, cur.current_font); else - insertStringAsLines(cur, clip); + insertStringAsLines(cur, clip, cur.current_font); } }