#include "MathCompletionList.h"
#include "MathData.h"
#include "MathFactory.h"
-#include "MathMacro.h"
-#include "MathMacroArgument.h"
+#include "InsetMathMacro.h"
+#include "InsetMathMacroArgument.h"
#include "MathParser.h"
#include "MathStream.h"
#include "MathSupport.h"
-#include "Bidi.h"
#include "Buffer.h"
+#include "BufferParams.h"
#include "BufferView.h"
#include "CoordCache.h"
#include "Cursor.h"
#include "Encoding.h"
#include "FuncRequest.h"
#include "FuncStatus.h"
+#include "LaTeXFeatures.h"
#include "LyX.h"
#include "LyXRC.h"
+#include "MetricsInfo.h"
#include "OutputParams.h"
+#include "TexRow.h"
#include "Text.h"
+#include "frontends/Application.h"
#include "frontends/Clipboard.h"
#include "frontends/Painter.h"
#include "frontends/Selection.h"
-#include "support/lassert.h"
#include "support/debug.h"
+#include "support/docstream.h"
#include "support/gettext.h"
+#include "support/lassert.h"
#include "support/lstrings.h"
#include "support/textutils.h"
-#include "support/docstream.h"
#include <algorithm>
#include <sstream>
// to touch all (math)inset's draw() methods. Right now, we'll store
// absolute value, and make them here relative, only to make them
// absolute again when actually drawing the cursor. What a mess.
- LASSERT(&sl.inset() == this, /**/);
+ LASSERT(&sl.inset() == this, return);
MathData const & ar = sl.cell();
CoordCache const & coord_cache = bv.coordCache();
if (!coord_cache.getArrays().has(&ar)) {
// << " asc: " << ascent() << " des: " << descent()
// << " ar.asc: " << ar.ascent() << " ar.des: " << ar.descent() << endl;
// move cursor visually into empty cells ("blue rectangles");
- if (ar.empty())
- x += 2;
+ if (ar.empty()) {
+ Dimension const dim = coord_cache.getArrays().dim(&ar);
+ x += dim.wid / 3;
+ }
}
-void InsetMathNest::metrics(MetricsInfo const & mi) const
+void InsetMathNest::cellsMetrics(MetricsInfo const & mi) const
{
MetricsInfo m = mi;
- for (idx_type i = 0, n = nargs(); i != n; ++i) {
+ for (auto const & cell : cells_) {
Dimension dim;
- cell(i).metrics(m, dim);
+ cell.metrics(m, dim);
}
}
bool InsetMathNest::idxNext(Cursor & cur) const
{
- LASSERT(&cur.inset() == this, /**/);
+ LASSERT(&cur.inset() == this, return false);
if (cur.idx() == cur.lastidx())
return false;
++cur.idx();
bool InsetMathNest::idxPrev(Cursor & cur) const
{
- LASSERT(&cur.inset() == this, /**/);
+ LASSERT(&cur.inset() == this, return false);
if (cur.idx() == 0)
return false;
--cur.idx();
bool InsetMathNest::idxFirst(Cursor & cur) const
{
- LASSERT(&cur.inset() == this, /**/);
+ LASSERT(&cur.inset() == this, return false);
if (nargs() == 0)
return false;
cur.idx() = 0;
bool InsetMathNest::idxLast(Cursor & cur) const
{
- LASSERT(&cur.inset() == this, /**/);
+ LASSERT(&cur.inset() == this, return false);
if (nargs() == 0)
return false;
cur.idx() = cur.lastidx();
void InsetMathNest::dump() const
{
odocstringstream oss;
- WriteStream os(oss);
+ otexrowstream ots(oss);
+ WriteStream os(ots);
os << "---------------------------------------------\n";
write(os);
os << "\n";
}
-void InsetMathNest::draw(PainterInfo & pi, int x, int y) const
+void InsetMathNest::draw(PainterInfo &, int, int) const
{
#if 0
if (lock_)
pi.pain.fillRectangle(x, y - ascent(), width(), height(),
Color_mathlockbg);
#endif
- setPosCache(pi, x, y);
-}
-
-
-void InsetMathNest::drawSelection(PainterInfo & pi, int x, int y) const
-{
- BufferView & bv = *pi.base.bv;
- // this should use the x/y values given, not the cached values
- Cursor & cur = bv.cursor();
- if (!cur.selection())
- return;
- if (&cur.inset() != this)
- return;
-
- // FIXME: hack to get position cache warm
- bool const original_drawing_state = pi.pain.isDrawingEnabled();
- pi.pain.setDrawingEnabled(false);
- draw(pi, x, y);
- pi.pain.setDrawingEnabled(original_drawing_state);
-
- CursorSlice s1 = cur.selBegin();
- CursorSlice s2 = cur.selEnd();
-
- //lyxerr << "InsetMathNest::drawing selection: "
- // << " s1: " << s1 << " s2: " << s2 << endl;
- if (s1.idx() == s2.idx()) {
- MathData const & c = cell(s1.idx());
- Geometry const & g = bv.coordCache().getArrays().geometry(&c);
- int x1 = g.pos.x_ + c.pos2x(pi.base.bv, s1.pos());
- int y1 = g.pos.y_ - g.dim.ascent();
- int x2 = g.pos.x_ + c.pos2x(pi.base.bv, s2.pos());
- int y2 = g.pos.y_ + g.dim.descent();
- pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, Color_selection);
- //lyxerr << "InsetMathNest::drawing selection 3: "
- // << " x1: " << x1 << " x2: " << x2
- // << " y1: " << y1 << " y2: " << y2 << endl;
- } else {
- for (idx_type i = 0; i < nargs(); ++i) {
- if (idxBetween(i, s1.idx(), s2.idx())) {
- MathData const & c = cell(i);
- Geometry const & g = bv.coordCache().getArrays().geometry(&c);
- int x1 = g.pos.x_;
- int y1 = g.pos.y_ - g.dim.ascent();
- int x2 = g.pos.x_ + g.dim.width();
- int y2 = g.pos.y_ + g.dim.descent();
- pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, Color_selection);
- }
- }
- }
}
void InsetMathNest::write(WriteStream & os) const
{
+ MathEnsurer ensurer(os, currentMode() == MATH_MODE);
ModeSpecifier specifier(os, currentMode(), lockedMode());
docstring const latex_name = name();
os << '\\' << latex_name;
- for (size_t i = 0; i < nargs(); ++i)
+ for (size_t i = 0; i < nargs(); ++i) {
+ Changer dummy = os.changeRowEntry(TexRow::mathEntry(id(),i));
os << '{' << cell(i) << '}';
+ }
if (nargs() == 0)
os.pendingSpace(true);
if (lock_ && !os.latex()) {
}
-int InsetMathNest::latex(odocstream & os, OutputParams const & runparams) const
+void InsetMathNest::latex(otexstream & os, OutputParams const & runparams) const
{
WriteStream wi(os, runparams.moving_arg, true,
- runparams.dryrun ? WriteStream::wsDryrun : WriteStream::wsDefault,
- runparams.encoding);
+ runparams.dryrun ? WriteStream::wsDryrun : WriteStream::wsDefault,
+ runparams.encoding);
+ wi.strikeoutMath(runparams.inDeletedInset
+ && (!LaTeXFeatures::isAvailable("dvipost")
+ || (runparams.flavor != OutputParams::LATEX
+ && runparams.flavor != OutputParams::DVILUATEX)));
+ if (runparams.inulemcmd) {
+ wi.ulemCmd(WriteStream::UNDERLINE);
+ if (runparams.local_font) {
+ FontInfo f = runparams.local_font->fontInfo();
+ if (f.strikeout() == FONT_ON)
+ wi.ulemCmd(WriteStream::STRIKEOUT);
+ }
+ }
+ wi.canBreakLine(os.canBreakLine());
+ Changer dummy = wi.changeRowEntry(TexRow::textEntry(runparams.lastid,
+ runparams.lastpos));
write(wi);
- return wi.line();
+ // Reset parbreak status after a math inset.
+ os.lastChar(0);
+ os.canBreakLine(wi.canBreakLine());
}
bool InsetMathNest::setMouseHover(BufferView const * bv, bool mouse_hover)
+ const
{
mouse_hover_[bv] = mouse_hover;
return true;
parseflg |= Parse::VERBATIM;
// fall through
case LFUN_PASTE: {
- if (cur.currentMode() <= TEXT_MODE)
+ if (cur.currentMode() != MATH_MODE)
parseflg |= Parse::TEXTMODE;
cur.recordUndoSelection();
cur.message(_("Paste"));
replaceSelection(cur);
docstring topaste;
if (cmd.argument().empty() && !theClipboard().isInternal())
- topaste = theClipboard().getAsText();
+ topaste = theClipboard().getAsText(frontend::Clipboard::PlainTextType);
else {
size_t n = 0;
idocstringstream is(cmd.argument());
is >> n;
- topaste = cap::selection(n);
+ topaste = cap::selection(n, buffer().params().documentClassPtr());
}
cur.niceInsert(topaste, parseflg, false);
cur.clearSelection(); // bug 393
cur.bv().cursor() = cur;
break;
+ case LFUN_WORD_RIGHT:
+ case LFUN_WORD_LEFT:
+ case LFUN_WORD_BACKWARD:
+ case LFUN_WORD_FORWARD:
case LFUN_CHAR_RIGHT:
case LFUN_CHAR_LEFT:
case LFUN_CHAR_BACKWARD:
case LFUN_CHAR_FORWARD:
cur.screenUpdateFlags(Update::Decoration | Update::FitCursor);
+ // fall through
+ case LFUN_WORD_RIGHT_SELECT:
+ case LFUN_WORD_LEFT_SELECT:
+ case LFUN_WORD_BACKWARD_SELECT:
+ case LFUN_WORD_FORWARD_SELECT:
case LFUN_CHAR_RIGHT_SELECT:
case LFUN_CHAR_LEFT_SELECT:
case LFUN_CHAR_BACKWARD_SELECT:
case LFUN_CHAR_FORWARD_SELECT: {
// are we in a selection?
- bool select = (act == LFUN_CHAR_RIGHT_SELECT
+ bool select = (act == LFUN_WORD_RIGHT_SELECT
+ || act == LFUN_WORD_LEFT_SELECT
+ || act == LFUN_WORD_BACKWARD_SELECT
+ || act == LFUN_WORD_FORWARD_SELECT
+ || act == LFUN_CHAR_RIGHT_SELECT
|| act == LFUN_CHAR_LEFT_SELECT
|| act == LFUN_CHAR_BACKWARD_SELECT
|| act == LFUN_CHAR_FORWARD_SELECT);
+ // select words
+ bool word = (act == LFUN_WORD_RIGHT_SELECT
+ || act == LFUN_WORD_LEFT_SELECT
+ || act == LFUN_WORD_BACKWARD_SELECT
+ || act == LFUN_WORD_FORWARD_SELECT
+ || act == LFUN_WORD_RIGHT
+ || act == LFUN_WORD_LEFT
+ || act == LFUN_WORD_BACKWARD
+ || act == LFUN_WORD_FORWARD);
// are we moving forward or backwards?
// If the command was RIGHT or LEFT, then whether we're moving forward
// or backwards depends on the cursor movement mode (logical or visual):
FuncCode finish_lfun;
if (act == LFUN_CHAR_FORWARD
- || act == LFUN_CHAR_FORWARD_SELECT) {
+ || act == LFUN_CHAR_FORWARD_SELECT
+ || act == LFUN_WORD_FORWARD
+ || act == LFUN_WORD_FORWARD_SELECT) {
forward = true;
finish_lfun = LFUN_FINISHED_FORWARD;
}
else if (act == LFUN_CHAR_BACKWARD
- || act == LFUN_CHAR_BACKWARD_SELECT) {
+ || act == LFUN_CHAR_BACKWARD_SELECT
+ || act == LFUN_WORD_BACKWARD
+ || act == LFUN_WORD_BACKWARD_SELECT) {
forward = false;
finish_lfun = LFUN_FINISHED_BACKWARD;
}
else {
bool right = (act == LFUN_CHAR_RIGHT_SELECT
- || act == LFUN_CHAR_RIGHT);
- if (lyxrc.visual_cursor || !reverseDirectionNeeded(cur))
+ || act == LFUN_CHAR_RIGHT
+ || act == LFUN_WORD_RIGHT_SELECT
+ || act == LFUN_WORD_RIGHT);
+ if (lyxrc.visual_cursor || !cur.reverseDirectionNeeded())
forward = right;
else
forward = !right;
cur.clearTargetX();
cur.macroModeClose();
// try moving forward or backwards as necessary...
- if (!(forward ? cursorMathForward(cur) : cursorMathBackward(cur))) {
+ if (!(forward ? cur.mathForward(word) : cur.mathBackward(word))) {
// ... and if movement failed, then finish forward or backwards
// as necessary
cmd = FuncRequest(finish_lfun);
case LFUN_DOWN:
case LFUN_UP:
+ case LFUN_PARAGRAPH_UP:
+ case LFUN_PARAGRAPH_DOWN:
cur.screenUpdateFlags(Update::Decoration | Update::FitCursor);
+ // fall through
case LFUN_DOWN_SELECT:
- case LFUN_UP_SELECT: {
+ case LFUN_UP_SELECT:
+ case LFUN_PARAGRAPH_UP_SELECT:
+ case LFUN_PARAGRAPH_DOWN_SELECT: {
// close active macro
if (cur.inMacroMode()) {
cur.macroModeClose();
}
// stop/start the selection
- bool select = act == LFUN_DOWN_SELECT ||
- act == LFUN_UP_SELECT;
+ bool select = act == LFUN_DOWN_SELECT
+ || act == LFUN_UP_SELECT
+ || act == LFUN_PARAGRAPH_DOWN_SELECT
+ || act == LFUN_PARAGRAPH_UP_SELECT;
cur.selHandle(select);
+ // handle autocorrect:
+ if (lyxrc.autocorrection_math && cur.autocorrect()) {
+ cur.autocorrect() = false;
+ cur.message(_("Autocorrect Off ('!' to enter)"));
+ }
+
// go up/down
- bool up = act == LFUN_UP || act == LFUN_UP_SELECT;
+ bool up = act == LFUN_UP || act == LFUN_UP_SELECT
+ || act == LFUN_PARAGRAPH_UP || act == LFUN_PARAGRAPH_UP_SELECT;
bool successful = cur.upDownInMath(up);
if (successful)
break;
}
case LFUN_MOUSE_DOUBLE:
- case LFUN_MOUSE_TRIPLE:
case LFUN_WORD_SELECT:
cur.pos() = 0;
- cur.idx() = 0;
- cur.resetAnchor();
- cur.setSelection(true);
+ cur.bv().mouseSetCursor(cur);
cur.pos() = cur.lastpos();
- cur.idx() = cur.lastidx();
+ cur.bv().mouseSetCursor(cur, true);
break;
- case LFUN_PARAGRAPH_UP:
- case LFUN_PARAGRAPH_DOWN:
- cur.screenUpdateFlags(Update::Decoration | Update::FitCursor);
- case LFUN_PARAGRAPH_UP_SELECT:
- case LFUN_PARAGRAPH_DOWN_SELECT:
+ case LFUN_MOUSE_TRIPLE:
+ cur.idx() = 0;
+ cur.pos() = 0;
+ cur.bv().mouseSetCursor(cur);
+ cur.idx() = cur.lastidx();
+ cur.pos() = cur.lastpos();
+ cur.bv().mouseSetCursor(cur, true);
break;
case LFUN_LINE_BEGIN:
- case LFUN_WORD_BACKWARD:
- case LFUN_WORD_LEFT:
cur.screenUpdateFlags(Update::Decoration | Update::FitCursor);
+ // fall through
case LFUN_LINE_BEGIN_SELECT:
- case LFUN_WORD_BACKWARD_SELECT:
- case LFUN_WORD_LEFT_SELECT:
cur.selHandle(act == LFUN_WORD_BACKWARD_SELECT ||
act == LFUN_WORD_LEFT_SELECT ||
act == LFUN_LINE_BEGIN_SELECT);
}
break;
- case LFUN_WORD_FORWARD:
- case LFUN_WORD_RIGHT:
case LFUN_LINE_END:
cur.screenUpdateFlags(Update::Decoration | Update::FitCursor);
- case LFUN_WORD_FORWARD_SELECT:
- case LFUN_WORD_RIGHT_SELECT:
+ // fall through
case LFUN_LINE_END_SELECT:
cur.selHandle(act == LFUN_WORD_FORWARD_SELECT ||
act == LFUN_WORD_RIGHT_SELECT ||
if (cur.pos() == 0)
// May affect external cell:
cur.recordUndoInset();
- else
+ else if (!cur.inMacroMode())
cur.recordUndoSelection();
// if the inset can not be removed from within, delete it
- if (!cur.backspace()) {
- FuncRequest cmd = FuncRequest(LFUN_CHAR_DELETE_FORWARD);
+ if (!cur.backspace(cmd.getArg(0) == "force")) {
+ FuncRequest cmd = FuncRequest(LFUN_CHAR_DELETE_FORWARD, "force");
cur.innerText()->dispatch(cur, cmd);
}
break;
else
cur.recordUndoSelection();
// if the inset can not be removed from within, delete it
- if (!cur.erase()) {
- FuncRequest cmd = FuncRequest(LFUN_CHAR_DELETE_FORWARD);
+ if (!cur.erase(cmd.getArg(0) == "force")) {
+ FuncRequest cmd = FuncRequest(LFUN_CHAR_DELETE_FORWARD, "force");
cur.innerText()->dispatch(cur, cmd);
}
break;
// if relevant. Think typing "\frac<space>".
if (cmd.argument()[0] == ' '
&& cur.inMacroMode() && cur.macroName() != "\\"
- && cur.macroModeClose()) {
+ && cur.macroModeClose() && cur.pos() > 0) {
MathAtom const atom = cur.prevAtom();
if (atom->asNestInset() && atom->isActive()) {
cur.posBackward();
break;
case LFUN_FONT_BOLD:
- if (currentMode() <= TEXT_MODE)
+ if (currentMode() != MATH_MODE)
handleFont(cur, cmd.argument(), "textbf");
else
handleFont(cur, cmd.argument(), "mathbf");
break;
case LFUN_FONT_BOLDSYMBOL:
- if (currentMode() <= TEXT_MODE)
+ if (currentMode() != MATH_MODE)
handleFont(cur, cmd.argument(), "textbf");
else
handleFont(cur, cmd.argument(), "boldsymbol");
break;
case LFUN_FONT_SANS:
- if (currentMode() <= TEXT_MODE)
+ if (currentMode() != MATH_MODE)
handleFont(cur, cmd.argument(), "textsf");
else
handleFont(cur, cmd.argument(), "mathsf");
break;
case LFUN_FONT_EMPH:
- if (currentMode() <= TEXT_MODE)
+ if (currentMode() != MATH_MODE)
handleFont(cur, cmd.argument(), "emph");
else
handleFont(cur, cmd.argument(), "mathcal");
break;
case LFUN_FONT_ROMAN:
- if (currentMode() <= TEXT_MODE)
+ if (currentMode() != MATH_MODE)
handleFont(cur, cmd.argument(), "textrm");
else
handleFont(cur, cmd.argument(), "mathrm");
break;
case LFUN_FONT_TYPEWRITER:
- if (currentMode() <= TEXT_MODE)
+ if (currentMode() != MATH_MODE)
handleFont(cur, cmd.argument(), "texttt");
else
handleFont(cur, cmd.argument(), "mathtt");
handleFont(cur, cmd.argument(), "mathfrak");
break;
case LFUN_FONT_ITAL:
- if (currentMode() <= TEXT_MODE)
+ if (currentMode() != MATH_MODE)
handleFont(cur, cmd.argument(), "textit");
else
handleFont(cur, cmd.argument(), "mathit");
break;
case LFUN_FONT_NOUN:
- if (currentMode() <= TEXT_MODE)
+ if (currentMode() != MATH_MODE)
// FIXME: should be "noun"
handleFont(cur, cmd.argument(), "textsc");
else
case LFUN_FONT_DEFAULT:
handleFont(cur, cmd.argument(), "textnormal");
break;
-
case LFUN_FONT_UNDERLINE:
cur.recordUndo();
cur.handleNest(createInsetMath("underline", cur.buffer()));
break;
+
case LFUN_MATH_MODE: {
#if 1
// ignore math-mode on when already in math mode
cur.macroModeClose();
docstring const save_selection = grabAndEraseSelection(cur);
selClearOrDel(cur);
- //cur.plainInsert(MathAtom(new InsetMathMBox(cur.bv())));
- if (currentMode() <= Inset::TEXT_MODE)
+ if (currentMode() != Inset::MATH_MODE)
cur.plainInsert(MathAtom(new InsetMathEnsureMath(buffer_)));
else
- cur.plainInsert(MathAtom(new InsetMathBox(buffer_, from_ascii("mbox"))));
+ cur.plainInsert(createInsetMath("text", buffer_));
cur.posBackward();
cur.pushBackward(*cur.nextInset());
cur.niceInsert(save_selection);
case LFUN_REGEXP_MODE: {
InsetMath * im = cur.inset().asInsetMath();
if (im) {
- InsetMathHull * i = im->asHullInset();
+ InsetMathHull * i = im->asHullInset();
if (i && i->getType() == hullRegexp) {
cur.message(_("Already in regular expression mode"));
break;
cur.recordUndo();
unsigned int m = 1;
unsigned int n = 1;
- docstring name;
+ docstring name = from_ascii("matrix");
idocstringstream is(cmd.argument());
is >> m >> n >> name;
if (m < 1)
m = 1;
if (n < 1)
n = 1;
+ // check if we have a valid decoration
+ if (name != "pmatrix" && name != "bmatrix"
+ && name != "Bmatrix" && name != "vmatrix"
+ && name != "Vmatrix" && name != "matrix")
+ name = from_ascii("matrix");
+
cur.niceInsert(
MathAtom(new InsetMathAMSArray(buffer_, name, m, n)));
break;
break;
}
- case LFUN_SPACE_INSERT:
+ case LFUN_SPACE_INSERT: {
cur.recordUndoSelection();
- cur.insert(MathAtom(new InsetMathSpace));
+ string const name = cmd.getArg(0);
+ if (name == "normal")
+ cur.insert(MathAtom(new InsetMathSpace(" ", "")));
+ else if (name == "protected")
+ cur.insert(MathAtom(new InsetMathSpace("~", "")));
+ else if (name == "thin" || name == "med" || name == "thick")
+ cur.insert(MathAtom(new InsetMathSpace(name + "space", "")));
+ else if (name == "hfill*")
+ cur.insert(MathAtom(new InsetMathSpace("hspace*{\\fill}", "")));
+ else if (name == "quad" || name == "qquad" ||
+ name == "enspace" || name == "enskip" ||
+ name == "negthinspace" || name == "negmedspace" ||
+ name == "negthickspace" || name == "hfill")
+ cur.insert(MathAtom(new InsetMathSpace(name, "")));
+ else if (name == "hspace" || name == "hspace*") {
+ string const len = cmd.getArg(1);
+ if (len.empty() || !isValidLength(len)) {
+ lyxerr << "LyX function 'space-insert " << name << "' "
+ "needs a valid length argument." << endl;
+ break;
+ }
+ cur.insert(MathAtom(new InsetMathSpace(name, len)));
+ } else
+ cur.insert(MathAtom(new InsetMathSpace));
break;
+ }
case LFUN_MATH_SPACE:
cur.recordUndoSelection();
bool fold = act == LFUN_MATH_MACRO_FOLD;
bool found = findMacroToFoldUnfold(it, fold);
if (found) {
- MathMacro * macro = it.nextInset()->asInsetMath()->asMacro();
+ InsetMathMacro * macro = it.nextInset()->asInsetMath()->asMacro();
cur.recordUndoInset();
if (fold)
macro->fold(cur);
if (createInsetMath_fromDialogStr(cmd.argument(), ar)) {
cur.recordUndoSelection();
cur.insert(ar);
- cur.forceBufferUpdate();
+ cur.forceBufferUpdate();
} else
cur.undispatched();
break;
// go backward through the current cell
Inset * inset = it.nextInset();
while (inset && inset->asInsetMath()) {
- MathMacro * macro = inset->asInsetMath()->asMacro();
+ InsetMathMacro * macro = inset->asInsetMath()->asMacro();
if (macro) {
// found the an macro to open/close?
if (macro->folded() != fold)
// we just need to be in math mode to enable that
case LFUN_MATH_SIZE:
case LFUN_MATH_SPACE:
- case LFUN_MATH_LIMITS:
case LFUN_MATH_EXTERN:
flag.setEnabled(true);
break;
break;
}
+ case LFUN_MATH_MODE:
+ // forbid "math-mode on" in math mode to prevent irritating
+ // behaviour of menu entries (bug 6709)
+ flag.setEnabled(currentMode() == TEXT_MODE || arg != "on");
+ break;
+
case LFUN_MATH_INSERT:
flag.setEnabled(currentMode() != TEXT_MODE);
break;
break;
}
+ case LFUN_DIALOG_SHOW_NEW_INSET: {
+ docstring const & name = cmd.argument();
+ if (name == "space")
+ flag.setEnabled(false);
+ break;
+ }
+
+
case LFUN_MATH_DELIM:
case LFUN_MATH_BIGDELIM:
// Don't do this with multi-cell selections
flag.setEnabled(false);
break;
+ case LFUN_CAPTION_INSERT:
+ flag.setEnabled(false);
+ break;
+
+ case LFUN_SPACE_INSERT: {
+ docstring const & name = cmd.argument();
+ if (name == "visible")
+ flag.setEnabled(false);
+ break;
+ }
+
case LFUN_INSET_DISSOLVE:
flag.setEnabled(!asHullInset());
break;
+ case LFUN_PASTE: {
+ docstring const & name = cmd.argument();
+ if (name == "html" || name == "latex")
+ flag.setEnabled(false);
+ break;
+ }
+
default:
ret = false;
break;
Inset * InsetMathNest::editXY(Cursor & cur, int x, int y)
{
- int idx_min = 0;
+ int idx_min = -1;
int dist_min = 1000000;
for (idx_type i = 0, n = nargs(); i != n; ++i) {
int const d = cell(i).dist(cur.bv(), x, y);
idx_min = i;
}
}
+ if (idx_min == -1)
+ return this;
+
MathData & ar = cell(idx_min);
cur.push(*this);
cur.idx() = idx_min;
{
//lyxerr << "## lfunMousePress: buttons: " << cmd.button() << endl;
BufferView & bv = cur.bv();
+ if (cmd.button() == mouse_button::button3) {
+ // Don't do anything if we right-click a
+ // selection, a context menu will popup.
+ if (bv.cursor().selection() && cur >= bv.cursor().selectionBegin()
+ && cur < bv.cursor().selectionEnd()) {
+ cur.noScreenUpdate();
+ return;
+ }
+ }
+
+ // set cursor after the inset if x is nearer to that position (bug 9748)
+ cur.moveToClosestEdge(cmd.x(), true);
+
bool do_selection = cmd.button() == mouse_button::button1
- && cmd.argument() == "region-select";
+ && cmd.modifier() == ShiftModifier;
bv.mouseSetCursor(cur, do_selection);
if (cmd.button() == mouse_button::button1) {
//lyxerr << "## lfunMousePress: setting cursor to: " << cur << endl;
// cur.result().update(): don't overwrite previously set flags.
cur.screenUpdateFlags(Update::Decoration | Update::FitCursor
| cur.result().screenUpdate());
- } else if (cmd.button() == mouse_button::button2) {
+ } else if (cmd.button() == mouse_button::button2 && lyxrc.mouse_middlebutton_paste) {
if (cap::selection()) {
// See comment in Text::dispatch why we do this
cap::copySelectionToStack();
void InsetMathNest::lfunMouseMotion(Cursor & cur, FuncRequest & cmd)
{
// only select with button 1
- if (cmd.button() == mouse_button::button1) {
- Cursor & bvcur = cur.bv().cursor();
- if (bvcur.realAnchor().hasPart(cur)) {
- //lyxerr << "## lfunMouseMotion: cursor: " << cur << endl;
- bvcur.setCursor(cur);
- bvcur.setSelection(true);
- //lyxerr << "MOTION " << bvcur << endl;
- } else
- cur.undispatched();
+ if (cmd.button() != mouse_button::button1)
+ return;
+
+ Cursor & bvcur = cur.bv().cursor();
+
+ // ignore motions deeper nested than the real anchor
+ if (!bvcur.realAnchor().hasPart(cur)) {
+ cur.undispatched();
+ return;
}
+
+ // set cursor after the inset if x is nearer to that position (bug 9748)
+ cur.moveToClosestEdge(cmd.x());
+
+ CursorSlice old = bvcur.top();
+
+ // We continue with our existing selection or start a new one, so don't
+ // reset the anchor.
+ bvcur.setCursor(cur);
+ // Did we actually move?
+ if (cur.top() == old)
+ // We didn't move one iota, so no need to change selection status
+ // or update the screen.
+ cur.screenUpdateFlags(Update::SinglePar | Update::FitCursor);
+ else
+ bvcur.setSelection();
}
cur.noScreenUpdate();
else {
Cursor & bvcur = cur.bv().cursor();
- bvcur.setSelection(true);
+ bvcur.selection(true);
}
return;
}
cur.backspace();
int n = c - '0';
if (n >= 1 && n <= 9)
- cur.insert(new MathMacroArgument(n));
+ cur.insert(new InsetMathMacroArgument(n));
return true;
}
// do not finish macro for known * commands
- MathWordList const & mwl = mathedWordList();
bool star_macro = c == '*'
- && (mwl.find(name.substr(1) + "*") != mwl.end()
+ && (in_word_set(name.substr(1) + '*')
|| cur.buffer()->getMacro(name.substr(1) + "*", cur, true));
if (isAlphaASCII(c) || star_macro) {
cur.activeMacro()->setName(name + docstring(1, c));
// remove the '\\'
if (c == '\\') {
cur.backspace();
- if (currentMode() <= InsetMath::TEXT_MODE)
+ if (currentMode() != InsetMath::MATH_MODE)
cur.niceInsert(createInsetMath("textbackslash", buf));
else
cur.niceInsert(createInsetMath("backslash", buf));
} else if (c == '^' && currentMode() == InsetMath::MATH_MODE) {
cur.backspace();
cur.niceInsert(createInsetMath("mathcircumflex", buf));
- } else if (c == '{') {
- cur.backspace();
- cur.niceInsert(MathAtom(new InsetMathBrace(buf)));
- } else if (c == '%') {
+ } else if (c == '{' || c == '%') {
+ //using the saved selection as argument
+ InsetMathUnknown * p = cur.activeMacro();
+ p->finalize();
+ MathData sel(cur.buffer());
+ asArray(p->selection(), sel);
cur.backspace();
- cur.niceInsert(MathAtom(new InsetMathComment(buf)));
+ if (c == '{')
+ cur.niceInsert(MathAtom(new InsetMathBrace(sel)));
+ else
+ cur.niceInsert(MathAtom(new InsetMathComment(sel)));
} else if (c == '#') {
- LASSERT(cur.activeMacro(), /**/);
+ LASSERT(cur.activeMacro(), return false);
cur.activeMacro()->setName(name + docstring(1, c));
} else {
cur.backspace();
new InsetMathBig(name.substr(1), delim)));
return true;
}
+ } else if (name == "\\smash" && c == '[') {
+ // We can't use cur.macroModeClose() because
+ // it would create an InsetMathPhantom
+ InsetMathUnknown * p = cur.activeMacro();
+ p->finalize();
+ interpretChar(cur, c);
+ return true;
}
// leave macro mode and try again if necessary
cur.autocorrect() = false;
cur.message(_("Autocorrect Off ('!' to enter)"));
return true;
- }
+ }
if (lyxrc.autocorrection_math && c == '!' && !cur.autocorrect()) {
cur.autocorrect() = true;
cur.message(_("Autocorrect On (<space> to exit)"));
// just clear selection on pressing the space bar
if (cur.selection() && c == ' ') {
- cur.setSelection(false);
+ cur.selection(false);
return true;
}
//lyxerr << "starting with macro" << endl;
bool reduced = cap::reduceSelectionToOneCell(cur);
if (reduced || !cur.selection()) {
+ cur.recordUndoInset();
docstring const safe = cap::grabAndEraseSelection(cur);
- cur.insert(MathAtom(new InsetMathUnknown(from_ascii("\\"), safe, false)));
+ if (!cur.inRegexped())
+ cur.insert(MathAtom(new InsetMathUnknown(from_ascii("\\"), safe, false)));
+ else
+ cur.niceInsert(createInsetMath("backslash", buf));
}
return true;
}
selClearOrDel(cur);
if (c == '\n') {
- if (currentMode() <= InsetMath::TEXT_MODE)
+ if (currentMode() != InsetMath::MATH_MODE)
cur.insert(c);
return true;
}
if (c == ' ') {
- if (currentMode() <= InsetMath::TEXT_MODE) {
+ if (currentMode() != InsetMath::MATH_MODE) {
// insert spaces in text or undecided mode,
// but suppress direct insertion of two spaces in a row
// the still allows typing '<space>a<space>' and deleting the 'a', but
// it is better than nothing...
- if (!cur.pos() != 0 || cur.prevAtom()->getChar() != ' ') {
+ if (cur.pos() == 0 || cur.prevAtom()->getChar() != ' ') {
cur.insert(c);
// FIXME: we have to enable full redraw here because of the
// visual box corners that define the inset. If we know for
}
// These should be treated differently when not in text mode:
- if (currentMode() != InsetMath::TEXT_MODE) {
+ if (cur.inRegexped()) {
+ switch (c) {
+ case '^':
+ cur.niceInsert(createInsetMath("mathcircumflex", buf));
+ break;
+ case '{':
+ case '}':
+ case '#':
+ case '%':
+ case '_':
+ cur.niceInsert(createInsetMath(docstring(1, c), buf));
+ break;
+ case '~':
+ cur.niceInsert(createInsetMath("sim", buf));
+ break;
+ default:
+ cur.insert(c);
+ }
+ return true;
+ } else if (currentMode() != InsetMath::TEXT_MODE) {
if (c == '_') {
script(cur, false, save_selection);
return true;
cur.niceInsert(createInsetMath("sim", buf));
return true;
}
- if (currentMode() == InsetMath::MATH_MODE && !isAsciiOrMathAlpha(c)) {
+ if (currentMode() == InsetMath::MATH_MODE && Encodings::isUnicodeTextOnly(c)) {
MathAtom at = createInsetMath("text", buf);
at.nucleus()->cell(0).push_back(MathAtom(new InsetMathChar(c)));
cur.niceInsert(at);
}
-bool InsetMathNest::cursorMathForward(Cursor & cur)
-{
- if (cur.pos() != cur.lastpos() && cur.openable(cur.nextAtom())) {
- cur.pushBackward(*cur.nextAtom().nucleus());
- cur.inset().idxFirst(cur);
- return true;
- }
- if (cur.posForward() || idxForward(cur))
- return true;
- // try to pop forwards --- but don't pop out of math! leave that to
- // the FINISH lfuns
- int s = cur.depth() - 2;
- if (s >= 0 && cur[s].inset().asInsetMath())
- return cur.popForward();
- return false;
-}
-
-
-bool InsetMathNest::cursorMathBackward(Cursor & cur)
-{
- if (cur.pos() != 0 && cur.openable(cur.prevAtom())) {
- cur.posBackward();
- cur.push(*cur.nextAtom().nucleus());
- cur.inset().idxLast(cur);
- return true;
- }
- if (cur.posBackward() || idxBackward(cur))
- return true;
- // try to pop backwards --- but don't pop out of math! leave that to
- // the FINISH lfuns
- int s = cur.depth() - 2;
- if (s >= 0 && cur[s].inset().asInsetMath())
- return cur.popBackward();
- return false;
-}
-
-
////////////////////////////////////////////////////////////////////
MathCompletionList::MathCompletionList(Cursor const & cur)
}
sort(locals.begin(), locals.end());
- if (globals.size() > 0)
+ if (!globals.empty())
return;
// fill in global macros
macros.clear();
- MacroTable::globalMacros().getMacroNames(macros);
+ MacroTable::globalMacros().getMacroNames(macros, false);
//lyxerr << "Globals completion macros: ";
for (it = macros.begin(); it != macros.end(); ++it) {
//lyxerr << "\\" + *it << " ";
globals.push_back(from_ascii("\\framebox"));
globals.push_back(from_ascii("\\makebox"));
globals.push_back(from_ascii("\\kern"));
+ globals.push_back(from_ascii("\\xhookrightarrow"));
+ globals.push_back(from_ascii("\\xhookleftarrow"));
globals.push_back(from_ascii("\\xrightarrow"));
+ globals.push_back(from_ascii("\\xRightarrow"));
+ globals.push_back(from_ascii("\\xrightharpoondown"));
+ globals.push_back(from_ascii("\\xrightharpoonup"));
+ globals.push_back(from_ascii("\\xrightleftharpoons"));
globals.push_back(from_ascii("\\xleftarrow"));
+ globals.push_back(from_ascii("\\xLeftarrow"));
+ globals.push_back(from_ascii("\\xleftharpoondown"));
+ globals.push_back(from_ascii("\\xleftharpoonup"));
+ globals.push_back(from_ascii("\\xleftrightarrow"));
+ globals.push_back(from_ascii("\\xLeftrightarrow"));
+ globals.push_back(from_ascii("\\xleftrightharpoons"));
+ globals.push_back(from_ascii("\\xmapsto"));
globals.push_back(from_ascii("\\split"));
globals.push_back(from_ascii("\\gathered"));
globals.push_back(from_ascii("\\aligned"));
globals.push_back(from_ascii("\\sqrt"));
globals.push_back(from_ascii("\\root"));
globals.push_back(from_ascii("\\tabular"));
+ globals.push_back(from_ascii("\\sideset"));
globals.push_back(from_ascii("\\stackrel"));
+ globals.push_back(from_ascii("\\stackrelthree"));
globals.push_back(from_ascii("\\binom"));
globals.push_back(from_ascii("\\choose"));
globals.push_back(from_ascii("\\brace"));
globals.push_back(from_ascii("\\hphantom"));
globals.push_back(from_ascii("\\phantom"));
globals.push_back(from_ascii("\\vphantom"));
+ globals.push_back(from_ascii("\\cancel"));
+ globals.push_back(from_ascii("\\bcancel"));
+ globals.push_back(from_ascii("\\xcancel"));
+ globals.push_back(from_ascii("\\cancelto"));
+ globals.push_back(from_ascii("\\smash"));
+ globals.push_back(from_ascii("\\mathclap"));
+ globals.push_back(from_ascii("\\mathllap"));
+ globals.push_back(from_ascii("\\mathrlap"));
+ globals.push_back(from_ascii("\\ensuremath"));
MathWordList const & words = mathedWordList();
MathWordList::const_iterator it2;
//lyxerr << "Globals completion commands: ";
for (it2 = words.begin(); it2 != words.end(); ++it2) {
- globals.push_back("\\" + (*it2).first);
- //lyxerr << "\\" + (*it2).first << " ";
+ if (it2->second.inset != "macro" && !it2->second.hidden) {
+ // macros are already read from MacroTable::globalMacros()
+ globals.push_back('\\' + it2->first);
+ //lyxerr << '\\' + it2->first << ' ';
+ }
}
//lyxerr << std::endl;
sort(globals.begin(), globals.end());
cmd = locals[idx];
// get the icon resource name by stripping the backslash
- return "images/math/" + to_utf8(cmd.substr(1)) + ".png";
+ docstring icon_name = frontend::Application::mathIcon(cmd.substr(1));
+ if (icon_name.empty())
+ return std::string();
+ return "images/math/" + to_utf8(icon_name);
}
std::vector<docstring> MathCompletionList::globals;