X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2Fformulabase.C;h=59619935632439fe910783a396e39360e4f95fa0;hb=02b6d38f1adb06a425ca8c334753f0d850359092;hp=7d5f21c3a09256794ef140a2bb1e7bca9bea10b2;hpb=9295f8236e01a5e425d808eb0d2bdd0460d1f423;p=lyx.git diff --git a/src/mathed/formulabase.C b/src/mathed/formulabase.C index 7d5f21c3a0..5961993563 100644 --- a/src/mathed/formulabase.C +++ b/src/mathed/formulabase.C @@ -1,4 +1,4 @@ - /* +/* * File: formulabase.C * Purpose: Implementation of common parts of the LyX math insets * Author: Alejandro Aguilar Sierra @@ -16,6 +16,7 @@ #include #include "Lsstream.h" +#include "support/LAssert.h" #ifdef __GNUG__ #pragma implementation @@ -23,90 +24,115 @@ #include "formula.h" #include "formulamacro.h" +#include "lyxrc.h" #include "commandtags.h" -#include "math_cursor.h" -#include "math_parser.h" #include "BufferView.h" #include "lyxtext.h" #include "lyxfunc.h" #include "gettext.h" #include "LaTeXFeatures.h" #include "debug.h" -#include "support.h" +#include "math_support.h" #include "support/lstrings.h" -#include "LyXView.h" -#include "Painter.h" -#include "font.h" +#include "frontends/LyXView.h" +#include "frontends/font_metrics.h" +#include "frontends/mouse_state.h" +#include "Lsstream.h" #include "math_arrayinset.h" -#include "math_spaceinset.h" -#include "math_macrotable.h" +#include "math_charinset.h" +#include "math_cursor.h" #include "math_factory.h" -#include "support/lyxlib.h" +#include "math_fontinset.h" +#include "math_hullinset.h" +#include "math_iterator.h" +#include "math_macrotable.h" +#include "math_parser.h" +#include "math_pos.h" +#include "math_spaceinset.h" #include "undo_funcs.h" +#include "textpainter.h" +#include "frontends/Dialogs.h" +#include "intl.h" +#include "../insets/insetcommand.h" + +#include "ref_inset.h" using std::endl; using std::ostream; using std::vector; +using std::abs; -extern char const * latex_mathenv[]; -MathCursor * mathcursor = 0; +MathCursor * mathcursor = 0; namespace { - // local global -int sel_x; -int sel_y; -bool sel_flag; +int first_x; +int first_y; -void handleFont(BufferView * bv, MathTextCodes t) -{ - if (mathcursor->selection()) - bv->lockedInsetStoreUndo(Undo::EDIT); - mathcursor->handleFont(t); -} - - -void handleAccent(BufferView * bv, string const & name) -{ - bv->lockedInsetStoreUndo(Undo::EDIT); - mathcursor->insert(createMathInset(name)); -} bool openNewInset(BufferView * bv, UpdatableInset * new_inset) { - LyXText * lt = bv->getLyXText(); - - bv->beforeChange(lt); - finishUndo(); if (!bv->insertInset(new_inset)) { delete new_inset; return false; } - new_inset->edit(bv, 0, 0, 0); + new_inset->edit(bv, 0, 0, mouse_button::none); return true; } -// returns the nearest enclosing grid -MathArrayInset * matrixpar(MathInset::idx_type & idx) -{ - idx = 0; - return (mathcursor ? mathcursor->enclosingArray(idx) : 0); -} - - } // namespace anon InsetFormulaBase::InsetFormulaBase() + : view_(0), font_(), xo_(0), yo_(0) { // This is needed as long the math parser is not re-entrant MathMacroTable::builtinMacros(); //lyxerr << "sizeof MathInset: " << sizeof(MathInset) << "\n"; + //lyxerr << "sizeof(MathMetricsInfo): " << sizeof(MathMetricsInfo) << "\n"; + //lyxerr << "sizeof(MathCharInset): " << sizeof(MathCharInset) << "\n"; + //lyxerr << "sizeof(LyXFont): " << sizeof(LyXFont) << "\n"; +} + + +// simply scrap this function if you want +void InsetFormulaBase::mutateToText() +{ +#if 0 + // translate to latex + ostringstream os; + latex(NULL, os, false, false); + string str = os.str(); + + // insert this text + LyXText * lt = view_->getLyXText(); + string::const_iterator cit = str.begin(); + string::const_iterator end = str.end(); + for (; cit != end; ++cit) + view_->owner()->getIntl()->getTransManager().TranslateAndInsert(*cit, lt); + + // remove ourselves + //view_->owner()->getLyXFunc()->dispatch(LFUN_ESCAPE); +#endif +} + + +void InsetFormulaBase::handleFont + (BufferView * bv, string const & arg, string const & font) +{ + bv->lockedInsetStoreUndo(Undo::EDIT); + bool sel = mathcursor->selection(); + if (sel) + updateLocal(bv, true); + mathcursor->handleNest(new MathFontInset(font)); + mathcursor->insert(arg); + if (!sel) + updateLocal(bv, false); } @@ -115,32 +141,56 @@ void InsetFormulaBase::validate(LaTeXFeatures &) const {} +void InsetFormulaBase::metrics(BufferView * bv, LyXFont const & f) const +{ + font_ = f; + metrics(bv); +} + + +void InsetFormulaBase::metrics(BufferView * bv) const +{ + if (bv) + view_ = bv; + MathMetricsInfo mi; + mi.view = view_; + mi.base.style = display() ? LM_ST_DISPLAY : LM_ST_TEXT; + mi.base.font = font_; + mi.base.font.setColor(LColor::math); + par()->metrics(mi); +} + + string const InsetFormulaBase::editMessage() const { return _("Math editor mode"); } -void InsetFormulaBase::edit(BufferView * bv, int x, int /*y*/, unsigned int) +void InsetFormulaBase::edit(BufferView * bv, int x, int y, mouse_button::state) { if (!bv->lockInset(this)) lyxerr[Debug::MATHED] << "Cannot lock inset!!!" << endl; + delete mathcursor; + mathcursor = new MathCursor(this, true); + metrics(bv); + mathcursor->setPos(x, y); + //lyxerr << "setting pos to " << x << "," << y << "\n"; - mathcursor = new MathCursor(this, x == 0); - metrics(); // if that is removed, we won't get the magenta box when entering an // inset for the first time bv->updateInset(this, false); - sel_x = 0; - sel_y = 0; - sel_flag = false; } void InsetFormulaBase::edit(BufferView * bv, bool front) { - // looks hackish but seems to work - edit(bv, front ? 0 : 1, 0, 0); + if (!bv->lockInset(this)) + lyxerr[Debug::MATHED] << "Cannot lock inset!!!" << endl; + delete mathcursor; + mathcursor = new MathCursor(this, front); + metrics(bv); + bv->updateInset(this, false); } @@ -158,12 +208,13 @@ void InsetFormulaBase::insetUnlock(BufferView * bv) } -void InsetFormulaBase::getCursorPos(BufferView *, int & x, int & y) const +void InsetFormulaBase::getCursorPos(BufferView * bv, int & x, int & y) const { + metrics(bv); mathcursor->getPos(x, y); - x -= par()->xo(); - y -= par()->yo(); - y -= 3; + //x -= xo_; + y -= yo_; + //lyxerr << "getCursorPos: " << x << " " << y << "\n"; } @@ -175,16 +226,16 @@ void InsetFormulaBase::toggleInsetCursor(BufferView * bv) if (isCursorVisible()) bv->hideLockedInsetCursor(); else { + metrics(bv); int x; int y; mathcursor->getPos(x, y); - //x -= par()->xo(); - y -= par()->yo(); - y -= 3; - int asc; - int des; - math_font_max_dim(LM_TC_TEXTRM, LM_ST_TEXT, asc, des); + y -= yo_; + int asc = 0; + int des = 0; + math_font_max_dim(font_, asc, des); bv->showLockedInsetCursor(x, y, asc, des); + //lyxerr << "toggleInsetCursor: " << x << " " << y << "\n"; } toggleCursorVisible(); @@ -193,20 +244,21 @@ void InsetFormulaBase::toggleInsetCursor(BufferView * bv) void InsetFormulaBase::showInsetCursor(BufferView * bv, bool) { - if (!isCursorVisible()) { - if (mathcursor) { - int x; - int y; - mathcursor->getPos(x, y); - x -= par()->xo(); - y -= par()->yo(); - int asc; - int des; - math_font_max_dim(LM_TC_TEXTRM, LM_ST_TEXT, asc, des); - bv->fitLockedInsetCursor(x, y, asc, des); - } - toggleInsetCursor(bv); + if (isCursorVisible()) + return; + if (mathcursor) { + metrics(bv); + int x; + int y; + mathcursor->getPos(x, y); + y -= yo_; + int asc = 0; + int des = 0; + math_font_max_dim(font_, asc, des); + bv->fitLockedInsetCursor(x, y, asc, des); + //lyxerr << "showInsetCursor: x: " << x << " y: " << y << " yo: " << yo_ << "\n"; } + toggleInsetCursor(bv); } @@ -217,6 +269,20 @@ void InsetFormulaBase::hideInsetCursor(BufferView * bv) } +void InsetFormulaBase::fitInsetCursor(BufferView * bv) const +{ + if (!mathcursor) + return; + + int const asc = font_metrics::maxAscent(font_); + int const desc = font_metrics::maxDescent(font_); + int x, y; + + getCursorPos(bv, x, y); + bv->fitLockedInsetCursor(x, y, asc, desc); +} + + void InsetFormulaBase::toggleInsetSelection(BufferView * bv) { if (mathcursor) @@ -226,77 +292,126 @@ void InsetFormulaBase::toggleInsetSelection(BufferView * bv) vector const InsetFormulaBase::getLabelList() const { - return std::vector(); + return vector(); } void InsetFormulaBase::updateLocal(BufferView * bv, bool dirty) { - metrics(); + metrics(bv); + if (mathcursor) + bv->fitCursor(); bv->updateInset(this, dirty); } -void InsetFormulaBase::insetButtonRelease(BufferView * bv, - int x, int y, int /*button*/) +bool InsetFormulaBase::insetButtonRelease(BufferView * bv, + int /*x*/, int /*y*/, mouse_button::state button) { - if (mathcursor) { - hideInsetCursor(bv); - x += par()->xo(); - y += par()->yo(); - mathcursor->setPos(x, y); - showInsetCursor(bv); - if (sel_flag) { - sel_flag = false; - sel_x = 0; - sel_y = 0; - } - bv->updateInset(this, false); + //lyxerr << "insetButtonRelease: " << x << " " << y << "\n"; + + if (!mathcursor) + return false; + hideInsetCursor(bv); + showInsetCursor(bv); + bv->updateInset(this, false); + + if (button == mouse_button::button3) { + // try to dispatch to enclosed insets first + if (mathcursor->dispatch("mouse 3")) + return true; + + // launch math panel for right mouse button + bv->owner()->getDialogs()->showMathPanel(); + return true; } + return false; } void InsetFormulaBase::insetButtonPress(BufferView * bv, - int x, int y, int /*button*/) + int x, int y, mouse_button::state button) { - sel_flag = false; - sel_x = x; - sel_y = y; - if (mathcursor && mathcursor->selection()) { + //lyxerr << "insetButtonPress: " + // << x << " " << y << " but: " << button << "\n"; +#if 0 + switch (button) { + default: + case 1: + // left click + delete mathcursor; + mathcursor = new MathCursor(this, x == 0); + metrics(bv); + first_x = x; + first_y = y; + mathcursor->selClear(); + mathcursor->setPos(x + xo_, y + yo_); + break; +/* + case 2: + lyxerr << "insetButtonPress: 2\n"; + // insert stuff + if (mathcursor) { + bv->lockedInsetStoreUndo(Undo::EDIT); + MathArray ar; + mathcursor->selGet(ar); + mathcursor->setPos(x + xo_, y + yo_); + string sel = + bv->getLyXText()->selectionAsString(bv->buffer(), false); + mathed_parse_cell(ar, sel); + mathcursor->insert(ar); + } + break; +*/ + case 3: + // launch math panel for right mouse button + bv->owner()->getDialogs()->showMathPanel(); + break; + } +#else + if (button == mouse_button::button1 || !mathcursor) { + delete mathcursor; + mathcursor = new MathCursor(this, x == 0); + metrics(bv); + first_x = x; + first_y = y; mathcursor->selClear(); - bv->updateInset(this, false); + mathcursor->setPos(x + xo_, y + yo_); + } +#if 0 +#warning Never launch a Dialog on "Press" event ONLY on "Release" event! + if (button == 3) { + // launch math panel for right mouse button + bv->owner()->getDialogs()->showMathPanel(); } +#endif +#endif + bv->updateInset(this, false); } void InsetFormulaBase::insetMotionNotify(BufferView * bv, - int x, int y, int /*button*/) + int x, int y, mouse_button::state) { - if (sel_x && sel_y && abs(x-sel_x) > 4 && !sel_flag) { - sel_flag = true; - hideInsetCursor(bv); - mathcursor->setPos(sel_x + par()->xo(), sel_y + par()->yo()); - mathcursor->selStart(); - showInsetCursor(bv); - mathcursor->getPos(sel_x, sel_y); - } else if (sel_flag) { - hideInsetCursor(bv); - x += par()->xo(); - y += par()->yo(); - mathcursor->setPos(x, y); - showInsetCursor(bv); - mathcursor->getPos(x, y); - if (sel_x != x || sel_y != y) - bv->updateInset(this, false); - sel_x = x; - sel_y = y; + if (!mathcursor) + return; + + if (abs(x - first_x) < 2 && abs(y - first_y) < 2) { + //lyxerr << "insetMotionNotify: ignored\n"; + return; } -} + first_x = x; + first_y = y; + if (!mathcursor->selection()) + mathcursor->selStart(); -void InsetFormulaBase::insetKeyPress(XKeyEvent *) -{ - lyxerr[Debug::MATHED] << "Used InsetFormulaBase::InsetKeyPress." << endl; + //lyxerr << "insetMotionNotify: " << x + xo_ << ' ' << y + yo_ + // << ' ' << button << "\n"; + hideInsetCursor(bv); + mathcursor->setPos(x + xo_, y + yo_); + showInsetCursor(bv); + bv->updateInset(this, false); } @@ -307,7 +422,7 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action, //lyxerr << "InsetFormulaBase::localDispatch: act: " << action // << " arg: '" << arg << "' cursor: " << mathcursor << "\n"; - if (!mathcursor) + if (!mathcursor) return UNDISPATCHED; RESULT result = DISPATCHED; @@ -318,17 +433,22 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action, hideInsetCursor(bv); mathcursor->normalize(); + mathcursor->touch(); switch (action) { - // --- Cursor Movements --------------------------------------------- + // --- Cursor Movements --------------------------------------------- case LFUN_RIGHTSEL: sel = true; // fall through... case LFUN_RIGHT: result = mathcursor->right(sel) ? DISPATCHED : FINISHED_RIGHT; + //lyxerr << "calling scroll 20\n"; + //scroll(bv, 20); updateLocal(bv, false); + // write something to the minibuffer + //bv->owner()->message(mathcursor->info()); break; @@ -396,32 +516,31 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action, updateLocal(bv, true); break; + case LFUN_DELETE_WORD_BACKWARD: case LFUN_BACKSPACE: bv->lockedInsetStoreUndo(Undo::DELETE); mathcursor->backspace(); - bv->updateInset(this, true); + updateLocal(bv, true); break; + case LFUN_DELETE_WORD_FORWARD: case LFUN_DELETE: bv->lockedInsetStoreUndo(Undo::DELETE); mathcursor->erase(); bv->updateInset(this, true); break; - // case LFUN_GETXY: - // sprintf(dispatch_buffer, "%d %d",); - // dispatch_result = dispatch_buffer; - // break; + // case LFUN_GETXY: + // sprintf(dispatch_buffer, "%d %d",); + // dispatch_result = dispatch_buffer; + // break; case LFUN_SETXY: { lyxerr << "LFUN_SETXY broken!\n"; - int x; - int y; - int x1; - int y1; + int x = 0; + int y = 0; istringstream is(arg.c_str()); is >> x >> y; - par()->getXY(x1, y1); - mathcursor->setPos(x1 + x, y1 + y); + mathcursor->setPos(x, y); updateLocal(bv, false); break; } @@ -429,7 +548,7 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action, case LFUN_PASTE: if (was_macro) mathcursor->macroModeClose(); - bv->lockedInsetStoreUndo(Undo::INSERT); + bv->lockedInsetStoreUndo(Undo::EDIT); mathcursor->selPaste(); updateLocal(bv, true); break; @@ -448,88 +567,106 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action, case LFUN_WORDLEFTSEL: break; - // --- accented characters ------------------------------ - - case LFUN_UMLAUT: handleAccent(bv, "ddot"); break; - case LFUN_CIRCUMFLEX: handleAccent(bv, "hat"); break; - case LFUN_GRAVE: handleAccent(bv, "grave"); break; - case LFUN_ACUTE: handleAccent(bv, "acute"); break; - case LFUN_TILDE: handleAccent(bv, "tilde"); break; - case LFUN_MACRON: handleAccent(bv, "bar"); break; - case LFUN_DOT: handleAccent(bv, "dot"); break; - case LFUN_CARON: handleAccent(bv, "check"); break; - case LFUN_BREVE: handleAccent(bv, "breve"); break; - case LFUN_VECTOR: handleAccent(bv, "vec"); break; + // Special casing for superscript in case of LyX handling + // dead-keys: + case LFUN_CIRCUMFLEX: + if (arg.empty()) { + // do superscript if LyX handles + // deadkeys + bv->lockedInsetStoreUndo(Undo::EDIT); + mathcursor->script(true); + updateLocal(bv, true); + } + break; + case LFUN_UMLAUT: + case LFUN_ACUTE: + case LFUN_GRAVE: + case LFUN_BREVE: + case LFUN_DOT: + case LFUN_MACRON: + case LFUN_CARON: + case LFUN_TILDE: + case LFUN_CEDILLA: + case LFUN_CIRCLE: + case LFUN_UNDERDOT: + case LFUN_TIE: + case LFUN_OGONEK: + case LFUN_HUNG_UMLAUT: + break; // Math fonts - case LFUN_GREEK_TOGGLE: handleFont(bv, LM_TC_GREEK); break; - case LFUN_BOLD: handleFont(bv, LM_TC_BF); break; - case LFUN_SANS: handleFont(bv, LM_TC_SF); break; - case LFUN_EMPH: handleFont(bv, LM_TC_CAL); break; - case LFUN_ROMAN: handleFont(bv, LM_TC_RM); break; - case LFUN_CODE: handleFont(bv, LM_TC_TT); break; - case LFUN_NOUN: handleFont(bv, LM_TC_BB); break; - case LFUN_DEFAULT: handleFont(bv, LM_TC_VAR); break; - - case LFUN_GREEK: - handleFont(bv, LM_TC_GREEK1); + case LFUN_GREEK_TOGGLE: handleFont(bv, arg, "lyxgreek"); break; + case LFUN_BOLD: handleFont(bv, arg, "textbf"); break; + case LFUN_SANS: handleFont(bv, arg, "textsf"); break; + case LFUN_EMPH: handleFont(bv, arg, "mathcal"); break; + case LFUN_ROMAN: handleFont(bv, arg, "mathrm"); break; + case LFUN_CODE: handleFont(bv, arg, "texttt"); break; + case LFUN_FRAK: handleFont(bv, arg, "mathfrak"); break; + case LFUN_ITAL: handleFont(bv, arg, "mathit"); break; + case LFUN_NOUN: handleFont(bv, arg, "mathbb"); break; + case LFUN_DEFAULT: handleFont(bv, arg, "textnormal"); break; + case LFUN_FREE: handleFont(bv, arg, "textrm"); break; + + case LFUN_GREEK: + handleFont(bv, arg, "lyxgreek1"); if (arg.size()) - mathcursor->interpret(arg[0]); + mathcursor->interpret(arg); break; case LFUN_MATH_MODE: - handleFont(bv, LM_TC_TEXTRM); + if (mathcursor->inMathMode()) { + handleFont(bv, arg, "textrm"); + } else { + mathcursor->niceInsert(MathAtom(new MathHullInset(LM_OT_SIMPLE))); + updateLocal(bv, true); + } //bv->owner()->message(_("math text mode toggled")); break; case LFUN_MATH_LIMITS: - bv->lockedInsetStoreUndo(Undo::INSERT); + bv->lockedInsetStoreUndo(Undo::EDIT); if (mathcursor->toggleLimits()) updateLocal(bv, true); break; case LFUN_MATH_SIZE: +#if 0 if (!arg.empty()) { - bv->lockedInsetStoreUndo(Undo::INSERT); - latexkeys const * l = in_word_set(arg); - mathcursor->setSize(MathStyles(l ? l->id : static_cast(-1))); + bv->lockedInsetStoreUndo(Undo::EDIT); + mathcursor->setSize(arg); updateLocal(bv, true); } +#endif break; case LFUN_INSERT_MATRIX: if (!arg.empty()) { - bv->lockedInsetStoreUndo(Undo::INSERT); + bv->lockedInsetStoreUndo(Undo::EDIT); mathcursor->interpret("matrix " + arg); updateLocal(bv, true); } break; - case LFUN_MATH_SPACE: + case LFUN_SUPERSCRIPT: + case LFUN_SUBSCRIPT: { bv->lockedInsetStoreUndo(Undo::EDIT); - //MathSpaceInset * p = mathcursor->prevSpaceInset(); - //if (p) - // p->incSpace(); - //else - // mathcursor->insert(new MathSpaceInset(1)); - mathcursor->insert(MathAtom(new MathSpaceInset(1))); + mathcursor->script(action == LFUN_SUPERSCRIPT); updateLocal(bv, true); break; } case LFUN_MATH_DELIM: { - bv->lockedInsetStoreUndo(Undo::INSERT); //lyxerr << "formulabase::LFUN_MATH_DELIM, arg: '" << arg << "'\n"; string ls; - string rs; - istringstream is(arg.c_str()); - is >> ls >> rs; - if (!is) { - lyxerr << "can't parse delimeters from '" << arg << "'\n"; - break; - } + string rs = split(arg, ls, ' '); + // Reasonable default values + if (ls.empty()) + ls = '('; + if (rs.empty()) + rs = ')'; + bv->lockedInsetStoreUndo(Undo::EDIT); mathcursor->handleDelim(ls, rs); updateLocal(bv, true); @@ -537,9 +674,9 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action, } case LFUN_PROTECTEDSPACE: - //lyxerr << " called LFUN_PROTECTEDSPACE\n"; - bv->lockedInsetStoreUndo(Undo::INSERT); - mathcursor->insert(MathAtom(new MathSpaceInset(1))); + case LFUN_MATH_SPACE: + bv->lockedInsetStoreUndo(Undo::EDIT); + mathcursor->insert(MathAtom(new MathSpaceInset(","))); updateLocal(bv, true); break; @@ -549,78 +686,29 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action, case LFUN_MATH_HALIGN: - { - bv->lockedInsetStoreUndo(Undo::INSERT); - lyxerr << "handling halign '" << arg << "'\n"; - MathInset::idx_type idx; - MathArrayInset * p = matrixpar(idx); - if (!p) - break; - p->halign(arg.size() ? arg[0] : 'c', p->col(idx)); - updateLocal(bv, true); - break; - } - case LFUN_MATH_VALIGN: - { - bv->lockedInsetStoreUndo(Undo::INSERT); - lyxerr << "handling valign '" << arg << "'\n"; - MathInset::idx_type idx; - MathArrayInset * p = matrixpar(idx); - if (!p) - break; - p->valign(arg.size() ? arg[0] : 'c'); - updateLocal(bv, true); - break; - } - case LFUN_MATH_ROW_INSERT: - { - bv->lockedInsetStoreUndo(Undo::INSERT); - MathInset::idx_type idx; - MathArrayInset * p = matrixpar(idx); - lyxerr << " calling LFUN_MATH_ROW_INSERT on " << p << endl; - if (!p) - break; - p->addRow(p->row(idx)); - updateLocal(bv, true); - break; - } - case LFUN_MATH_ROW_DELETE: - { - bv->lockedInsetStoreUndo(Undo::INSERT); - MathInset::idx_type idx; - MathArrayInset * p = matrixpar(idx); - lyxerr << " calling LFUN_MATH_ROW_DELETE on " << p << endl; - if (!p) - break; - p->delRow(p->row(idx)); - updateLocal(bv, true); - break; - } - case LFUN_MATH_COLUMN_INSERT: - { - bv->lockedInsetStoreUndo(Undo::INSERT); - MathInset::idx_type idx; - MathArrayInset * p = matrixpar(idx); - if (!p) - break; - p->addCol(p->col(idx)); - updateLocal(bv, true); - break; - } - case LFUN_MATH_COLUMN_DELETE: { - bv->lockedInsetStoreUndo(Undo::INSERT); - MathInset::idx_type idx; - MathArrayInset * p = matrixpar(idx); - if (!p) - break; - p->delCol(p->col(idx)); - updateLocal(bv, true); + MathInset::idx_type idx = 0; + MathGridInset * p = mathcursor ? mathcursor->enclosingGrid(idx) : 0; + if (p) { + mathcursor->popToEnclosingGrid(); + bv->lockedInsetStoreUndo(Undo::EDIT); + char align = arg.size() ? arg[0] : 'c'; + switch (action) { + case LFUN_MATH_HALIGN: p->halign(align, p->col(idx)); break; + case LFUN_MATH_VALIGN: p->valign(align); break; + case LFUN_MATH_ROW_INSERT: p->addRow(p->row(idx)); break; + case LFUN_MATH_ROW_DELETE: p->delRow(p->row(idx)); break; + case LFUN_MATH_COLUMN_INSERT: p->addFancyCol(p->col(idx)); break; + case LFUN_MATH_COLUMN_DELETE: p->delFancyCol(p->col(idx)); break; + default: ; + } + updateLocal(bv, true); + } break; } @@ -628,12 +716,27 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action, result = UNDISPATCHED; break; + case LFUN_BREAKPARAGRAPH: + case LFUN_BREAKPARAGRAPHKEEPLAYOUT: + //lyxerr << "LFUN ignored\n"; + break; + + case LFUN_INSET_ERT: + // interpret this as if a backslash was typed + bv->lockedInsetStoreUndo(Undo::EDIT); + mathcursor->interpret('\\'); + updateLocal(bv, true); + break; + case -1: case LFUN_INSERT_MATH: case LFUN_SELFINSERT: if (!arg.empty()) { - bv->lockedInsetStoreUndo(Undo::INSERT); - mathcursor->interpret(arg); + bv->lockedInsetStoreUndo(Undo::EDIT); + if (arg.size() == 1) + result = mathcursor->interpret(arg[0]) ? DISPATCHED : FINISHED_RIGHT; + else + result = mathcursor->interpret(arg) ? DISPATCHED : FINISHED_RIGHT; updateLocal(bv, true); } break; @@ -642,16 +745,53 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action, result = UNDISPATCHED; break; + case LFUN_ESCAPE: + if (mathcursor->selection()) + mathcursor->selClear(); + else + result = UNDISPATCHED; + break; + + case LFUN_INSET_TOGGLE: + mathcursor->insetToggle(); + updateLocal(bv, true); + break; + + case LFUN_REF_INSERT: + //if (argument.empty()) { + // InsetCommandParams p("ref"); + // owner_->getDialogs()->createRef(p.getAsString()); + //} else { + // InsetCommandParams p; + // p.setFromString(argument); + + // InsetRef * inset = new InsetRef(p, *buffer_); + // if (!insertInset(inset)) + // delete inset; + // else + // updateInset(inset, true); + //} + // + if (arg.empty()) { + InsetCommandParams p("ref"); + bv->owner()->getDialogs()->createRef(p.getAsString()); + } else { + //mathcursor->handleNest(new RefInset); + //mathcursor->insert(arg); + mathcursor->insert(MathAtom(new RefInset(arg))); + } + updateLocal(bv, true); + break; + default: result = UNDISPATCHED; } - //mathcursor->normalize(); + mathcursor->normalize(); + mathcursor->touch(); + + lyx::Assert(mathcursor); - if (was_macro != mathcursor->inMacroMode() - && action >= 0 && action != LFUN_BACKSPACE) - updateLocal(bv, true); - if (mathcursor->selection() || was_selection) toggleInsetSelection(bv); @@ -661,16 +801,138 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action, else bv->unlockInset(this); + revealCodes(bv); + return result; // original version } +void InsetFormulaBase::revealCodes(BufferView * bv) const +{ + if (!mathcursor) + return; + bv->owner()->message(mathcursor->info()); + +#if 0 + // write something to the minibuffer + // translate to latex + mathcursor->markInsert(); + ostringstream os; + write(NULL, os); + string str = os.str(); + mathcursor->markErase(); + string::size_type pos = 0; + string res; + for (string::iterator it = str.begin(); it != str.end(); ++it) { + if (*it == '\n') + res += ' '; + else if (*it == '\0') { + res += " -X- "; + pos = it - str.begin(); + } + else + res += *it; + } + if (pos > 30) + res = res.substr(pos - 30); + if (res.size() > 60) + res = res.substr(0, 60); + bv->owner()->message(res); +#endif +} + + Inset::Code InsetFormulaBase::lyxCode() const { return Inset::MATH_CODE; } +int InsetFormulaBase::ylow() const +{ + return yo_ - ascent(view_, font_); +} + + +int InsetFormulaBase::yhigh() const +{ + return yo_ + descent(view_, font_); +} + + +int InsetFormulaBase::xlow() const +{ + return xo_; +} + + +int InsetFormulaBase::xhigh() const +{ + return xo_ + width(view_, font_); +} + + +///////////////////////////////////////////////////////////////////// + + +bool InsetFormulaBase::searchForward(BufferView * bv, string const & str, + bool, bool) +{ +#ifdef WITH_WARNINGS +#warning pretty ugly +#endif + static InsetFormulaBase * lastformula = 0; + static MathIterator current = MathIterator(ibegin(par().nucleus())); + static MathArray ar; + static string laststr; + + if (lastformula != this || laststr != str) { + //lyxerr << "reset lastformula to " << this << "\n"; + lastformula = this; + laststr = str; + current = ibegin(par().nucleus()); + ar.clear(); + mathed_parse_cell(ar, str); + } else { + ++current; + } + //lyxerr << "searching '" << str << "' in " << this << ar << endl; + + for (MathIterator it = current; it != iend(par().nucleus()); ++it) { + if (it.cell().matchpart(ar, it.position().pos_)) { + bv->unlockInset(bv->theLockingInset()); + if (!bv->lockInset(this)) { + lyxerr << "Cannot lock inset" << endl; + return false; + } + delete mathcursor; + mathcursor = new MathCursor(this, true); + metrics(bv); + mathcursor->setSelection(it.cursor(), ar.size()); + current = it; + it.jump(ar.size()); + updateLocal(bv, false); + return true; + } + } + + //lyxerr << "not found!\n"; + lastformula = 0; + return false; +} + + +bool InsetFormulaBase::searchBackward(BufferView * bv, string const & what, + bool a, bool b) +{ + lyxerr << "searching backward not implemented in mathed" << endl; + return searchForward(bv, what, a, b); +} + + +///////////////////////////////////////////////////////////////////// + + void mathDispatchCreation(BufferView * bv, string const & arg, bool display) { if (bv->available()) { @@ -680,12 +942,11 @@ void mathDispatchCreation(BufferView * bv, string const & arg, bool display) // sel = ""; //else - string sel = bv->getLyXText()->selectionAsString(bv->buffer(), - false); + string sel = bv->getLyXText()->selectionAsString(bv->buffer(), false); InsetFormulaBase * f; if (sel.empty()) { - f = new InsetFormula; + f = new InsetFormula(LM_OT_SIMPLE); if (openNewInset(bv, f)) { // don't do that also for LFUN_MATH_MODE unless you want end up with // always changing to mathrm when opening an inlined inset @@ -697,10 +958,16 @@ void mathDispatchCreation(BufferView * bv, string const & arg, bool display) } else { // create a macro if we see "\\newcommand" somewhere, and an ordinary // formula otherwise - if (sel.find("\\newcommand") == string::npos) + if (sel.find("\\newcommand") == string::npos && + sel.find("\\def") == string::npos) + { f = new InsetFormula(sel); - else + } else { + string name; + if (!mathed_parse_macro(name, sel)) + return; f = new InsetFormulaMacro(sel); + } bv->getLyXText()->cutSelection(bv); openNewInset(bv, f); } @@ -714,7 +981,7 @@ void mathDispatchMathDisplay(BufferView * bv, string const & arg) mathDispatchCreation(bv, arg, true); } - + void mathDispatchMathMode(BufferView * bv, string const & arg) { mathDispatchCreation(bv, arg, false); @@ -733,7 +1000,7 @@ void mathDispatchMathMacro(BufferView * bv, string const & arg) if (arg.empty()) bv->owner()->getLyXFunc()->setErrorMessage(N_("Missing argument")); else { - string s(arg); + string s = arg; string const s1 = token(s, ' ', 1); int const na = s1.empty() ? 0 : lyx::atoi(s1); openNewInset(bv, new InsetFormulaMacro(token(s, ' ', 0), na)); @@ -743,42 +1010,54 @@ void mathDispatchMathMacro(BufferView * bv, string const & arg) void mathDispatchMathDelim(BufferView * bv, string const & arg) -{ - if (bv->available()) { - if (openNewInset(bv, new InsetFormula)) +{ + if (bv->available()) { + if (openNewInset(bv, new InsetFormula(LM_OT_SIMPLE))) bv->theLockingInset()->localDispatch(bv, LFUN_MATH_DELIM, arg); } -} +} void mathDispatchInsertMatrix(BufferView * bv, string const & arg) -{ - if (bv->available()) { - if (openNewInset(bv, new InsetFormula)) +{ + if (bv->available()) { + if (openNewInset(bv, new InsetFormula(LM_OT_SIMPLE))) bv->theLockingInset()->localDispatch(bv, LFUN_INSERT_MATRIX, arg); } -} +} void mathDispatchInsertMath(BufferView * bv, string const & arg) { if (bv->available()) { - if (arg.size() && arg[0] == '\\') - openNewInset(bv, new InsetFormula(arg)); - else + if (arg.size() && arg[0] == '\\') { + InsetFormula * f = new InsetFormula(arg); + if (!bv->insertInset(f)) + delete f; + else if (!mathcursor) // hotfix + bv->getLyXText()->cursorRight(bv); + } else { mathDispatchMathMode(bv, arg); + } } } void mathDispatchGreek(BufferView * bv, string const & arg) -{ - if (bv->available()) { - InsetFormula * f = new InsetFormula; +{ + if (bv->available()) { + InsetFormula * f = new InsetFormula(LM_OT_SIMPLE); if (openNewInset(bv, f)) { bv->theLockingInset()->localDispatch(bv, LFUN_GREEK, arg); bv->unlockInset(f); } } -} +} + +void mathDispatch(BufferView *, kb_action, string const &) +{} + + +void mathDispatch(BufferView *, string const &) +{}