]> git.lyx.org Git - lyx.git/blob - src/mathed/math_factory.C
*duck*
[lyx.git] / src / mathed / math_factory.C
1 #include <config.h>
2
3 #include "math_parser.h"
4 #include "math_arrayinset.h"
5 #include "math_amsarrayinset.h"
6 #include "math_binominset.h"
7 #include "math_boxinset.h"
8 #include "math_casesinset.h"
9 #include "math_decorationinset.h"
10 #include "math_dotsinset.h"
11 #include "math_fontinset.h"
12 #include "math_fracinset.h"
13 #include "math_kerninset.h"
14 #include "math_lefteqninset.h"
15 #include "math_macro.h"
16 #include "math_macrotable.h"
17 #include "math_macroarg.h"
18 #include "math_notinset.h"
19 #include "math_rootinset.h"
20 #include "math_sizeinset.h"
21 #include "math_spaceinset.h"
22 #include "math_splitinset.h"
23 #include "math_sqrtinset.h"
24 #include "math_stackrelinset.h"
25 #include "math_substackinset.h"
26 #include "math_symbolinset.h"
27 #include "math_undersetinset.h"
28 #include "math_unknowninset.h"
29 #include "math_xarrowinset.h"
30 #include "math_xymatrixinset.h"
31 #include "math_xyarrowinset.h"
32
33 #include "math_metricsinfo.h"
34 #include "debug.h"
35 #include "math_support.h"
36 #include "Lsstream.h"
37 #include "support/filetools.h" // LibFileSearch
38 #include "frontends/font_loader.h"
39
40 #include <map>
41 #include <fstream>
42
43
44 namespace {
45
46 // file scope
47 typedef std::map<string, latexkeys> WordList;
48 WordList theWordList;
49
50
51 struct key_type {
52         ///
53         string name;
54         ///
55         string inset;
56         ///
57         int id;
58 };
59
60
61 key_type wordlist_array[] =
62 {
63         {"!",  "space", 0},
64         {"(",  "begin", LM_OT_SIMPLE},
65         {")",  "end", LM_OT_SIMPLE},
66         {",",  "space", 1},
67         {":",  "space", 2},
68         {";",  "space", 3},
69         {"[",  "begin", LM_OT_EQUATION},
70         {"]",  "end", LM_OT_EQUATION},
71         {"acute",  "decoration", 0},
72         {"bar",  "decoration", 0},
73         {"begin",  "begin", 0},
74         {"bf",  "oldfont", 0},
75         {"breve",  "decoration", 0},
76         {"cal",  "oldfont", 0},
77         {"cdots",  "dots", 0},
78         {"check",  "decoration", 0},
79         {"ddot",  "decoration", 0},
80         {"dddot",  "decoration", 0},
81         {"ddots",  "dots", 0},
82         {"displaystyle",  "style", LM_ST_DISPLAY},
83         {"dot",  "decoration", 0},
84         {"dotsb",  "dots", 0},
85         {"dotsc",  "dots", 0},
86         {"dotsi",  "dots", 0},
87         {"dotsm",  "dots", 0},
88         {"dotso",  "dots", 0},
89         {"end",  "end", 0},
90         {"frak",  "font", 0},
91         {"grave",  "decoration", 0},
92         {"hat",  "decoration", 0},
93         {"it",  "oldfont", 0},
94         {"label",  "label", 0},
95         {"ldots",  "dots", 0},
96         {"left",  "left", 0},
97         {"limits",  "limit", 1 },
98         {"lyxbox",  "box", 0},
99         {"lyxnegspace",  "space", 6},
100         {"mathbb",  "font", 0},
101         {"mathbf",  "font", 0},
102         {"mathcal",  "font", 0},
103         {"mathfrak",  "font", 0},
104         {"mathit",  "font", 0},
105         {"mathnormal",  "font", 0},
106         {"mathring",  "decoration", 0},
107         {"mathrm",  "font", 0},
108         {"mathsf",  "font", 0},
109         {"mathtt",  "font", 0},
110         {"mbox",  "box", 0},
111         {"newcommand",  "newcommand", 0 },
112         {"nolimits",  "limit", -1},
113         {"nonumber",  "nonum", 0},
114         {"overbrace",  "decoration", 0},
115         {"overleftarrow",  "decoration", 0},
116         {"overline",  "decoration", 0},
117         {"overrightarrow",  "decoration", 0},
118         {"overleftrightarrow", "decoration", 0},
119         {"protect",  "protect", 0},
120         {"qquad",  "space", 5},
121         {"quad",  "space", 4},
122         {"right",  "right", 0},
123         {"rm",  "oldfont", 0},
124         {"scriptscriptstyle",  "style", LM_ST_SCRIPTSCRIPT},
125         {"scriptstyle",  "style", LM_ST_SCRIPT},
126         {"textbf",  "font", 1},
127         {"textit",  "font", 1},
128         {"textmd",  "font", 1},
129         {"textrm",  "font", 1},
130         {"textsl",  "font", 1},
131         {"textup",  "font", 1},
132         {"textstyle",  "style", LM_ST_TEXT},
133         {"tilde",  "decoration", 0},
134         {"tt",  "oldfont", 0},
135         {"underbar",  "decoration", 0},
136         {"underbrace",  "decoration", 0},
137         {"underleftarrow", "decoration", 0},
138         {"underline",  "decoration", 0},
139         {"underrightarrow", "decoration", 0},
140         {"underleftrightarrow", "decoration", 0},
141         {"underset",  "underset", 0},
142         {"vdots",  "dots", 0},
143         {"vec",  "decoration", 0},
144         {"widehat",  "decoration", 0},
145         {"widetilde",  "decoration", 0}
146 };
147
148
149 bool math_font_available(string & name)
150 {
151         LyXFont f;
152         augmentFont(f, name);
153
154         // Do we have the font proper?
155         if (fontloader.available(f))
156                 return true;
157
158         // can we fake it?
159         if (name == "eufrak") {
160                 name = "lyxfakefrak";
161                 return true;
162         }
163
164         lyxerr << "font " << name << " not available and I can't fake it\n";
165         return false;
166 }
167
168
169 void readSymbols(string const & filename)
170 {
171         std::ifstream fs(filename.c_str());
172         while (fs) {
173                 int charid     = 0;
174                 int fallbackid = 0;
175                 latexkeys tmp;
176                 string line;
177                 getline(fs, line);
178                 istringstream is(line);
179                 is      >> tmp.name
180                                 >> tmp.inset
181                                 >> charid
182                                 >> fallbackid
183                                 >> tmp.extra
184                                 >> tmp.xmlname;
185                 if (!is)
186                         continue;
187
188                 // tmp.inset _is_ the fontname here.
189                 // create fallbacks if necessary
190                 if (tmp.extra == "func" || tmp.extra == "funclim" || tmp.extra=="special") {
191                         lyxerr[Debug::MATHED] << "symbol abuse for " << tmp.name << "\n";
192                         tmp.draw = tmp.name;
193                 } else if (math_font_available(tmp.inset)) {
194                         lyxerr[Debug::MATHED] << "symbol available for " << tmp.name << "\n";
195                         tmp.draw += char(charid);
196                 } else if (fallbackid) {
197                         if (tmp.inset == "cmex")
198                                 tmp.inset  = "lyxsymbol";
199                         else
200                                 tmp.inset  = "lyxboldsymbol";
201                         lyxerr[Debug::MATHED] << "symbol fallback for " << tmp.name << "\n";
202                         tmp.draw += char(fallbackid); 
203                 } else {
204                         lyxerr[Debug::MATHED] << "faking " << tmp.name << "\n";
205                         tmp.draw = tmp.name;
206                         tmp.inset = "lyxredtext";
207                 }
208
209                 if (theWordList.find(tmp.name) != theWordList.end())
210                         lyxerr[Debug::MATHED] << "readSymbols: inset " << tmp.name
211                                << " already exists.\n";
212                 else
213                         theWordList[tmp.name] = tmp;
214                 lyxerr[Debug::MATHED] << "read symbol '" << tmp.name
215                                         <<  "  inset: " << tmp.inset
216                                         <<  "  draw: " << int(tmp.draw[0])
217                                         <<  "  extra: " << tmp.extra
218                                         << "'\n";
219         }
220 }
221
222
223 void initSymbols()
224 {
225         unsigned const n = sizeof(wordlist_array) / sizeof(wordlist_array[0]);
226         for (key_type * p = wordlist_array; p != wordlist_array + n; ++p) {
227                 latexkeys tmp;
228                 tmp.name  = p->name;
229                 tmp.inset = p->inset;
230                 tmp.draw  = p->name;
231                 theWordList[p->name] = tmp;
232         }
233
234         lyxerr[Debug::MATHED] << "reading symbols file\n";
235         string const file = LibFileSearch(string(), "symbols");
236         if (file.empty())
237                 lyxerr << "Could not find symbols file\n";
238         else
239                 readSymbols(file);
240 }
241
242
243 } // namespace anon
244
245
246 latexkeys const * in_word_set(string const & str)
247 {
248         static bool initialized = false;
249
250         if (!initialized) {
251                 initSymbols();
252                 initialized = true;
253         }
254
255         WordList::iterator it = theWordList.find(str);
256         //lyxerr << "looking up '" << str << "' found: "
257         // << (it != theWordList.end()) << "\n";
258         return (it != theWordList.end()) ? &(it->second) : 0;
259 }
260
261
262 MathAtom createMathInset(string const & s)
263 {
264         lyxerr[Debug::MATHED] << "creating inset with name: '" << s << "'\n";
265         if (s.size() == 2 && s[0] == '#' && s[1] >= '1' && s[1] <= '9')
266                 return MathAtom(new MathMacroArgument(s[1] - '0'));
267
268         if (s.size() == 3 && s[0] == '\\' && s[1] == '#'
269                         && s[2] >= '1' && s[2] <= '9')
270                 return MathAtom(new MathMacroArgument(s[2] - '0'));
271         if (s == "kern")
272                 return MathAtom(new MathKernInset);
273         if (s == "xymatrix")
274                 return MathAtom(new MathXYMatrixInset);
275         if (s == "xrightarrow" || s == "xleftarrow")
276                 return MathAtom(new MathXArrowInset(s));
277         if (s == "split" || s == "gathered" || s == "aligned")
278                 return MathAtom(new MathSplitInset(s));
279         if (s == "cases")
280                 return MathAtom(new MathCasesInset);
281         if (s == "substack")
282                 return MathAtom(new MathSubstackInset);
283         if (s == "subarray" || s == "array")
284                 return MathAtom(new MathArrayInset(s, 1, 1));
285         if (s == "pmatrix" || s == "bmatrix" || s == "vmatrix" || s == "Vmatrix" ||
286                   s == "matrix")
287                 return MathAtom(new MathAMSArrayInset(s));
288         if (s == "sqrt")
289                 return MathAtom(new MathSqrtInset);
290         if (s == "root")
291                 return MathAtom(new MathRootInset);
292         if (s == "stack")
293                 return MathAtom(new MathStackrelInset);
294         if (s == "binom" || s == "choose")
295                 return MathAtom(new MathBinomInset);
296         if (s == "over" || s == "frac")
297                 return MathAtom(new MathFracInset);
298         if (s == "atop")
299                 return MathAtom(new MathFracInset(true));
300         if (s == "not")
301                 return MathAtom(new MathNotInset);
302         if (s == "lefteqn")
303                 return MathAtom(new MathLefteqnInset);
304
305         latexkeys const * l = in_word_set(s);
306         if (l) {
307                 string const & inset = l->inset;
308                 lyxerr[Debug::MATHED] << " found inset: '" << inset << "'\n";
309                 if (inset == "underset")
310                         return MathAtom(new MathUndersetInset);
311                 if (inset == "decoration")
312                         return MathAtom(new MathDecorationInset(l->name));
313                 //if (inset == "space")
314                 //      return MathAtom(new MathSpaceInset(l->id));
315                 if (inset == "dots")
316                         return MathAtom(new MathDotsInset(l->name));
317                 if (inset == "box")
318                         return MathAtom(new MathBoxInset(l->name));
319                 if (inset == "style")
320                         return MathAtom(new MathSizeInset(l));
321                 if (inset == "font")
322                         return MathAtom(new MathFontInset(l->name));
323                 if (inset == "oldfont")
324                         return MathAtom(new MathFontInset(l->name));
325                 return MathAtom(new MathSymbolInset(l));
326         }
327
328         if (MathMacroTable::has(s))
329                 return MathAtom(new MathMacro(s));
330
331         //lyxerr[Debug::MATHED] << "creating inset 2 with name: '" << s << "'\n";
332         return MathAtom(new MathUnknownInset(s));
333 }