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