+bool InsetMathNest::completionSupported(Cursor const & cur) const
+{
+ return cur.inMacroMode();
+}
+
+
+bool InsetMathNest::inlineCompletionSupported(Cursor const & cur) const
+{
+ return cur.inMacroMode();
+}
+
+
+bool InsetMathNest::automaticInlineCompletion() const
+{
+ return lyxrc.completion_inline_math;
+}
+
+
+bool InsetMathNest::automaticPopupCompletion() const
+{
+ return lyxrc.completion_popup_math;
+}
+
+
+CompletionList const *
+InsetMathNest::createCompletionList(Cursor const & cur) const
+{
+ if (!cur.inMacroMode())
+ return 0;
+
+ return new MathCompletionList(cur);
+}
+
+
+docstring InsetMathNest::completionPrefix(Cursor const & cur) const
+{
+ if (!cur.inMacroMode())
+ return docstring();
+
+ return cur.activeMacro()->name();
+}
+
+
+bool InsetMathNest::insertCompletion(Cursor & cur, docstring const & s,
+ bool finished)
+{
+ if (!cur.inMacroMode())
+ return false;
+
+ // append completion to active macro
+ InsetMathUnknown * inset = cur.activeMacro();
+ inset->setName(inset->name() + s);
+
+ // finish macro
+ if (finished) {
+#if 0
+ // FIXME: this creates duplicates in the completion popup
+ // which looks ugly. Moreover the changes the list lengths
+ // which seems to
+ confuse the popup as well.
+ MathCompletionList::addToFavorites(inset->name());
+#endif
+ lyx::dispatch(FuncRequest(LFUN_SELF_INSERT, " "));
+ }
+
+ return true;
+}
+
+
+void InsetMathNest::completionPosAndDim(Cursor const & cur, int & x, int & y,
+ Dimension & dim) const
+{
+ Inset const * inset = cur.activeMacro();
+ if (!inset)
+ return;
+
+ // get inset dimensions
+ dim = cur.bv().coordCache().insets().dim(inset);
+ // FIXME: these 3 are no accurate, but should depend on the font.
+ // Now the popup jumps down if you enter a char with descent > 0.
+ dim.des += 3;
+ dim.asc += 3;
+
+ // and position
+ Point xy = cur.bv().coordCache().insets().xy(inset);
+ x = xy.x_;
+ y = xy.y_;
+}
+
+
+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)
+{
+ // fill it with macros from the buffer
+ MacroNameSet macros;
+ cur.buffer()->listMacroNames(macros);
+ MacroNameSet::const_iterator it;
+ for (it = macros.begin(); it != macros.end(); ++it) {
+ if (cur.buffer()->getMacro(*it, cur, false))
+ locals.push_back("\\" + *it);
+ }
+ sort(locals.begin(), locals.end());
+
+ if (!globals.empty())
+ return;
+
+ // fill in global macros
+ macros.clear();
+ MacroTable::globalMacros().getMacroNames(macros, false);
+ //lyxerr << "Globals completion macros: ";
+ for (it = macros.begin(); it != macros.end(); ++it) {
+ //lyxerr << "\\" + *it << " ";
+ globals.push_back("\\" + *it);
+ }
+ //lyxerr << std::endl;
+
+ // fill in global commands
+ globals.push_back(from_ascii("\\boxed"));
+ globals.push_back(from_ascii("\\fbox"));
+ 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("\\alignedat"));
+ globals.push_back(from_ascii("\\cases"));
+ globals.push_back(from_ascii("\\substack"));
+ globals.push_back(from_ascii("\\xymatrix"));
+ globals.push_back(from_ascii("\\Diagram"));
+ globals.push_back(from_ascii("\\subarray"));
+ globals.push_back(from_ascii("\\array"));
+ globals.push_back(from_ascii("\\sqrt"));
+ 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("\\brack"));
+ globals.push_back(from_ascii("\\frac"));
+ globals.push_back(from_ascii("\\over"));
+ globals.push_back(from_ascii("\\nicefrac"));
+ globals.push_back(from_ascii("\\unitfrac"));
+ globals.push_back(from_ascii("\\unitfracthree"));
+ globals.push_back(from_ascii("\\unitone"));
+ globals.push_back(from_ascii("\\unittwo"));
+ globals.push_back(from_ascii("\\infer"));
+ globals.push_back(from_ascii("\\atop"));
+ globals.push_back(from_ascii("\\lefteqn"));
+ globals.push_back(from_ascii("\\boldsymbol"));
+ globals.push_back(from_ascii("\\bm"));
+ globals.push_back(from_ascii("\\color"));
+ globals.push_back(from_ascii("\\normalcolor"));
+ globals.push_back(from_ascii("\\textcolor"));
+ globals.push_back(from_ascii("\\cfrac"));
+ globals.push_back(from_ascii("\\cfracleft"));
+ globals.push_back(from_ascii("\\cfracright"));
+ globals.push_back(from_ascii("\\dfrac"));
+ globals.push_back(from_ascii("\\tfrac"));
+ globals.push_back(from_ascii("\\dbinom"));
+ globals.push_back(from_ascii("\\tbinom"));
+ 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) {
+ 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());
+}
+
+
+MathCompletionList::~MathCompletionList()
+{
+}
+
+
+size_type MathCompletionList::size() const
+{
+ return locals.size() + globals.size();
+}
+
+
+docstring const & MathCompletionList::data(size_t idx) const
+{
+ size_t lsize = locals.size();
+ if (idx >= lsize)
+ return globals[idx - lsize];
+ else
+ return locals[idx];
+}
+
+
+std::string MathCompletionList::icon(size_t idx) const
+{
+ // get the latex command
+ docstring cmd;
+ size_t lsize = locals.size();
+ if (idx >= lsize)
+ cmd = globals[idx - lsize];
+ else
+ cmd = locals[idx];
+
+ // get the icon resource name by stripping the backslash
+ 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;
+