X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FText3.cpp;h=af69c654e79311a7cce1254a5862a778ac506cb5;hb=2098f1d8c20d51e63e670bcdc9da8996068975bf;hp=a6c597e3e245957af6d2906dc36483460609e617;hpb=091e3908b075398dd55e0502f6dac414e4342ef3;p=lyx.git diff --git a/src/Text3.cpp b/src/Text3.cpp index a6c597e3e2..af69c654e7 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@ -41,7 +41,6 @@ #include "Lexer.h" #include "LyXRC.h" #include "Paragraph.h" -#include "paragraph_funcs.h" #include "ParagraphParameters.h" #include "TextClass.h" #include "TextMetrics.h" @@ -49,13 +48,12 @@ #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 +61,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 +141,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 +165,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 +184,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) @@ -203,13 +202,14 @@ void regexpDispatch(Cursor & cur, FuncRequest const & cmd) 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,10 +229,13 @@ 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->setButtonLabel(); + cur.recordUndo(); if (cmd.action == LFUN_INDEX_INSERT) { docstring ds = subst(text->getStringToIndex(cur), '\n', ' '); @@ -240,7 +243,7 @@ static bool doInsertInset(Cursor & cur, Text * text, if (edit) inset->edit(cur, true); // Now put this into inset - cur.text()->insertStringAsLines(cur, ds); + cur.text()->insertStringAsLines(cur, ds, cur.current_font); cur.leaveInset(*inset); return true; } @@ -264,16 +267,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 @@ -283,7 +289,6 @@ static bool doInsertInset(Cursor & cur, Text * text, : dc.defaultLayoutName(); text->setLayout(cur, layoutname); } - return true; } @@ -384,10 +389,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()) @@ -411,10 +412,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: { @@ -432,12 +431,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: { @@ -457,7 +454,6 @@ static void outline(OutlineOp mode, Cursor & cur) } } } - set_buffers = false; break; } case OutlineOut: { @@ -477,20 +473,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); } @@ -502,8 +487,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()); } @@ -549,7 +535,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) pit_type const pit = cur.pit(); recUndo(cur, pit, pit + 1); cur.finishUndo(); - swap(pars_[pit], pars_[pit + 1]); + pars_.swap(pit, pit + 1); cur.buffer()->updateLabels(); needsUpdate = true; ++cur.pit(); @@ -560,7 +546,7 @@ 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]); + pars_.swap(pit, pit - 1); cur.buffer()->updateLabels(); --cur.pit(); needsUpdate = true; @@ -638,7 +624,7 @@ 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) + if (cur.depth() == 1 || !cur.top().at_begin()) needsUpdate |= cursorTop(cur); else cur.undispatched(); @@ -648,13 +634,25 @@ 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()) + 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); @@ -1055,13 +1053,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. @@ -1098,26 +1096,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; } @@ -1282,7 +1262,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()) { @@ -1390,7 +1370,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(); } @@ -1425,14 +1405,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: @@ -1445,7 +1428,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() @@ -1462,7 +1444,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) { @@ -1617,9 +1599,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; @@ -1679,7 +1661,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; @@ -1688,7 +1670,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); } @@ -1775,7 +1757,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); @@ -1803,7 +1786,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) 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); @@ -2000,7 +1983,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); @@ -2029,7 +2012,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(); @@ -2141,10 +2124,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 @@ -2283,9 +2262,36 @@ 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; @@ -2503,21 +2509,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(); - 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 @@ -2525,10 +2516,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; @@ -2540,7 +2530,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, 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; @@ -2578,9 +2568,11 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_LANGUAGE: enable = !cur.inset().getLayout().isPassThru(); + break; case LFUN_BREAK_PARAGRAPH: enable = cur.inset().getLayout().isMultiPar(); + break; case LFUN_WORD_DELETE_FORWARD: case LFUN_WORD_DELETE_BACKWARD: @@ -2665,6 +2657,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_INSET_END: case LFUN_INSET_BEGIN_SELECT: case LFUN_INSET_END_SELECT: + case LFUN_INSET_SELECT_ALL: case LFUN_UNICODE_INSERT: // these are handled in our dispatch() enable = true; @@ -2697,10 +2690,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_ACCENT_UMLAUT: case LFUN_ACCENT_UNDERBAR: case LFUN_ACCENT_UNDERDOT: - case LFUN_APPENDIX: - case LFUN_DEPTH_DECREMENT: - case LFUN_DEPTH_INCREMENT: - case LFUN_FILE_INSERT: case LFUN_FONT_BOLD: case LFUN_FONT_BOLDSYMBOL: case LFUN_FONT_TYPEWRITER: @@ -2717,15 +2706,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_FONT_STRIKEOUT: case LFUN_FONT_UULINE: case LFUN_FONT_UWAVE: - case LFUN_LABEL_GOTO: - case LFUN_LAYOUT_TABULAR: - case LFUN_MENU_OPEN: - case LFUN_NOACTION: - case LFUN_NOTE_NEXT: - case LFUN_REFERENCE_NEXT: - case LFUN_SERVER_GOTO_FILE_ROW: - case LFUN_SERVER_NOTIFY: - case LFUN_SERVER_SET_XY: case LFUN_TEXTSTYLE_APPLY: case LFUN_TEXTSTYLE_UPDATE: if (cur.inset().getLayout().isPassThru()) @@ -2747,9 +2727,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); } }