]> git.lyx.org Git - lyx.git/blob - src/mathed/MathFactory.cpp
Fix drawing of empty boxes
[lyx.git] / src / mathed / MathFactory.cpp
1 /**
2  * \file MathFactory.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author André Pönitz
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "MathFactory.h"
14
15 #include "InsetMathAMSArray.h"
16 #include "InsetMathArray.h"
17 #include "InsetMathBoldSymbol.h"
18 #include "InsetMathBox.h"
19 #include "InsetMathCancel.h"
20 #include "InsetMathCancelto.h"
21 #include "InsetMathCases.h"
22 #include "InsetMathClass.h"
23 #include "InsetMathColor.h"
24 #include "InsetMathDecoration.h"
25 #include "InsetMathDots.h"
26 #include "InsetMathEnsureMath.h"
27 #include "InsetMathFont.h"
28 #include "InsetMathFontOld.h"
29 #include "InsetMathFrac.h"
30 #include "InsetMathKern.h"
31 #include "InsetMathLefteqn.h"
32 #include "InsetMathOverset.h"
33 #include "InsetMathPhantom.h"
34 #include "InsetMathRef.h"
35 #include "InsetMathRoot.h"
36 #include "InsetMathSideset.h"
37 #include "InsetMathSize.h"
38 #include "InsetMathSpace.h"
39 #include "InsetMathSpecialChar.h"
40 #include "InsetMathSplit.h"
41 #include "InsetMathSqrt.h"
42 #include "InsetMathStackrel.h"
43 #include "InsetMathSubstack.h"
44 #include "InsetMathSymbol.h"
45 #include "InsetMathTabular.h"
46 #include "InsetMathUnderset.h"
47 #include "InsetMathUnknown.h"
48 #include "InsetMathHull.h"
49 #include "InsetMathXArrow.h"
50 #include "InsetMathXYMatrix.h"
51 #include "InsetMathDiagram.h"
52 #include "MacroTable.h"
53 #include "MathMacro.h"
54 #include "MathMacroArgument.h"
55 #include "MathParser.h"
56 #include "MathStream.h"
57 #include "MathSupport.h"
58
59 #include "insets/InsetCommand.h"
60 #include "insets/InsetSpace.h"
61
62 #include "support/debug.h"
63 #include "support/docstream.h"
64 #include "support/FileName.h"
65 #include "support/filetools.h" // LibFileSearch
66 #include "support/lstrings.h"
67 #include "support/textutils.h"
68
69 #include "frontends/FontLoader.h"
70
71 #include "Buffer.h"
72 #include "BufferParams.h"
73 #include "Encoding.h"
74 #include "LyX.h" // use_gui
75 #include "OutputParams.h"
76
77
78 using namespace std;
79 using namespace lyx::support;
80
81 namespace lyx {
82
83 bool has_math_fonts;
84
85
86 namespace {
87
88 MathWordList theMathWordList;
89
90
91 bool isMathFontAvailable(string & name)
92 {
93         if (!use_gui)
94                 return false;
95
96         FontInfo f;
97         augmentFont(f, name);
98
99         // Do we have the font proper?
100         if (theFontLoader().available(f))
101                 return true;
102
103         // can we fake it?
104         if (name == "eufrak") {
105                 name = "lyxfakefrak";
106                 return true;
107         }
108
109         LYXERR(Debug::MATHED,
110                 "font " << name << " not available and I can't fake it");
111         return false;
112 }
113
114
115 bool canBeDisplayed(char_type c)
116 {
117         if (!use_gui)
118                 return true;
119         return theFontLoader().canBeDisplayed(c);
120 }
121
122
123 bool isUnicodeSymbolAvailable(docstring const & name, char_type & c)
124 {
125         docstring cmd(from_ascii("\\") + name);
126         bool is_combining;
127         bool termination;
128         c = Encodings::fromLaTeXCommand(cmd, Encodings::MATH_CMD,
129                                         is_combining, termination);
130         if (c == 0 && name == "varOmega") {
131                 // fallback for bug 7954, unicodesymbols does not list
132                 // \\varOmega because of requirements, but this might change
133                 cmd = from_ascii("\\mathit{\\Omega}");
134                 c = Encodings::fromLaTeXCommand(cmd, Encodings::MATH_CMD,
135                                                 is_combining, termination);
136         }
137         return c != 0 && !is_combining;
138 }
139
140
141 void initSymbols()
142 {
143         FileName const filename = libFileSearch(string(), "symbols");
144         LYXERR(Debug::MATHED, "read symbols from " << filename);
145         if (filename.empty()) {
146                 lyxerr << "Could not find symbols file" << endl;
147                 return;
148         }
149
150         ifstream fs(filename.toFilesystemEncoding().c_str());
151         string line;
152         bool skip = false;
153         while (getline(fs, line)) {
154                 int charid     = 0;
155                 int fallbackid = 0;
156                 if (line.empty() || line[0] == '#')
157                         continue;
158
159                 // special case of iffont/else/endif
160                 if (line.size() >= 7 && line.substr(0, 6) == "iffont") {
161                         istringstream is(line);
162                         string tmp;
163                         is >> tmp;
164                         is >> tmp;
165                         skip = !isMathFontAvailable(tmp);
166                         continue;
167                 } else if (line.size() >= 4 && line.substr(0, 4) == "else") {
168                         skip = !skip;
169                         continue;
170                 } else if (line.size() >= 5 && line.substr(0, 5) == "endif") {
171                         skip = false;
172                         continue;
173                 } else if (skip)
174                         continue;
175
176                 // special case of pre-defined macros
177                 if (line.size() > 8 && line.substr(0, 5) == "\\def\\") {
178                         //lyxerr << "macro definition: '" << line << '\'' << endl;
179                         // syntax: Either
180                         // \def\macroname{definition}
181                         // or
182                         // \def\macroname{definition} requires
183                         // or
184                         // \def\macroname{definition} extra xmlname requires
185                         istringstream is(line);
186                         string macro;
187                         string requires;
188                         string extra;
189                         string xmlname;
190                         bool hidden = false;
191                         is >> macro >> requires;
192                         if ((is >> xmlname)) {
193                                 extra = requires;
194                                 if (!(is >> requires))
195                                         requires = "";
196                         } else
197                                 xmlname = "";
198                         MacroTable::iterator it = MacroTable::globalMacros().insert(
199                                         0, from_utf8(macro));
200                         if (!extra.empty() || !xmlname.empty() || !requires.empty()) {
201                                 MathWordList::iterator wit = theMathWordList.find(it->first);
202                                 if (wit != theMathWordList.end())
203                                         LYXERR(Debug::MATHED, "readSymbols: inset "
204                                                 << to_utf8(it->first) << " already exists.");
205                                 else {
206                                         latexkeys tmp;
207                                         tmp.inset = "macro";
208                                         tmp.name = it->first;
209                                         tmp.extra = from_utf8(extra);
210                                         tmp.xmlname = from_utf8(xmlname);
211                                         if (requires == "hiddensymbol") {
212                                                 requires = "";
213                                                 tmp.hidden = hidden = true;
214                                         } else
215                                                 tmp.requires = requires;
216                                         theMathWordList[it->first] = tmp;
217                                         wit = theMathWordList.find(it->first);
218                                         it->second.setSymbol(&(wit->second));
219                                 }
220                         }
221                         // If you change the following output, please adjust
222                         // development/tools/generate_symbols_images.py.
223                         LYXERR(Debug::MATHED, "read symbol '" << to_utf8(it->first)
224                                 << "  inset: macro"
225                                 << "  draw: 0"
226                                 << "  extra: " << extra
227                                 << "  xml: " << xmlname
228                                 << "  requires: " << requires
229                                 << "  hidden: " << hidden << '\'');
230                         continue;
231                 }
232
233                 idocstringstream is(from_utf8(line));
234                 latexkeys tmp;
235                 docstring help;
236                 is >> tmp.name >> help;
237                 tmp.inset = to_ascii(help);
238                 if (isFontName(tmp.inset))
239                         is >> charid >> fallbackid >> tmp.extra >> tmp.xmlname;
240                 else
241                         is >> tmp.extra;
242                 // requires is optional
243                 if (is) {
244                         if ((is >> help)) {
245                                 // backward compatibility
246                                 if (help == "esintoramsmath")
247                                         tmp.requires = "esint|amsmath";
248                                 else
249                                         tmp.requires = to_ascii(help);
250                         }
251                 } else {
252                         LYXERR(Debug::MATHED, "skipping line '" << line << "'\n"
253                                 << to_utf8(tmp.name) << ' ' << tmp.inset << ' '
254                                 << to_utf8(tmp.extra));
255                         continue;
256                 }
257
258                 if (isFontName(tmp.inset)) {
259                         // tmp.inset _is_ the fontname here.
260                         // create fallbacks if necessary
261
262                         // store requirements as long as we can
263                         if (tmp.requires.empty()) {
264                                 if (tmp.inset == "msa" || tmp.inset == "msb")
265                                         tmp.requires = "amssymb";
266                                 else if (tmp.inset == "wasy")
267                                         tmp.requires = "wasysym";
268                                 else if (tmp.inset == "mathscr")
269                                         tmp.requires = "mathrsfs";
270                         }
271
272                         // symbol font is not available sometimes
273                         string symbol_font = "lyxsymbol";
274                         char_type unicodesymbol = 0;
275
276                         if (tmp.extra == "func" || tmp.extra == "funclim" || tmp.extra == "special") {
277                                 LYXERR(Debug::MATHED, "symbol abuse for " << to_utf8(tmp.name));
278                                 tmp.draw = tmp.name;
279                         } else if (isMathFontAvailable(tmp.inset) && canBeDisplayed(charid)) {
280                                 LYXERR(Debug::MATHED, "symbol available for " << to_utf8(tmp.name));
281                                 tmp.draw.push_back(char_type(charid));
282                         } else if (fallbackid && isMathFontAvailable(symbol_font) &&
283                                    canBeDisplayed(fallbackid)) {
284                                 if (tmp.inset == "cmex")
285                                         tmp.inset = "lyxsymbol";
286                                 else
287                                         tmp.inset = "lyxboldsymbol";
288                                 LYXERR(Debug::MATHED, "symbol fallback for " << to_utf8(tmp.name));
289                                 tmp.draw.push_back(char_type(fallbackid));
290                         } else if (isUnicodeSymbolAvailable(tmp.name, unicodesymbol)) {
291                                 LYXERR(Debug::MATHED, "unicode fallback for " << to_utf8(tmp.name));
292                                 tmp.inset = "mathnormal";
293                                 tmp.draw.push_back(unicodesymbol);
294                         } else {
295                                 LYXERR(Debug::MATHED, "faking " << to_utf8(tmp.name));
296                                 tmp.draw = tmp.name;
297                                 tmp.inset = "lyxtex";
298                         }
299                 } else {
300                         // it's a proper inset
301                         LYXERR(Debug::MATHED, "inset " << tmp.inset
302                                               << " used for " << to_utf8(tmp.name));
303                 }
304
305                 if (tmp.requires == "hiddensymbol")
306                 {
307                         tmp.requires = "";
308                         tmp.hidden = true;
309                 }
310
311                 if (theMathWordList.find(tmp.name) != theMathWordList.end())
312                         LYXERR(Debug::MATHED, "readSymbols: inset " << to_utf8(tmp.name)
313                                 << " already exists.");
314                 else
315                         theMathWordList[tmp.name] = tmp;
316
317                 // If you change the following output, please adjust
318                 // development/tools/generate_symbols_images.py.
319                 LYXERR(Debug::MATHED, "read symbol '" << to_utf8(tmp.name)
320                         << "  inset: " << tmp.inset
321                         << "  draw: " << int(tmp.draw.empty() ? 0 : tmp.draw[0])
322                         << "  extra: " << to_utf8(tmp.extra)
323                         << "  xml: " << to_utf8(tmp.xmlname)
324                         << "  requires: " << tmp.requires
325                         << "  hidden: " << tmp.hidden << '\'');
326         }
327         string tmp = "cmm";
328         string tmp2 = "cmsy";
329         has_math_fonts = isMathFontAvailable(tmp) && isMathFontAvailable(tmp2);
330 }
331
332
333 bool isSpecialChar(docstring const & name)
334 {
335         if (name.size() != 1)
336                 return  name == "textasciicircum" || name == "mathcircumflex" ||
337                         name == "textasciitilde"  || name == "textbackslash";
338
339         char_type const c = name.at(0);
340         return  c == '{' || c == '}' || c == '&' || c == '$' ||
341                 c == '#' || c == '%' || c == '_';
342 }
343
344
345 } // namespace anon
346
347 MathWordList const & mathedWordList()
348 {
349         return theMathWordList;
350 }
351
352
353 void initMath()
354 {
355         static bool initialized = false;
356         if (!initialized) {
357                 initialized = true;
358                 initParser();
359                 initSymbols();
360         }
361 }
362
363
364 bool ensureMath(WriteStream & os, bool needs_mathmode, bool macro,
365                 bool textmode_macro)
366 {
367         bool brace = os.pendingBrace();
368         os.pendingBrace(false);
369         if (!os.latex())
370                 return brace;
371         if (os.textMode() && needs_mathmode) {
372                 if (brace) {
373                         // close \lyxmathsym
374                         os << '}';
375                         brace = false;
376                 } else {
377                         os << "\\ensuremath{";
378                         brace = true;
379                 }
380                 os.textMode(false);
381         } else if (macro && textmode_macro && !os.textMode()) {
382                 if (brace) {
383                         // close \ensuremath
384                         os << '}';
385                         brace = false;
386                 } else {
387                         os << "\\lyxmathsym{";
388                         brace = true;
389                 }
390                 os.textMode(true);
391         } else if (macro && brace && !needs_mathmode && !textmode_macro) {
392                 // This is a user defined macro, not a MathMacro, so we
393                 // cannot be sure what mode is needed. We leave it in the
394                 // same environment it was entered by closing either \lyxmathsym
395                 // or \ensuremath, whichever was opened.
396                 os << '}';
397                 brace = false;
398                 os.textMode(!os.textMode());
399         }
400         return brace;
401 }
402
403
404 int ensureMode(WriteStream & os, InsetMath::mode_type mode,
405                 bool locked, bool ascii)
406 {
407         bool textmode = mode == InsetMath::TEXT_MODE;
408         if (os.latex() && textmode && os.pendingBrace()) {
409                 os.os() << '}';
410                 os.pendingBrace(false);
411                 os.pendingSpace(false);
412                 os.textMode(true);
413         }
414         int oldmodes = os.textMode() ? 0x01 : 0;
415         os.textMode(textmode);
416         oldmodes |= os.lockedMode() ? 0x02 : 0;
417         os.lockedMode(locked);
418         oldmodes |= os.asciiOnly() ? 0x04 : 0;
419         os.asciiOnly(ascii);
420         return oldmodes;
421 }
422
423
424 latexkeys const * in_word_set(docstring const & str)
425 {
426         MathWordList::iterator it = theMathWordList.find(str);
427         if (it == theMathWordList.end())
428                 return 0;
429         if (it->second.inset == "macro")
430                 return 0;
431         return &(it->second);
432 }
433
434
435 MathAtom createInsetMath(char const * const s, Buffer * buf)
436 {
437         return createInsetMath(from_utf8(s), buf);
438 }
439
440
441 MathAtom createInsetMath(docstring const & s, Buffer * buf)
442 {
443         //lyxerr << "creating inset with name: '" << to_utf8(s) << '\'' << endl;
444         if ((s == "ce" || s == "cf") && buf
445             && buf->params().use_package("mhchem") == BufferParams::package_off)
446                 return MathAtom(new MathMacro(buf, s));
447
448         latexkeys const * l = in_word_set(s);
449         if (l) {
450                 string const & inset = l->inset;
451                 //lyxerr << " found inset: '" << inset << '\'' << endl;
452                 if (inset == "ref")
453                         return MathAtom(new InsetMathRef(buf, l->name));
454                 if (inset == "overset")
455                         return MathAtom(new InsetMathOverset(buf));
456                 if (inset == "underset")
457                         return MathAtom(new InsetMathUnderset(buf));
458                 if (inset == "decoration")
459                         return MathAtom(new InsetMathDecoration(buf, l));
460                 if (inset == "space")
461                         return MathAtom(new InsetMathSpace(to_ascii(l->name), ""));
462                 if (inset == "class")
463                         return MathAtom(new InsetMathClass(buf, string_to_class(s)));
464                 if (inset == "dots")
465                         return MathAtom(new InsetMathDots(l));
466                 if (inset == "mbox")
467                         return MathAtom(new InsetMathBox(buf, l->name));
468 //              if (inset == "fbox")
469 //                      return MathAtom(new InsetMathFBox(l));
470                 if (inset == "style")
471                         return MathAtom(new InsetMathSize(buf, l));
472                 if (inset == "font")
473                         return MathAtom(new InsetMathFont(buf, l));
474                 if (inset == "oldfont")
475                         return MathAtom(new InsetMathFontOld(buf, l));
476                 if (inset == "matrix")
477                         return MathAtom(new InsetMathAMSArray(buf, s));
478                 if (inset == "split")
479                         return MathAtom(new InsetMathSplit(buf, s));
480                 if (inset == "big")
481                         // we can't create a InsetMathBig, since the argument
482                         // is missing.
483                         return MathAtom(new InsetMathUnknown(s));
484                 return MathAtom(new InsetMathSymbol(l));
485         }
486
487         if (s.size() == 2 && s[0] == '#' && s[1] >= '1' && s[1] <= '9')
488                 return MathAtom(new MathMacroArgument(s[1] - '0'));
489         if (s.size() == 3 && s[0] == '\\' && s[1] == '#'
490                         && s[2] >= '1' && s[2] <= '9')
491                 return MathAtom(new MathMacroArgument(s[2] - '0'));
492         if (s == "boxed")
493                 return MathAtom(new InsetMathBoxed(buf));
494         if (s == "fbox")
495                 return MathAtom(new InsetMathFBox(buf));
496         if (s == "framebox")
497                 return MathAtom(new InsetMathMakebox(buf, true));
498         if (s == "makebox")
499                 return MathAtom(new InsetMathMakebox(buf, false));
500         if (s == "kern" || s == "mkern")
501                 return MathAtom(new InsetMathKern);
502         if (s.substr(0, 8) == "xymatrix") {
503                 char spacing_code = '\0';
504                 Length spacing;
505                 bool equal_spacing = false;
506                 size_t const len = s.length();
507                 size_t i = 8;
508                 if (i < len && s[i] == '@') {
509                         ++i;
510                         if (i < len && s[i] == '!') {
511                                 equal_spacing = true;
512                                 ++i;
513                                 if (i < len) {
514                                         switch (s[i]) {
515                                         case '0':
516                                         case 'R':
517                                         case 'C':
518                                                 spacing_code = static_cast<char>(s[i]);
519                                         }
520                                 }
521                         } else if (i < len) {
522                                 switch (s[i]) {
523                                 case 'R':
524                                 case 'C':
525                                 case 'M':
526                                 case 'W':
527                                 case 'H':
528                                 case 'L':
529                                         spacing_code = static_cast<char>(s[i]);
530                                         ++i;
531                                         break;
532                                 }
533                                 if (i < len && s[i] == '=') {
534                                         ++i;
535                                         spacing = Length(to_ascii(s.substr(i)));
536                                 }
537                         }
538                 }
539                 return MathAtom(new InsetMathXYMatrix(buf, spacing, spacing_code,
540                         equal_spacing));
541         }
542
543         if (s == "Diagram")
544                 return MathAtom(new InsetMathDiagram(buf));
545         if (s == "xrightarrow" || s == "xleftarrow" ||
546                 s == "xhookrightarrow" || s == "xhookleftarrow" ||
547                 s == "xRightarrow" || s == "xLeftarrow" ||
548                 s == "xleftrightarrow" || s == "xLeftrightarrow" ||
549                 s == "xrightharpoondown" || s == "xrightharpoonup" ||
550                 s == "xleftharpoondown" || s == "xleftharpoonup" ||
551                 s == "xleftrightharpoons" || s == "xrightleftharpoons" ||
552                 s == "xmapsto")
553                 return MathAtom(new InsetMathXArrow(buf, s));
554         if (s == "split" || s == "alignedat")
555                 return MathAtom(new InsetMathSplit(buf, s));
556         if (s == "cases")
557                 return MathAtom(new InsetMathCases(buf));
558         if (s == "substack")
559                 return MathAtom(new InsetMathSubstack(buf));
560         if (s == "subarray" || s == "array")
561                 return MathAtom(new InsetMathArray(buf, s, 1, 1));
562         if (s == "sqrt")
563                 return MathAtom(new InsetMathSqrt(buf));
564         if (s == "root")
565                 return MathAtom(new InsetMathRoot(buf));
566         if (s == "tabular")
567                 return MathAtom(new InsetMathTabular(buf, s, 1, 1));
568         if (s == "stackrel")
569                 return MathAtom(new InsetMathStackrel(buf, false));
570         // This string value is only for math toolbar use, no LaTeX name
571         if (s == "stackrelthree")
572                 return MathAtom(new InsetMathStackrel(buf, true));
573         if (s == "binom")
574                 return MathAtom(new InsetMathBinom(buf, InsetMathBinom::BINOM));
575         if (s == "dbinom")
576                 return MathAtom(new InsetMathBinom(buf, InsetMathBinom::DBINOM));
577         if (s == "tbinom")
578                 return MathAtom(new InsetMathBinom(buf, InsetMathBinom::TBINOM));
579         if (s == "choose")
580                 return MathAtom(new InsetMathBinom(buf, InsetMathBinom::CHOOSE));
581         if (s == "brace")
582                 return MathAtom(new InsetMathBinom(buf, InsetMathBinom::BRACE));
583         if (s == "brack")
584                 return MathAtom(new InsetMathBinom(buf, InsetMathBinom::BRACK));
585         if (s == "frac")
586                 return MathAtom(new InsetMathFrac(buf));
587         if (s == "cfrac")
588                 return MathAtom(new InsetMathFrac(buf, InsetMathFrac::CFRAC));
589         if (s == "dfrac")
590                 return MathAtom(new InsetMathFrac(buf, InsetMathFrac::DFRAC));
591         if (s == "tfrac")
592                 return MathAtom(new InsetMathFrac(buf, InsetMathFrac::TFRAC));
593         if (s == "over")
594                 return MathAtom(new InsetMathFrac(buf, InsetMathFrac::OVER));
595         if (s == "nicefrac")
596                 return MathAtom(new InsetMathFrac(buf, InsetMathFrac::NICEFRAC));
597         if (s == "unitfrac")
598                 return MathAtom(new InsetMathFrac(buf, InsetMathFrac::UNITFRAC));
599         // These string values are only for math toolbar use, no LaTeX names
600         if (s == "unitfracthree")
601                 return MathAtom(new InsetMathFrac(buf, InsetMathFrac::UNITFRAC, 3));
602         if (s == "unitone")
603                 return MathAtom(new InsetMathFrac(buf, InsetMathFrac::UNIT, 1));
604         if (s == "unittwo")
605                 return MathAtom(new InsetMathFrac(buf, InsetMathFrac::UNIT));
606         if (s == "cfracleft")
607                 return MathAtom(new InsetMathFrac(buf, InsetMathFrac::CFRACLEFT));
608         if (s == "cfracright")
609                 return MathAtom(new InsetMathFrac(buf, InsetMathFrac::CFRACRIGHT));
610         //if (s == "infer")
611         //      return MathAtom(new MathInferInset);
612         if (s == "atop")
613                 return MathAtom(new InsetMathFrac(buf, InsetMathFrac::ATOP));
614         if (s == "lefteqn")
615                 return MathAtom(new InsetMathLefteqn(buf));
616         if (s == "boldsymbol")
617                 return MathAtom(new InsetMathBoldSymbol(buf, InsetMathBoldSymbol::AMS_BOLD));
618         if (s == "bm")
619                 return MathAtom(new InsetMathBoldSymbol(buf, InsetMathBoldSymbol::BM_BOLD));
620         if (s == "heavysymbol" || s == "hm")
621                 return MathAtom(new InsetMathBoldSymbol(buf, InsetMathBoldSymbol::BM_HEAVY));
622         if (s == "color" || s == "normalcolor")
623                 return MathAtom(new InsetMathColor(buf, true));
624         if (s == "textcolor")
625                 return MathAtom(new InsetMathColor(buf, false));
626         if (s == "hphantom")
627                 return MathAtom(new InsetMathPhantom(buf, InsetMathPhantom::hphantom));
628         if (s == "phantom")
629                 return MathAtom(new InsetMathPhantom(buf, InsetMathPhantom::phantom));
630         if (s == "vphantom")
631                 return MathAtom(new InsetMathPhantom(buf, InsetMathPhantom::vphantom));
632         if (s == "cancel")
633                 return MathAtom(new InsetMathCancel(buf, InsetMathCancel::cancel));
634         if (s == "bcancel")
635                 return MathAtom(new InsetMathCancel(buf, InsetMathCancel::bcancel));
636         if (s == "xcancel")
637                 return MathAtom(new InsetMathCancel(buf, InsetMathCancel::xcancel));
638         if (s == "cancelto")
639                 return MathAtom(new InsetMathCancelto(buf));
640         if (s == "smash")
641                 return MathAtom(new InsetMathPhantom(buf, InsetMathPhantom::smash));
642         // The following 2 string values are only for math toolbar use, no LaTeX names
643         if (s == "smashb")
644                 return MathAtom(new InsetMathPhantom(buf, InsetMathPhantom::smashb));
645         if (s == "smasht")
646                 return MathAtom(new InsetMathPhantom(buf, InsetMathPhantom::smasht));
647         if (s == "mathclap")
648                 return MathAtom(new InsetMathPhantom(buf, InsetMathPhantom::mathclap));
649         if (s == "mathllap")
650                 return MathAtom(new InsetMathPhantom(buf, InsetMathPhantom::mathllap));
651         if (s == "mathrlap")
652                 return MathAtom(new InsetMathPhantom(buf, InsetMathPhantom::mathrlap));
653         if (s == "ensuremath")
654                 return MathAtom(new InsetMathEnsureMath(buf));
655         if (s == "sideset")
656                 return MathAtom(new InsetMathSideset(buf, true, true));
657         // The following 3 string values are only for math toolbar use, no LaTeX names
658         if (s == "sidesetr")
659                 return MathAtom(new InsetMathSideset(buf, false, true));
660         if (s == "sidesetl")
661                 return MathAtom(new InsetMathSideset(buf, true, false));
662         if (s == "sidesetn")
663                 return MathAtom(new InsetMathSideset(buf, false, false));
664         if (isSpecialChar(s))
665                 return MathAtom(new InsetMathSpecialChar(s));
666         if (s == " ")
667                 return MathAtom(new InsetMathSpace(" ", ""));
668         if (s == "regexp")
669                 return MathAtom(new InsetMathHull(buf, hullRegexp));
670
671         return MathAtom(new MathMacro(buf, s));
672 }
673
674
675 bool createInsetMath_fromDialogStr(docstring const & str, MathData & ar)
676 {
677         // An example str:
678         // "ref LatexCommand ref\nreference \"sec:Title\"\n\\end_inset\n\n";
679         docstring name;
680         docstring body = split(str, name, ' ');
681
682         if (name == "ref") {
683                 InsetCommandParams icp(REF_CODE);
684                 // FIXME UNICODE
685                 InsetCommand::string2params(to_utf8(str), icp);
686                 Encoding const * const utf8 = encodings.fromLyXName("utf8");
687                 OutputParams op(utf8);
688                 mathed_parse_cell(ar, icp.getCommand(op));
689         } else if (name == "mathspace") {
690                 InsetSpaceParams isp(true);
691                 InsetSpace::string2params(to_utf8(str), isp);
692                 InsetSpace is(isp);
693                 odocstringstream ods;
694                 otexstream os(ods);
695                 Encoding const * const ascii = encodings.fromLyXName("ascii");
696                 OutputParams op(ascii);
697                 is.latex(os, op);
698                 mathed_parse_cell(ar, ods.str());
699                 if (ar.size() == 2) {
700                         // remove "{}"
701                         if (ar[1].nucleus()->asBraceInset())
702                                 ar.pop_back();
703                 }
704         } else
705                 return false;
706
707         if (ar.size() != 1)
708                 return false;
709
710         return ar[0].nucleus();
711 }
712
713
714 bool isAsciiOrMathAlpha(char_type c)
715 {
716         return isASCII(c) || Encodings::isMathAlpha(c);
717 }
718
719
720 } // namespace lyx