]> git.lyx.org Git - lyx.git/blobdiff - src/Text3.cpp
* Call metrics of the parameters with the correct font in MathMacros, for example
[lyx.git] / src / Text3.cpp
index be8e80feb43e2d8c7c65945dad1c3d5861f20309..22408657cb4ddcb97a7d58c88f9ec1cbff53e8a9 100644 (file)
@@ -56,7 +56,6 @@
 #include "insets/InsetQuotes.h"
 #include "insets/InsetSpecialChar.h"
 #include "insets/InsetText.h"
-#include "insets/InsetInfo.h"
 #include "insets/InsetGraphics.h"
 #include "insets/InsetGraphicsParams.h"
 
@@ -68,6 +67,7 @@
 
 #include "mathed/InsetMathHull.h"
 #include "mathed/MathMacroTemplate.h"
+#include "mathed/MathParser.h"
 
 #include <boost/next_prior.hpp>
 
@@ -128,6 +128,9 @@ static void mathDispatch(Cursor & cur, FuncRequest const & cmd, bool display)
        // It may happen that sel is empty but there is a selection
        replaceSelection(cur);
 
+       // Is this a valid formula?
+       bool valid = true;
+
        if (sel.empty()) {
 #ifdef ENABLE_ASSERTIONS
                const int old_pos = cur.pos();
@@ -157,20 +160,35 @@ static void mathDispatch(Cursor & cur, FuncRequest const & cmd, bool display)
                                && sel.find(from_ascii("\\def")) == string::npos)
                {
                        InsetMathHull * formula = new InsetMathHull;
-                       istringstream is(to_utf8(sel));
+                       string const selstr = to_utf8(sel);
+                       istringstream is(selstr);
                        Lexer lex;
                        lex.setStream(is);
+                       mathed_parser_warn_contents(false);
                        formula->read(lex);
-                       if (formula->getType() == hullNone)
-                               // Don't create pseudo formulas if
-                               // delimiters are left out
-                               formula->mutate(hullSimple);
-                       cur.insert(formula);
+                       if (formula->getType() == hullNone) {
+                               // No valid formula, let's try with delims
+                               is.str("$" + selstr + "$");
+                               lex.setStream(is);
+                               formula->read(lex);
+                               if (formula->getType() == hullNone) {
+                                       // Still not valid, leave it as is
+                                       valid = false;
+                                       delete formula;
+                                       cur.insert(sel);
+                               } else
+                                       cur.insert(formula);
+                       } else
+                               cur.insert(formula);
+                       mathed_parser_warn_contents(true);
                } else {
                        cur.insert(new MathMacroTemplate(sel));
                }
        }
-       cur.message(from_utf8(N_("Math editor mode")));
+       if (valid)
+               cur.message(from_utf8(N_("Math editor mode")));
+       else
+               cur.message(from_utf8(N_("No valid math formula")));
 }
 
 
@@ -225,7 +243,7 @@ static bool doInsertInset(Cursor & cur, Text * text,
        cur.clearSelection(); // bug 393
        cur.finishUndo();
        InsetText * insetText = dynamic_cast<InsetText *>(inset);
-       if (insetText && !insetText->allowMultiPar() || cur.lastpit() == 0) {
+       if (insetText && (!insetText->allowMultiPar() || cur.lastpit() == 0)) {
                // reset first par to default
                cur.text()->paragraphs().begin()
                        ->setPlainOrDefaultLayout(bparams.documentClass());
@@ -238,9 +256,10 @@ static bool doInsertInset(Cursor & cur, Text * text,
        } else {
                cur.leaveInset(*inset);
                // reset surrounding par to default
-               docstring const layoutname = insetText->usePlainLayout()
-                       ? bparams.documentClass().plainLayoutName()
-                       : bparams.documentClass().defaultLayoutName();
+               DocumentClass const & dc = bparams.documentClass();
+               docstring const layoutname = inset->usePlainLayout()
+                       ? dc.plainLayoutName()
+                       : dc.defaultLayoutName();
                text->setLayout(cur, layoutname);
        }
 
@@ -558,10 +577,10 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        }
                } else {
                        if (reverseDirectionNeeded(cur)) {
-                               cmd.action = cmd.action == LFUN_CHAR_LEFT_SELECT ? 
+                               cmd.action = cmd.action == LFUN_CHAR_LEFT_SELECT ?
                                        LFUN_CHAR_FORWARD_SELECT : LFUN_CHAR_FORWARD;
                        } else {
-                               cmd.action = cmd.action == LFUN_CHAR_LEFT_SELECT ? 
+                               cmd.action = cmd.action == LFUN_CHAR_LEFT_SELECT ?
                                        LFUN_CHAR_BACKWARD_SELECT : LFUN_CHAR_BACKWARD;
                        }
                        dispatch(cur, cmd);
@@ -581,17 +600,17 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        }
                } else {
                        if (reverseDirectionNeeded(cur)) {
-                               cmd.action = cmd.action == LFUN_CHAR_RIGHT_SELECT ? 
+                               cmd.action = cmd.action == LFUN_CHAR_RIGHT_SELECT ?
                                        LFUN_CHAR_BACKWARD_SELECT : LFUN_CHAR_BACKWARD;
                        } else {
-                               cmd.action = cmd.action == LFUN_CHAR_RIGHT_SELECT ? 
+                               cmd.action = cmd.action == LFUN_CHAR_RIGHT_SELECT ?
                                        LFUN_CHAR_FORWARD_SELECT : LFUN_CHAR_FORWARD;
                        }
                        dispatch(cur, cmd);
                        return;
                }
                break;
