#include "Bidi.h"
#include "Buffer.h"
+#include "BufferParams.h"
#include "BufferView.h"
#include "CoordCache.h"
#include "Cursor.h"
#include "OutputParams.h"
#include "Text.h"
+#include "frontends/Application.h"
#include "frontends/Clipboard.h"
#include "frontends/Painter.h"
#include "frontends/Selection.h"
// 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)) {
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();
runparams.encoding);
wi.canBreakLine(os.canBreakLine());
write(wi);
+ // Reset parbreak status after a math inset.
+ os.lastChar(0);
os.canBreakLine(wi.canBreakLine());
int lf = wi.line();
replaceSelection(cur);
docstring topaste;
if (cmd.argument().empty() && !theClipboard().isInternal())
- topaste = theClipboard().getAsText();
+ topaste = theClipboard().getAsText(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
act == LFUN_UP_SELECT;
cur.selHandle(select);
+ // handle autocorrect:
+ cur.autocorrect() = false;
+ cur.message(_("Autocorrect Off ('!' to enter)"));
+
// go up/down
bool up = act == LFUN_UP || act == LFUN_UP_SELECT;
bool successful = cur.upDownInMath(up);
cur.idx() = 0;
cur.resetAnchor();
cur.setSelection(true);
- cur.pos() = cur.lastpos();
cur.idx() = cur.lastidx();
+ cur.pos() = cur.lastpos();
+ cur.bv().cursor() = cur;
break;
case LFUN_PARAGRAPH_UP:
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()) {
// 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();
cur.macroModeClose();
docstring const save_selection = grabAndEraseSelection(cur);
selClearOrDel(cur);
- //cur.plainInsert(MathAtom(new InsetMathMBox(cur.bv())));
if (currentMode() <= Inset::TEXT_MODE)
cur.plainInsert(MathAtom(new InsetMathEnsureMath(buffer_)));
else
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();
if (createInsetMath_fromDialogStr(cmd.argument(), ar)) {
cur.recordUndoSelection();
cur.insert(ar);
- cur.forceBufferUpdate();
+ cur.forceBufferUpdate();
} else
cur.undispatched();
break;
// 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_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;
// 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;
}
+
+ 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();
}
}
// 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));
cur.backspace();
cur.niceInsert(MathAtom(new InsetMathComment(buf)));
} 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)"));
//lyxerr << "starting with macro" << endl;
bool reduced = cap::reduceSelectionToOneCell(cur);
if (reduced || !cur.selection()) {
+ cur.recordUndoInset();
docstring const safe = cap::grabAndEraseSelection(cur);
if (!cur.inRegexped())
cur.insert(MathAtom(new InsetMathUnknown(from_ascii("\\"), safe, false)));
// 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("backslash", buf));
+ break;
+ 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;
}
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("\\root"));
globals.push_back(from_ascii("\\tabular"));
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"));
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;