X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2FMathMacroTemplate.cpp;h=2989e2be5ce01ba25c5aab5ccabdf091308552d4;hb=981e958b9d63930c83b1adced65b75b3d857ac97;hp=257c55f639e867657a73fefb49e56a1a2a14ea2d;hpb=ff4460603e3888948b46f0ab5bfa69a862d538ad;p=lyx.git diff --git a/src/mathed/MathMacroTemplate.cpp b/src/mathed/MathMacroTemplate.cpp index 257c55f639..2989e2be5c 100644 --- a/src/mathed/MathMacroTemplate.cpp +++ b/src/mathed/MathMacroTemplate.cpp @@ -17,6 +17,7 @@ #include "LaTeXFeatures.h" #include "InsetMathBrace.h" #include "InsetMathChar.h" +#include "InsetMathHull.h" #include "InsetMathSqrt.h" #include "MathMacro.h" #include "MathMacroArgument.h" @@ -33,10 +34,12 @@ #include "FuncRequest.h" #include "FuncStatus.h" #include "Lexer.h" -#include "Undo.h" +#include "LyXRC.h" #include "frontends/Painter.h" +#include "insets/RenderPreview.h" + #include "support/lassert.h" #include "support/convert.h" #include "support/debug.h" @@ -44,6 +47,7 @@ #include "support/docstream.h" #include "support/lstrings.h" +#include #include using namespace std; @@ -588,6 +592,7 @@ void MathMacroTemplate::metrics(MetricsInfo & mi, Dimension & dim) const void MathMacroTemplate::draw(PainterInfo & pi, int x, int y) const { + ColorChanger dummy0(pi.base.font, Color_math); FontSetChanger dummy1(pi.base, from_ascii("mathnormal")); StyleChanger dummy2(pi.base, LM_ST_TEXT); @@ -612,29 +617,25 @@ void MathMacroTemplate::draw(PainterInfo & pi, int x, int y) const void MathMacroTemplate::edit(Cursor & cur, bool front, EntryDirection entry_from) { updateLook(); - cur.updateFlags(Update::SinglePar); + cur.screenUpdateFlags(Update::SinglePar); InsetMathNest::edit(cur, front, entry_from); } bool MathMacroTemplate::notifyCursorLeaves(Cursor const & old, Cursor & cur) { - // find this in cursor old - Cursor insetCur = old; - int scriptSlice = insetCur.find(this); - LASSERT(scriptSlice != -1, /**/); - insetCur.cutOff(scriptSlice); - - commitEditChanges(insetCur); + commitEditChanges(cur, old); updateLook(); - cur.updateFlags(Update::Force); + cur.screenUpdateFlags(Update::Force); return InsetMathNest::notifyCursorLeaves(old, cur); } -void MathMacroTemplate::removeArguments(Cursor & cur, int from, int to) +void MathMacroTemplate::removeArguments(Cursor & cur, + DocIterator const & /*inset_pos*/, int from, int to) { - for (DocIterator it = doc_iterator_begin(&buffer(), this); it; it.forwardChar()) { + DocIterator it = doc_iterator_begin(&buffer(), this); + for (; it; it.forwardChar()) { if (!it.nextInset()) continue; if (it.nextInset()->lyxCode() != MATH_MACROARG_CODE) @@ -673,7 +674,7 @@ void MathMacroTemplate::shiftArguments(size_t from, int by) int MathMacroTemplate::maxArgumentInDefinition() const { // We don't have a buffer when pasting from the clipboard (bug 6014). - Buffer const * macro_buffer = this->isBufferValid() ? &buffer() : 0; + Buffer const * macro_buffer = isBufferLoaded() ? &buffer() : 0; int maxArg = 0; DocIterator it = doc_iterator_begin(macro_buffer, this); it.idx() = defIdx(); @@ -716,68 +717,97 @@ void MathMacroTemplate::insertMissingArguments(int maxArg) } -void MathMacroTemplate::changeArity(Cursor & cur, int newNumArg) +void MathMacroTemplate::changeArity(Cursor & cur, + DocIterator const & inset_pos, int newNumArg) { // remove parameter which do not appear anymore in the definition for (int i = numargs_; i > newNumArg; --i) - removeParameter(cur, numargs_ - 1, false); + removeParameter(cur, inset_pos, numargs_ - 1, true); // add missing parameter for (int i = numargs_; i < newNumArg; ++i) - insertParameter(cur, numargs_, false, false); + insertParameter(cur, inset_pos, numargs_, true, false); } -void MathMacroTemplate::commitEditChanges(Cursor & cur) +/// +class AddRemoveMacroInstanceFix { - int argsInDef = maxArgumentInDefinition(); - if (argsInDef != numargs_) { - cur.recordUndoFullDocument(); - changeArity(cur, argsInDef); +public: + /// + AddRemoveMacroInstanceFix(int n, bool insert) : n_(n), insert_(insert) {} + /// + void operator()(MathMacro * macro) + { + if (macro->folded()) { + if (insert_) + macro->insertArgument(n_); + else + macro->removeArgument(n_); + } } - insertMissingArguments(argsInDef); -} +private: + /// + int n_; + /// + bool insert_; +}; -// FIXME: factorize those functions here with a functional style, maybe using Boost's function -// objects? -void fixMacroInstancesAddRemove(Cursor const & from, docstring const & name, int n, bool insert) { - Cursor dit = from; +/// +class OptionalsMacroInstanceFix +{ +public: + /// + OptionalsMacroInstanceFix(int optionals) : optionals_(optionals) {} + /// + void operator()(MathMacro * macro) + { + macro->setOptionals(optionals_); + } - for (; dit; dit.forwardPos()) { - // only until a macro is redefined - if (dit.inset().lyxCode() == MATHMACRO_CODE) { - MathMacroTemplate const & macroTemplate - = static_cast(dit.inset()); - if (macroTemplate.name() == name) - break; - } +private: + /// + int optionals_; +}; - // in front of macro instance? - Inset * inset = dit.nextInset(); - if (!inset) - continue; - InsetMath * insetMath = inset->asInsetMath(); - if (!insetMath) - continue; - MathMacro * macro = insetMath->asMacro(); - if (macro && macro->name() == name && macro->folded()) { - // found macro instance - if (insert) - macro->insertArgument(n); - else - macro->removeArgument(n); - } - } -} +/// +class NullMacroInstanceFix +{ +public: + /// + void operator()(MathMacro * ) {} +}; -void fixMacroInstancesOptional(Cursor const & from, docstring const & name, int optionals) { - Cursor dit = from; +template +void fixMacroInstances(Cursor & cur, DocIterator const & inset_pos, + docstring const & name, F & fix) +{ + // goto position behind macro template + DocIterator dit = inset_pos; + dit.pop_back(); + dit.top().forwardPos(); + + // remember hull to trigger preview reload + DocIterator hull(dit.buffer()); + bool preview_reload_needed = false; + set preview_hulls; + // iterate over all positions until macro is redefined for (; dit; dit.forwardPos()) { + // left the outer hull? + if (!hull.empty() && dit.depth() == hull.depth()) { + // schedule reload of the preview if necessary + if (preview_reload_needed) { + preview_hulls.insert(hull); + preview_reload_needed = false; + } + hull.clear(); + } + // only until a macro is redefined if (dit.inset().lyxCode() == MATHMACRO_CODE) { MathMacroTemplate const & macroTemplate @@ -793,44 +823,55 @@ void fixMacroInstancesOptional(Cursor const & from, docstring const & name, int InsetMath * insetMath = inset->asInsetMath(); if (!insetMath) continue; + + // in front of outer hull? + InsetMathHull * inset_hull = insetMath->asHullInset(); + if (inset_hull && hull.empty()) { + // remember this for later preview reload + hull = dit; + } + MathMacro * macro = insetMath->asMacro(); if (macro && macro->name() == name && macro->folded()) { - // found macro instance - macro->setOptionals(optionals); + fix(macro); + if (RenderPreview::status() == LyXRC::PREVIEW_ON) + preview_reload_needed = true; } } -} - - -template -void fixMacroInstancesFunctional(Cursor const & from, - docstring const & name, F & fix) { - Cursor dit = from; - for (; dit; dit.forwardPos()) { - // only until a macro is redefined - if (dit.inset().lyxCode() == MATHMACRO_CODE) { - MathMacroTemplate const & macroTemplate - = static_cast(dit.inset()); - if (macroTemplate.name() == name) - break; + if (!preview_hulls.empty()) { + // reload the scheduled previews + set::const_iterator sit = preview_hulls.begin(); + set::const_iterator end = preview_hulls.end(); + for (; sit != end; ++sit) { + InsetMathHull * inset_hull = + sit->nextInset()->asInsetMath()->asHullInset(); + LASSERT(inset_hull, /**/); + inset_hull->reloadPreview(*sit); } + cur.screenUpdateFlags(Update::Force); + } +} - // in front of macro instance? - Inset * inset = dit.nextInset(); - if (!inset) - continue; - InsetMath * insetMath = inset->asInsetMath(); - if (!insetMath) - continue; - MathMacro * macro = insetMath->asMacro(); - if (macro && macro->name() == name && macro->folded()) - F(macro); + +void MathMacroTemplate::commitEditChanges(Cursor & cur, + DocIterator const & inset_pos) +{ + int args_in_def = maxArgumentInDefinition(); + if (args_in_def != numargs_) { + cur.recordUndoFullDocument(); + changeArity(cur, inset_pos, args_in_def); } + insertMissingArguments(args_in_def); + + // make sure the preview are up to date + NullMacroInstanceFix fix; + fixMacroInstances(cur, inset_pos, name(), fix); } -void MathMacroTemplate::insertParameter(Cursor & cur, int pos, bool greedy, bool addarg) +void MathMacroTemplate::insertParameter(Cursor & cur, + DocIterator const & inset_pos, int pos, bool greedy, bool addarg) { if (pos <= numargs_ && pos >= optionals_ && numargs_ < 9) { ++numargs_; @@ -845,13 +886,9 @@ void MathMacroTemplate::insertParameter(Cursor & cur, int pos, bool greedy, bool } if (!greedy) { - Cursor dit = cur; - dit.leaveInset(*this); - // TODO: this was dit.forwardPosNoDescend before. Check that this is the same - dit.top().forwardPos(); - // fix macro instances - fixMacroInstancesAddRemove(dit, name(), pos, true); + AddRemoveMacroInstanceFix fix(pos, true); + fixMacroInstances(cur, inset_pos, name(), fix); } } @@ -859,11 +896,12 @@ void MathMacroTemplate::insertParameter(Cursor & cur, int pos, bool greedy, bool } -void MathMacroTemplate::removeParameter(Cursor & cur, int pos, bool greedy) +void MathMacroTemplate::removeParameter(Cursor & cur, + DocIterator const & inset_pos, int pos, bool greedy) { if (pos < numargs_ && pos >= 0) { --numargs_; - removeArguments(cur, pos, pos); + removeArguments(cur, inset_pos, pos, pos); shiftArguments(pos + 1, -1); // removed optional parameter? @@ -886,13 +924,8 @@ void MathMacroTemplate::removeParameter(Cursor & cur, int pos, bool greedy) if (!greedy) { // fix macro instances - //boost::function fix = _1->insertArgument(n); - //fixMacroInstancesFunctional(dit, name(), fix); - Cursor dit = cur; - dit.leaveInset(*this); - // TODO: this was dit.forwardPosNoDescend before. Check that this is the same - dit.top().forwardPos(); - fixMacroInstancesAddRemove(dit, name(), pos, false); + AddRemoveMacroInstanceFix fix(pos, false); + fixMacroInstances(cur, inset_pos, name(), fix); } } @@ -900,7 +933,9 @@ void MathMacroTemplate::removeParameter(Cursor & cur, int pos, bool greedy) } -void MathMacroTemplate::makeOptional(Cursor & cur) { +void MathMacroTemplate::makeOptional(Cursor & cur, + DocIterator const & inset_pos) +{ if (numargs_ > 0 && optionals_ < numargs_) { ++optionals_; cells_.insert(cells_.begin() + optIdx(optionals_ - 1), optionalValues_[optionals_ - 1]); @@ -910,18 +945,17 @@ void MathMacroTemplate::makeOptional(Cursor & cur) { ++cur[macroSlice].idx(); // fix macro instances - Cursor dit = cur; - dit.leaveInset(*this); - // TODO: this was dit.forwardPosNoDescend before. Check that this is the same - dit.top().forwardPos(); - fixMacroInstancesOptional(dit, name(), optionals_); + OptionalsMacroInstanceFix fix(optionals_); + fixMacroInstances(cur, inset_pos, name(), fix); } updateLook(); } -void MathMacroTemplate::makeNonOptional(Cursor & cur) { +void MathMacroTemplate::makeNonOptional(Cursor & cur, + DocIterator const & inset_pos) +{ if (numargs_ > 0 && optionals_ > 0) { --optionals_; @@ -942,11 +976,8 @@ void MathMacroTemplate::makeNonOptional(Cursor & cur) { } // fix macro instances - Cursor dit = cur; - dit.leaveInset(*this); - // TODO: this was dit.forwardPosNoDescend before. Check that this is the same - dit.top().forwardPos(); - fixMacroInstancesOptional(dit, name(), optionals_); + OptionalsMacroInstanceFix fix(optionals_); + fixMacroInstances(cur, inset_pos, name(), fix); } updateLook(); @@ -956,81 +987,81 @@ void MathMacroTemplate::makeNonOptional(Cursor & cur) { void MathMacroTemplate::doDispatch(Cursor & cur, FuncRequest & cmd) { string const arg = to_utf8(cmd.argument()); - switch (cmd.action) { + switch (cmd.action()) { case LFUN_MATH_MACRO_ADD_PARAM: if (numargs_ < 9) { - commitEditChanges(cur); + commitEditChanges(cur, cur); cur.recordUndoFullDocument(); size_t pos = numargs_; if (arg.size() != 0) pos = (size_t)convert(arg) - 1; // it is checked for >=0 in getStatus - insertParameter(cur, pos); + insertParameter(cur, cur, pos); } break; case LFUN_MATH_MACRO_REMOVE_PARAM: if (numargs_ > 0) { - commitEditChanges(cur); + commitEditChanges(cur, cur); cur.recordUndoFullDocument(); size_t pos = numargs_ - 1; if (arg.size() != 0) pos = (size_t)convert(arg) - 1; // it is checked for >=0 in getStatus - removeParameter(cur, pos); + removeParameter(cur, cur, pos); } break; case LFUN_MATH_MACRO_APPEND_GREEDY_PARAM: if (numargs_ < 9) { - commitEditChanges(cur); + commitEditChanges(cur, cur); cur.recordUndoFullDocument(); - insertParameter(cur, numargs_, true); + insertParameter(cur, cur, numargs_, true); } break; case LFUN_MATH_MACRO_REMOVE_GREEDY_PARAM: if (numargs_ > 0) { - commitEditChanges(cur); + commitEditChanges(cur, cur); cur.recordUndoFullDocument(); - removeParameter(cur, numargs_ - 1, true); + removeParameter(cur, cur, numargs_ - 1, true); } break; case LFUN_MATH_MACRO_MAKE_OPTIONAL: - commitEditChanges(cur); + commitEditChanges(cur, cur); cur.recordUndoFullDocument(); - makeOptional(cur); + makeOptional(cur, cur); break; case LFUN_MATH_MACRO_MAKE_NONOPTIONAL: - commitEditChanges(cur); + commitEditChanges(cur, cur); cur.recordUndoFullDocument(); - makeNonOptional(cur); + makeNonOptional(cur, cur); break; case LFUN_MATH_MACRO_ADD_OPTIONAL_PARAM: if (numargs_ < 9) { - commitEditChanges(cur); + commitEditChanges(cur, cur); cur.recordUndoFullDocument(); - insertParameter(cur, optionals_); - makeOptional(cur); + insertParameter(cur, cur, optionals_); + makeOptional(cur, cur); } break; case LFUN_MATH_MACRO_REMOVE_OPTIONAL_PARAM: if (optionals_ > 0) { - commitEditChanges(cur); + commitEditChanges(cur, cur); cur.recordUndoFullDocument(); - removeParameter(cur, optionals_ - 1); + removeParameter(cur, cur, optionals_ - 1); } break; case LFUN_MATH_MACRO_ADD_GREEDY_OPTIONAL_PARAM: if (numargs_ == optionals_) { - commitEditChanges(cur); + commitEditChanges(cur, cur); cur.recordUndoFullDocument(); - insertParameter(cur, 0, true); - makeOptional(cur); + insertParameter(cur, cur, 0, true); + makeOptional(cur, cur); } break; @@ -1046,7 +1077,7 @@ bool MathMacroTemplate::getStatus(Cursor & /*cur*/, FuncRequest const & cmd, { bool ret = true; string const arg = to_utf8(cmd.argument()); - switch (cmd.action) { + switch (cmd.action()) { case LFUN_MATH_MACRO_ADD_PARAM: { int num = numargs_ + 1; if (arg.size() != 0) @@ -1061,6 +1092,7 @@ bool MathMacroTemplate::getStatus(Cursor & /*cur*/, FuncRequest const & cmd, flag.setEnabled(numargs_ < 9); break; + case LFUN_MATH_MACRO_REMOVE_GREEDY_PARAM: case LFUN_MATH_MACRO_REMOVE_PARAM: { int num = numargs_; if (arg.size() != 0) @@ -1108,7 +1140,7 @@ bool MathMacroTemplate::getStatus(Cursor & /*cur*/, FuncRequest const & cmd, void MathMacroTemplate::read(Lexer & lex) { MathData ar(buffer_); - mathed_parse_cell(ar, lex.getStream(), Parse::NORMAL); + mathed_parse_cell(ar, lex.getStream(), Parse::TRACKMACRO); if (ar.size() != 1 || !ar[0]->asMacroTemplate()) { lyxerr << "Cannot read macro from '" << ar << "'" << endl; lyxerr << "Read: " << to_utf8(asString(ar)) << endl; @@ -1136,8 +1168,10 @@ void MathMacroTemplate::write(WriteStream & os) const } -void MathMacroTemplate::write(WriteStream & os, bool overwriteRedefinition) const +int MathMacroTemplate::write(WriteStream & os, bool overwriteRedefinition) const { + int num_lines = 0; + if (os.latex()) { if (optionals_ > 0) { // macros with optionals use the xargs package, e.g.: @@ -1200,14 +1234,24 @@ void MathMacroTemplate::write(WriteStream & os, bool overwriteRedefinition) cons if (os.latex()) { // writing .tex. done. os << "\n"; + ++num_lines; } else { // writing .lyx, write special .tex export only if necessary - if (!cell(displayIdx()).empty()) + if (!cell(displayIdx()).empty()) { os << "\n{" << cell(displayIdx()) << '}'; + ++num_lines; + } } + + return num_lines; } +docstring MathMacroTemplate::xhtml(XHTMLStream &, OutputParams const &) const +{ + return docstring(); +} + int MathMacroTemplate::plaintext(odocstream & os, OutputParams const &) const { @@ -1323,7 +1367,7 @@ void MathMacroTemplate::infoize(odocstream & os) const } -docstring MathMacroTemplate::contextMenu(BufferView const &, int, int) const +docstring MathMacroTemplate::contextMenuName() const { return from_ascii("context-math-macro-definition"); }