-               
+
 
        case LFUN_UP_SELECT:
        case LFUN_DOWN_SELECT:
@@ -601,7 +620,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                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);
@@ -610,7 +629,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        needsUpdate |= cur.beforeDispatchCursor().inMathed();
                } else
                        cur.undispatched();
-               
+
                break;
        }
 
@@ -719,7 +738,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                moveCursor(cur, false);
                break;
        }
-       
+
        case LFUN_CHAR_DELETE_FORWARD:
                if (!cur.selection()) {
                        if (cur.pos() == cur.paragraph().size())
@@ -863,7 +882,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                if (!ins)
                        break;
 
-               cur.recordUndoFullDocument();
+               cur.recordUndo();
 
                string id = to_utf8(cmd.argument());
                string grp = graphics::getGroupParams(bv->buffer(), id);
@@ -931,6 +950,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_PASTE: {
                cur.message(_("Paste"));
+               LASSERT(cur.selBegin().idx() == cur.selEnd().idx(), /**/);
                cap::replaceSelection(cur);
 
                // without argument?
@@ -1012,14 +1032,14 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                if (layout.empty())
                        layout = tclass.defaultLayoutName();
 
-               if (para.forcePlainLayout()) 
+               if (para.forcePlainLayout())
                        // in this case only the empty layout is allowed
                        layout = tclass.plainLayoutName();
                else if (para.usePlainLayout()) {
-                       // in this case, default layout maps to empty layout 
+                       // in this case, default layout maps to empty layout
                        if (layout == tclass.defaultLayoutName())
                                layout = tclass.plainLayoutName();
-               } else { 
+               } else {
                        // otherwise, the empty layout maps to the default
                        if (layout == tclass.plainLayoutName())
                                layout = tclass.defaultLayoutName();
@@ -1110,9 +1130,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        else
                                c = par.getChar(pos - 1);
                        string arg = to_utf8(cmd.argument());
-                       cur.insert(new InsetQuotes(c, bufparams.quotes_language,
-                               (arg == "single") ? InsetQuotes::SingleQuotes
-                                       : InsetQuotes::DoubleQuotes));
+                       cur.insert(new InsetQuotes(bv->buffer(), c, (arg == "single")
+                               ? InsetQuotes::SingleQuotes : InsetQuotes::DoubleQuotes));
                        cur.posForward();
                }
                else
@@ -1148,17 +1167,18 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        // Single-click on work area
        case LFUN_MOUSE_PRESS:
                // We are not marking a selection with the keyboard in any case.
-               cur.bv().cursor().mark() = false;
+               cur.bv().cursor().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);
-                       break;                  
+                       break;
 
                case mouse_button::button2:
                        // Middle mouse pasting.
-                       if (!cap::selection()) {                        
+                       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,
@@ -1177,23 +1197,20 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        bv->cursor().finishUndo();
                        break;
 
-               case mouse_button::button3:
-                       if (cur.selection()) {
-                               DocIterator const selbeg = cur.selectionBegin();
-                               DocIterator const selend = cur.selectionEnd();
-                               Cursor tmpcur = cur;
-                               tm.setCursorFromCoordinates(tmpcur, cmd.x, cmd.y);
-                               // Don't do anything if we right-click a selection, a selection
-                               // context menu should popup instead.
-                               if (tmpcur < selbeg || tmpcur >= selend) {
-                                       cur.noUpdate();
-                                       return;
-                               }
+               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()
+                           && cur < bvcur.selectionEnd()) {
+                               cur.noUpdate();
+                               return;
                        }
-                       if (!bv->mouseSetCursor(cur, false)) {
+                       if (!bv->mouseSetCursor(cur, false))
                                cur.updateFlags(Update::SinglePar | Update::FitCursor);
-                               break;                  
-                       }
+                       break;
+               }
+
                default:
                        break;
                } // switch (cmd.button())
