]> git.lyx.org Git - lyx.git/blobdiff - src/Text3.cpp
fix "make check" with gcc 4.3
[lyx.git] / src / Text3.cpp
index 42ea91a2b002fe05fd522561d1034a1b16e2d2d5..0a84a70f536849ec644a9f3faed55ab0a53c9d2e 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * \file text3.cpp
+ * \file Text3.cpp
  * This file is part of LyX, the document processor.
  * Licence details can be found in the file COPYING.
  *
 #include "TextMetrics.h"
 #include "VSpace.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/InsetFloatList.h"
+#include "insets/InsetGraphics.h"
+#include "insets/InsetGraphicsParams.h"
 #include "insets/InsetNewline.h"
 #include "insets/InsetQuotes.h"
 #include "insets/InsetSpecialChar.h"
 #include "insets/InsetText.h"
-#include "insets/InsetGraphics.h"
-#include "insets/InsetGraphicsParams.h"
 
 #include "support/convert.h"
 #include "support/debug.h"
@@ -84,6 +88,8 @@ using cap::pasteFromStack;
 using cap::pasteClipboardText;
 using cap::pasteClipboardGraphics;
 using cap::replaceSelection;
+using cap::grabAndEraseSelection;
+using cap::selClearOrDel;
 
 // globals...
 static Font freefont(ignore_font, ignore_language);
@@ -187,6 +193,26 @@ static void mathDispatch(Cursor & cur, FuncRequest const & cmd, bool display)
 }
 
 