@@ -1232,7 +1249,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                // We continue with our existing selection or start a new one, so don't
                // reset the anchor.
                bvcur.setCursor(cur);
-               bvcur.selection() = true;
+               bvcur.setSelection(true);
                if (cur.top() == old) {
                        // We didn't move one iota, so no need to update the screen.
                        cur.updateFlags(Update::SinglePar | Update::FitCursor);
@@ -1250,13 +1267,17 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        // otherwise, single click does not clear persistent selection
                        // buffer.
                        if (cur.selection()) {
-                               // Finish selection.
-                               // If double click, cur is moved to the end of word by selectWord
-                               // but bvcur is current mouse position.
-                               cur.bv().cursor().selection() = true;
-                       }
+                               // Finish selection. If double click,
+                               // cur is moved to the end of word by
+                               // selectWord but bvcur is current
+                               // mouse position.
+                               cur.bv().cursor().setSelection();
+                               // We might have removed an empty but drawn selection
+                               // (probably a margin)
+                               cur.updateFlags(Update::SinglePar | Update::FitCursor);
+                       } else
+                               cur.noUpdate();
                        // FIXME: We could try to handle drag and drop of selection here.
-                       cur.noUpdate();
                        return;
 
                case mouse_button::button2:
@@ -1401,7 +1422,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(&pars[0].inInset());
                pars.back().setPlainOrDefaultLayout(tclass);
                int cap_pit = pars.size() - 1;
 
@@ -1410,7 +1431,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(&pars[0].inInset());
                        pars.back().setPlainOrDefaultLayout(tclass);
                }
 
@@ -1430,21 +1451,13 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        }
 
        case LFUN_NOMENCL_INSERT: {
-               FuncRequest cmd1 = cmd;
+               InsetCommandParams p(NOMENCL_CODE);
                if (cmd.argument().empty())
-                       cmd1 = FuncRequest(cmd,
-                               bv->cursor().innerText()->getStringToIndex(bv->cursor()));
-               Inset * inset = createInset(cur.bv().buffer(), cmd1);
-               if (!inset)
-                       break;
-               cur.recordUndo();
-               cur.clearSelection();
-               insertInset(cur, inset);
-               // Show the dialog for the nomenclature entry, since the
-               // description entry still needs to be filled in.
-               if (cmd.action == LFUN_NOMENCL_INSERT)
-                       inset->edit(cur, true);
-               cur.posForward();
+                       p["symbol"] = bv->cursor().innerText()->getStringToIndex(bv->cursor());
+               else
+                       p["symbol"] = cmd.argument();
+               string const data = InsetCommand::params2string("nomenclature", p);
+               bv->showDialog("nomenclature", data);
                break;
        }
 
@@ -1489,8 +1502,16 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                        MacroType type = MacroTypeNewcommand;
                        if (s2 == "def")
                                type = MacroTypeDef;
-                       cur.insert(new MathMacroTemplate(from_utf8(token(s, ' ', 0)), nargs, false, type));
-                       //cur.nextInset()->edit(cur, true);
+                       MathMacroTemplate * inset = new MathMacroTemplate(from_utf8(token(s, ' ', 0)), nargs, false, type);
+                       inset->setBuffer(bv->buffer());
+                       insertInset(cur, inset);
+
+                       // enter macro inset and select the name
+                       cur.push(*inset);
+                       cur.top().pos() = cur.top().lastpos();
+                       cur.resetAnchor();
+                       cur.setSelection(true);
+                       cur.top().pos() = 0;
                }
                break;
 
@@ -1506,6 +1527,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_MATH_MATRIX:
        case LFUN_MATH_DELIM:
        case LFUN_MATH_BIGDELIM: {
+               cur.recordUndo();
                cap::replaceSelection(cur);
                cur.insert(new InsetMathHull(hullSimple));
                checkAndActivateInset(cur, true);
@@ -1521,7 +1543,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                break;
        }
 
-       case LFUN_FONT_BOLD: {
+       case LFUN_FONT_BOLD:
+       case LFUN_FONT_BOLDSYMBOL: {
                Font font(ignore_font, ignore_language);
                font.fontInfo().setSeries(BOLD_SERIES);
                toggleAndShow(cur, this, font);
@@ -1608,9 +1631,9 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_FINISHED_LEFT:
                LYXERR(Debug::DEBUG, "handle LFUN_FINISHED_LEFT:\n" << cur);
-               // We're leaving an inset, going left. If the inset is LTR, we're 
+               // We're leaving an inset, going left. If the inset is LTR, we're
                // leaving from the front, so we should not move (remain at --- but
-               // not in --- the inset). If the inset is RTL, move left, without 
+               // not in --- the inset). If the inset is RTL, move left, without
                // entering the inset itself; i.e., move to after the inset.
                if (cur.paragraph().getFontSettings(
                                cur.bv().buffer().params(), cur.pos()).isRightToLeft())
@@ -1619,9 +1642,9 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_FINISHED_RIGHT:
                LYXERR(Debug::DEBUG, "handle LFUN_FINISHED_RIGHT:\n" << cur);
-               // We're leaving an inset, going right. If the inset is RTL, we're 
+               // We're leaving an inset, going right. If the inset is RTL, we're
                // leaving from the front, so we should not move (remain at --- but
-               // not in --- the inset). If the inset is LTR, move right, without 
+               // not in --- the inset). If the inset is LTR, move right, without
                // entering the inset itself; i.e., move to after the inset.
                if (!cur.paragraph().getFontSettings(
                                cur.bv().buffer().params(), cur.pos()).isRightToLeft())
@@ -1651,7 +1674,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                params2string(cur.paragraph(), data);
 
                // Will the paragraph accept changes from the dialog?
-               bool const accept = 
+               bool const accept =
                        cur.inset().allowParagraphCustomization(cur.idx());
 
                data = "update " + convert<string>(accept) + '\n' + data;
@@ -1699,8 +1722,10 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                                tclass.defaultLayoutName();
                        setLayout(cur, laystr);
                        ParagraphParameters p;
+                       // FIXME If this call were replaced with one to clearParagraphParams(),
+                       // then we could get rid of this method altogether.
                        setParagraphs(cur, p);
-                       // FIXME This should be simplified when InsetFloatList takes a 
+                       // FIXME This should be simplified when InsetFloatList takes a
                        // Buffer in its constructor.
                        InsetFloatList * ifl = new InsetFloatList(to_utf8(cmd.argument()));
                        ifl->setBuffer(bv->buffer());
@@ -1742,17 +1767,17 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
                // Given data, an encoding of the ParagraphParameters
                // generated in the Paragraph dialog, this function sets
                // the current paragraph, or currently selected paragraphs,
-               // appropriately. 
+               // appropriately.
                // NOTE: This function overrides all existing settings.
                setParagraphs(cur, cmd.argument());
                cur.message(_("Paragraph layout set"));
                break;
        }
-       
+
        case LFUN_PARAGRAPH_PARAMS: {
                // Given data, an encoding of the ParagraphParameters as we'd
-               // find them in a LyX file, this function modifies the current paragraph, 
-               // or currently selected paragraphs. 
+               // find them in a LyX file, this function modifies the current paragraph,
+               // or currently selected paragraphs.
                // NOTE: This function only modifies, and does not override, existing
                // settings.
                setParagraphs(cur, cmd.argument(), true);
@@ -1762,7 +1787,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_ESCAPE:
                if (cur.selection()) {
-                       cur.selection() = false;
+                       cur.setSelection(false);
                } else {
                        cur.undispatched();
                        // This used to be LFUN_FINISHED_RIGHT, I think FORWARD is more
@@ -1919,6 +1944,8 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                break;
        case LFUN_LISTING_INSERT:
                code = LISTINGS_CODE;
+               // not allowed in description items
+               enable = !inDescriptionItem(cur);
                break;
        case LFUN_FOOTNOTE_INSERT:
                code = FOOT_CODE;
@@ -1932,26 +1959,34 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_FLOAT_INSERT:
        case LFUN_FLOAT_WIDE_INSERT:
                code = FLOAT_CODE;
+               // not allowed in description items
+               enable = !inDescriptionItem(cur);
                break;
        case LFUN_WRAP_INSERT:
                code = WRAP_CODE;
+               // not allowed in description items
+               enable = !inDescriptionItem(cur);
                break;
        case LFUN_FLOAT_LIST_INSERT:
                code = FLOAT_LIST_CODE;
                break;
        case LFUN_CAPTION_INSERT:
                code = CAPTION_CODE;
+               // not allowed in description items
+               enable = !inDescriptionItem(cur);
                break;
        case LFUN_NOTE_INSERT:
                code = NOTE_CODE;
-               // in commands (sections etc., only Notes are allowed)
+               // in commands (sections etc.) and description items,
+               // only Notes are allowed
                enable = (cmd.argument().empty() || cmd.getArg(0) == "Note" ||
-                         !cur.paragraph().layout().isCommand());
+                         (!cur.paragraph().layout().isCommand()
+                          && !inDescriptionItem(cur)));
                break;
        case LFUN_FLEX_INSERT: {
                code = FLEX_CODE;
                string s = cmd.getArg(0);
-               InsetLayout il = 
+               InsetLayout il =
                        cur.buffer().params().documentClass().insetLayout(from_utf8(s));
                if (il.lyxtype() != "charstyle" &&
                    il.lyxtype() != "custom" &&
@@ -1986,6 +2021,10 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                code = INDEX_PRINT_CODE;
                break;
        case LFUN_NOMENCL_INSERT:
+               if (cur.selIsMultiCell() || cur.selIsMultiLine()) {
+                       enable = false;
+                       break;
+               }
                code = NOMENCL_CODE;
                break;
        case LFUN_NOMENCL_PRINT:
@@ -1995,6 +2034,10 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                code = TOC_CODE;
                break;
        case LFUN_HYPERLINK_INSERT:
+               if (cur.selIsMultiCell() || cur.selIsMultiLine()) {
+                       enable = false;
+                       break;
+               }
                code = HYPERLINK_CODE;
                break;
        case LFUN_QUOTE_INSERT:
@@ -2027,6 +2070,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                break;
 
        case LFUN_FONT_BOLD:
+       case LFUN_FONT_BOLDSYMBOL:
                flag.setOnOff(fontinfo.series() == BOLD_SERIES);
                break;
 
@@ -2055,7 +2099,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                                enable = !theClipboard().empty();
                        break;
                }
-               
+
                // we have an argument
                string const arg = to_utf8(cmd.argument());
                if (isStrUnsignedInt(arg)) {
@@ -2064,7 +2108,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                        enable = cap::numberOfSelections() > n;
                        break;
                }
-               
+
                // explicit graphics type?
                if ((arg == "pdf" && theClipboard().hasGraphicsContents(Clipboard::PdfGraphicsType))
                    || (arg == "png" && theClipboard().hasGraphicsContents(Clipboard::PngGraphicsType))
@@ -2073,7 +2117,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                        enable = true;
                        break;
                }
-               
+
                // unknown argument
                enable = false;
                break;
@@ -2101,7 +2145,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                        enable = cur.inset().lyxCode() == FLEX_CODE
                                 && il.lyxtype() == to_utf8(cmd.argument());
                } else {
-                       enable = !isMainText(cur.bv().buffer()) 
+                       enable = !isMainText(cur.bv().buffer())
                                 && cur.inset().nargs() == 1;
                }
                break;
@@ -2133,13 +2177,18 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
 
        case LFUN_SET_GRAPHICS_GROUP: {
                InsetGraphics * ins = graphics::getCurrentGraphicsInset(cur);
-               if (!ins) 
+               if (!ins)
                        enable = false;
                else
                        flag.setOnOff(to_utf8(cmd.argument()) == ins->getParams().groupId);
                break;
        }
 
+       case LFUN_NEWPAGE_INSERT:
+               // not allowed in description items
+               enable = !inDescriptionItem(cur);
+               break;
+
        case LFUN_WORD_DELETE_FORWARD:
        case LFUN_WORD_DELETE_BACKWARD:
        case LFUN_LINE_DELETE:
@@ -2188,7 +2237,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
        case LFUN_DATE_INSERT:
        case LFUN_SELF_INSERT:
        case LFUN_LINE_INSERT:
-       case LFUN_NEWPAGE_INSERT:
        case LFUN_MATH_DISPLAY:
        case LFUN_MATH_MODE:
        case LFUN_MATH_MACRO:
@@ -2261,4 +2309,22 @@ void Text::pasteString(Cursor & cur, docstring const & clip,
        }
 }
 
+
+// FIXME: an item inset would make things much easier.
+bool Text::inDescriptionItem(Cursor & cur) const
+{
+       Paragraph & par = cur.paragraph();
+       pos_type const pos = cur.pos();
+       pos_type const body_pos = par.beginOfBody();
+
+       if (par.layout().latextype != LATEX_LIST_ENVIRONMENT
+           && (par.layout().latextype != LATEX_ITEM_ENVIRONMENT
+               || par.layout().margintype != MARGIN_FIRST_DYNAMIC))
+               return false;
+
+       return (pos < body_pos
+               || (pos == body_pos
+                   && (pos == 0 || par.getChar(pos - 1) != ' ')));
+}
+
 } // namespace lyx