+void regexpDispatch(Cursor & cur, FuncRequest const & cmd)
+{
+       BOOST_ASSERT(cmd.action == LFUN_REGEXP_MODE);
+       if (cur.inRegexped()) {
+               cur.message(_("Already in regexp mode"));
+               return;
+       }
+       cur.recordUndo();
+       docstring const save_selection = grabAndEraseSelection(cur);
+       selClearOrDel(cur);
+       // replaceSelection(cur);
+
+       cur.insert(new InsetMathHull(hullRegexp));
+       cur.nextInset()->edit(cur, true);
+       cur.niceInsert(save_selection);
+
+       cur.message(_("Regexp editor mode"));
+}
+
+
 static void specialChar(Cursor & cur, InsetSpecialChar::Kind kind)
 {
        cur.recordUndo();
@@ -234,8 +260,8 @@ static bool doInsertInset(Cursor & cur, Text * text,
        if (!gotsel || !pastesel)
                return true;
 
-       pasteFromStack(cur, cur.buffer().errorList("Paste"), 0);
-       cur.buffer().errors("Paste");
+       pasteFromStack(cur, cur.buffer()->errorList("Paste"), 0);
+       cur.buffer()->errors("Paste");
        cur.clearSelection(); // bug 393
        cur.finishUndo();
        InsetText * insetText = dynamic_cast<InsetText *>(inset);
@@ -280,7 +306,7 @@ enum OutlineOp {
 
 static void outline(OutlineOp mode, Cursor & cur)
 {
-       Buffer & buf = cur.buffer();
+       Buffer & buf = *cur.buffer();
        pit_type & pit = cur.pit();
        ParagraphList & pars = buf.text().paragraphs();
        ParagraphList::iterator bgn = pars.begin();
@@ -421,8 +447,10 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        BufferView * bv = &cur.bv();
        TextMetrics & tm = bv->textMetrics(this);
-       if (!tm.contains(cur.pit()))
+       if (!tm.contains(cur.pit())) {
                lyx::dispatch(FuncRequest(LFUN_SCREEN_RECENTER));
+               tm = bv->textMetrics(this);
+       }
 
        // FIXME: We use the update flag to indicates wether a singlePar or a
        // full screen update is needed. We reset it here but shall we restore it
@@ -448,7 +476,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                recUndo(cur, pit, pit + 1);
                cur.finishUndo();
                swap(pars_[pit], pars_[pit + 1]);
-               updateLabels(cur.buffer());
+               cur.buffer()->updateLabels();
                needsUpdate = true;
                ++cur.pit();
                break;
@@ -459,7 +487,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                recUndo(cur, pit - 1, pit);
                cur.finishUndo();
                swap(pars_[pit], pars_[pit - 1]);
-               updateLabels(cur.buffer());
+               cur.buffer()->updateLabels();
                --cur.pit();
                needsUpdate = true;
                break;
@@ -485,30 +513,30 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                par.params().startOfAppendix(start);
 
                // we can set the refreshing parameters now
-               updateLabels(cur.buffer());
+               cur.buffer()->updateLabels();
                break;
        }
 
        case LFUN_WORD_DELETE_FORWARD:
-               if (cur.selection()) {
+               if (cur.selection())
                        cutSelection(cur, true, false);
-               else
+               else
                        deleteWordForward(cur);
                finishChange(cur, false);
                break;
 
        case LFUN_WORD_DELETE_BACKWARD:
-               if (cur.selection()) {
+               if (cur.selection())
                        cutSelection(cur, true, false);
-               else
+               else
                        deleteWordBackward(cur);
                finishChange(cur, false);
                break;
 
        case LFUN_LINE_DELETE:
-               if (cur.selection()) {
+               if (cur.selection())
                        cutSelection(cur, true, false);
-               else
+               else
                        tm.deleteLineForward(cur);
                finishChange(cur, false);
                break;
@@ -516,22 +544,40 @@ 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);
-               if (cur.depth() == 1) {
+               if (cur.depth() == 1)
                        needsUpdate |= cursorTop(cur);
-               } else {
+               else
                        cur.undispatched();
-               }
                cur.updateFlags(Update::FitCursor);
                break;
 
        case LFUN_BUFFER_END:
        case LFUN_BUFFER_END_SELECT:
                needsUpdate |= cur.selHandle(cmd.action == LFUN_BUFFER_END_SELECT);
-               if (cur.depth() == 1) {
+               if (cur.depth() == 1)
                        needsUpdate |= cursorBottom(cur);
-               } else {
+               else
+                       cur.undispatched();
+               cur.updateFlags(Update::FitCursor);
+               break;
+
+       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 |= cursorTop(cur);
+               else
+                       cur.undispatched();
+               cur.updateFlags(Update::FitCursor);
+               break;
+
+       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 |= cursorBottom(cur);
+               else
                        cur.undispatched();
-               }
                cur.updateFlags(Update::FitCursor);
                break;
 
@@ -615,16 +661,24 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                // stop/start the selection
                bool select = cmd.action == LFUN_DOWN_SELECT ||
                        cmd.action == LFUN_UP_SELECT;
-               cur.selHandle(select);
 
                // move cursor up/down
                bool up = cmd.action == LFUN_UP_SELECT || cmd.action == LFUN_UP;
-               bool const successful = cur.upDownInText(up, needsUpdate);
-               if (successful) {
-                       // redraw if you leave mathed (for the decorations)
+               bool const atFirstOrLastRow = cur.atFirstOrLastRow(up);
+
+               if (!atFirstOrLastRow) {
+                       needsUpdate |= cur.selHandle(select);   
+                       cur.selHandle(select);
+                       cur.upDownInText(up, needsUpdate);
                        needsUpdate |= cur.beforeDispatchCursor().inMathed();
-               } else
+               } else {
+                       // if the cursor cannot be moved up or down do not remove
+                       // the selection right now, but wait for the next dispatch.
+                       if (select)
+                               needsUpdate |= cur.selHandle(select);   
+                       cur.upDownInText(up, needsUpdate);
                        cur.undispatched();
+               }
 
                break;
        }
@@ -819,7 +873,14 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_INSET_INSERT: {
                cur.recordUndo();
+
+               // We have to avoid triggering InstantPreview loading
+               // before inserting into the document. See bug #5626.
+               bool loaded = bv->buffer().isFullyLoaded();
+               bv->buffer().setFullyLoaded(false);
                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:
@@ -847,13 +908,41 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                cutSelection(cur, true, false);
                        cur.insert(inset);
                        cur.posForward();
+
+                       // trigger InstantPreview now
+                       if (inset->lyxCode() == EXTERNAL_CODE) {
+                               InsetExternal & ins =
+                                       static_cast<InsetExternal &>(*inset);
+                               ins.updatePreview();
+                       }
                }
+
                break;
        }
 
-       case LFUN_INSET_DISSOLVE:
-               needsUpdate |= dissolveInset(cur);
+       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)) {
+                       needsUpdate = true;
+                       break;
+               }
+               // if it did not work, do nothing.
                break;
+       }
 
        case LFUN_INSET_SETTINGS: {
                Inset & inset = cur.inset();
@@ -954,7 +1043,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                if (arg.empty()) {
                        if (theClipboard().isInternal())
                                pasteFromStack(cur, bv->buffer().errorList("Paste"), 0);
-                       else if (theClipboard().hasGraphicsContents())
+                       else if (theClipboard().hasGraphicsContents() 
+                                    && !theClipboard().hasTextContents())
                                pasteClipboardGraphics(cur, bv->buffer().errorList("Paste"));
                        else
                                pasteClipboardText(cur, bv->buffer().errorList("Paste"));
@@ -1090,6 +1180,15 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                            cmd.argument() == "paragraph");
                break;
 
+       case LFUN_SELECTION_PASTE:
+               // Copy the selection buffer to the clipboard stack,
+               // because we want it to appear in the "Edit->Paste
+               // recent" menu.
+               cap::copySelectionToStack();
+               cap::pasteSelection(bv->cursor(), bv->buffer().errorList("Paste"));
+               bv->buffer().errors("Paste");
+               break;
+
        case LFUN_UNICODE_INSERT: {
                if (cmd.argument().empty())
                        break;
@@ -1110,7 +1209,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                pos_type pos = cur.pos();
                BufferParams const & bufparams = bv->buffer().params();
                Layout const & style = par.layout();
-               if (!style.pass_thru
+               InsetLayout const & ilayout = cur.inset().getLayout(bufparams);
+               if (!style.pass_thru && !ilayout.isPassThru()
                    && par.getFontSettings(bufparams, pos).language()->lang() != "hebrew") {
                        // this avoids a double undo
                        // FIXME: should not be needed, ideally
@@ -1174,23 +1274,10 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                case mouse_button::button2:
                        // Middle mouse pasting.
                        bv->mouseSetCursor(cur);
-                       if (!cap::selection()) {
-                               // There is no local selection in the current buffer, so try to
-                               // paste primary selection instead.
-                               lyx::dispatch(FuncRequest(LFUN_PRIMARY_SELECTION_PASTE,
-                                       "paragraph"));
-                               // Nothing else to do.
-                               cur.noUpdate();
-                               return;
-                       }
-                       // Copy the selection buffer to the clipboard stack, because we want it
-                       // to appear in the "Edit->Paste recent" menu.
-                       cap::copySelectionToStack();
-                       cap::pasteSelection(bv->cursor(), bv->buffer().errorList("Paste"));
-                       cur.updateFlags(Update::Force | Update::FitCursor);
-                       bv->buffer().errors("Paste");
-                       bv->buffer().markDirty();
-                       bv->cursor().finishUndo();
+                       lyx::dispatch(
+                               FuncRequest(LFUN_COMMAND_ALTERNATIVES,
+                                           "selection-paste ; primary-selection-paste paragraph"));
+                       cur.noUpdate();
                        break;
 
                case mouse_button::button3: {
@@ -1319,6 +1406,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
                cur.resetAnchor();
                moveCursor(cur, false);
+               bv->bookmarkEditPosition();
                break;
        }
 
@@ -1381,6 +1469,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_FLEX_INSERT:
        case LFUN_BOX_INSERT:
        case LFUN_BRANCH_INSERT:
+       case LFUN_PHANTOM_INSERT:
        case LFUN_ERT_INSERT:
        case LFUN_LISTING_INSERT:
        case LFUN_MARGINALNOTE_INSERT:
@@ -1392,7 +1481,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                cur.posForward();
                // Some insets are numbered, others are shown in the outline pane so
                // let's update the labels and the toc backend.
-               updateLabels(bv->buffer());
+               bv->buffer().updateLabels();
                break;
 
        case LFUN_TABULAR_INSERT:
@@ -1446,7 +1535,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                // date metrics.
                FuncRequest cmd_caption(LFUN_CAPTION_INSERT);
                doInsertInset(cur, cur.text(), cmd_caption, true, false);
-               updateLabels(bv->buffer());
+               bv->buffer().updateLabels();
                cur.updateFlags(Update::Force);
                // FIXME: When leaving the Float (or Wrap) inset we should
                // delete any empty paragraph left above or below the
@@ -1487,6 +1576,10 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                mathDispatch(cur, cmd, true);
                break;
 
+       case LFUN_REGEXP_MODE:
+               regexpDispatch(cur, cmd);
+               break;
+
        case LFUN_MATH_MODE:
                if (cmd.argument() == "on")
                        // don't pass "on" as argument
@@ -1547,6 +1640,13 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                break;
        }
 
+       case LFUN_FONT_ITAL: {
+               Font font(ignore_font, ignore_language);
+               font.fontInfo().setShape(ITALIC_SHAPE);
+               toggleAndShow(cur, this, font);
+               break;
+       }
+
        case LFUN_FONT_BOLD:
        case LFUN_FONT_BOLDSYMBOL: {
                Font font(ignore_font, ignore_language);
@@ -1761,6 +1861,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                // Get word or selection
                                selectWordWhenUnderCursor(cur, WHOLE_WORD);
                                arg = cur.selectionAsString(false);
+                               arg += " lang=" + from_ascii(cur.getFont().language()->lang());
                        }
                }
                bv->showDialog("thesaurus", to_utf8(arg));
@@ -1803,26 +1904,26 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_OUTLINE_UP:
                outline(OutlineUp, cur);
                setCursor(cur, cur.pit(), 0);
-               updateLabels(cur.buffer());
+               cur.buffer()->updateLabels();
                needsUpdate = true;
                break;
 
        case LFUN_OUTLINE_DOWN:
                outline(OutlineDown, cur);
                setCursor(cur, cur.pit(), 0);
-               updateLabels(cur.buffer());
+               cur.buffer()->updateLabels();
                needsUpdate = true;
                break;
 
        case LFUN_OUTLINE_IN:
                outline(OutlineIn, cur);
-               updateLabels(cur.buffer());
+               cur.buffer()->updateLabels();
                needsUpdate = true;
                break;
 
        case LFUN_OUTLINE_OUT:
                outline(OutlineOut, cur);
-               updateLabels(cur.buffer());
+               cur.buffer()->updateLabels();
                needsUpdate = true;
                break;
 
@@ -1928,6 +2029,8 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                        code = LABEL_CODE;
                else if (cmd.argument() == "note")
                        code = NOTE_CODE;
+               else if (cmd.argument() == "phantom")
+                       code = PHANTOM_CODE;
                else if (cmd.argument() == "ref")
                        code = REF_CODE;
                else if (cmd.argument() == "space")
@@ -1990,7 +2093,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                code = FLEX_CODE;
                string s = cmd.getArg(0);
                InsetLayout il =
-                       cur.buffer().params().documentClass().insetLayout(from_utf8(s));
+                       cur.buffer()->params().documentClass().insetLayout(from_utf8(s));
                if (il.lyxtype() != InsetLayout::CHARSTYLE &&
                    il.lyxtype() != InsetLayout::CUSTOM &&
                    il.lyxtype() != InsetLayout::ELEMENT &&
@@ -2003,9 +2106,12 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                break;
        case LFUN_BRANCH_INSERT:
                code = BRANCH_CODE;
-               if (cur.buffer().masterBuffer()->params().branchlist().empty())
+               if (cur.buffer()->masterBuffer()->params().branchlist().empty())
                        enable = false;
                break;
+       case LFUN_PHANTOM_INSERT:
+               code = PHANTOM_CODE;
+               break;
        case LFUN_LABEL_INSERT:
                code = LABEL_CODE;
                break;
@@ -2068,6 +2174,10 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                flag.setOnOff(fontinfo.emph() == FONT_ON);
                break;
 
+       case LFUN_FONT_ITAL:
+               flag.setOnOff(fontinfo.shape() == ITALIC_SHAPE);
+               break;
+
        case LFUN_FONT_NOUN:
                flag.setOnOff(fontinfo.noun() == FONT_ON);
                break;
@@ -2134,6 +2244,10 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                enable = cur.selection() || !theSelection().empty();
                break;
 
+       case LFUN_SELECTION_PASTE:
+               enable = cap::selection();
+               break;
+
        case LFUN_PARAGRAPH_MOVE_UP:
                enable = cur.pit() > 0 && !cur.selection();
                break;
@@ -2144,14 +2258,16 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
 
        case LFUN_INSET_DISSOLVE:
                if (!cmd.argument().empty()) {
-                       InsetLayout const & il = cur.inset().getLayout(cur.buffer().params());
+                       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;
+                       enable = ((!isMainText(cur.bv().buffer())
+                                     && cur.inset().nargs() == 1)
+                                 || (cur.nextInset()
+                                     && cur.nextInset()->nargs() == 1));
                }
                break;
 
@@ -2194,6 +2310,14 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                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_WORD_DELETE_FORWARD:
        case LFUN_WORD_DELETE_BACKWARD:
        case LFUN_LINE_DELETE:
@@ -2245,10 +2369,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_MATH_DISPLAY:
        case LFUN_MATH_MODE:
        case LFUN_MATH_MACRO:
-       case LFUN_MATH_MATRIX:
-       case LFUN_MATH_DELIM:
-       case LFUN_MATH_BIGDELIM:
-       case LFUN_MATH_INSERT:
        case LFUN_MATH_SUBSCRIPT:
        case LFUN_MATH_SUPERSCRIPT:
        case LFUN_FONT_DEFAULT:
@@ -2279,10 +2399,14 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_PARAGRAPH_PARAMS_APPLY:
        case LFUN_PARAGRAPH_PARAMS:
        case LFUN_ESCAPE:
-       case LFUN_BUFFER_END:
        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;