1 /****************************************************************************
2 **
3 ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of a Qt Solutions component.
8 **
9 ** Commercial Usage
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Solutions Commercial License Agreement provided
12 ** with the Software or, alternatively, in accordance with the terms
13 ** contained in a written agreement between you and Nokia.
14 **
15 ** GNU Lesser General Public License Usage
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** General Public License version 2.1 as published by the Free Software
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** packaging of this file.  Please review the following information to
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 **
23 ** In addition, as a special exception, Nokia gives you certain
24 ** additional rights. These rights are described in the Nokia Qt LGPL
25 ** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this
26 ** package.
27 **
28 ** GNU General Public License Usage
29 ** Alternatively, this file may be used under the terms of the GNU
30 ** General Public License version 3.0 as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL included in the
32 ** packaging of this file.  Please review the following information to
33 ** ensure the GNU General Public License version 3.0 requirements will be
34 ** met: http://www.gnu.org/copyleft/gpl.html.
35 **
36 ** Please note Third Party Software included with Qt Solutions may impose
37 ** additional restrictions and it is the user's responsibility to ensure
38 ** that they have met the licensing requirements of the GPL, LGPL, or Qt
39 ** Solutions Commercial license and the relevant license of the Third
40 ** Party Software they are using.
41 **
42 ** If you are unsure which license is appropriate for your use, please
43 ** contact Nokia at qt-info@nokia.com.
44 **
45 ****************************************************************************/
46 
47 #include <QtWidgets/QApplication>
48 #include <QtCore/QString>
49 #include <QtCore/QMap>
50 #include <QtWidgets/QDesktopWidget>
51 #include <QtGui/QPainter>
52 #include <QtGui/QPaintEvent>
53 
54 #include "qtmmlwidget.h"
55 
56 // *******************************************************************
57 // Declarations
58 // *******************************************************************
59 
60 #define ROUND(a) (int)((a)+.5)
61 
62 static bool           g_draw_frames			= false;
63 static const double   g_mfrac_spacing			= 0.1;
64 static const double   g_mroot_base_margin		= 0.1;
65 static const double   g_script_size_multiplier	    	= 0.7071; // sqrt(1/2)
66 static const int      g_min_font_point_size		= 8;
67 static const QChar    g_radical_char  	    	    	= QChar(0x1A, 0x22);
68 static const unsigned g_oper_spec_rows     	        = 9;
69 
70 // use unnamed namespace
71 namespace
72 {
73 
74 struct Mml
75 {
76     enum NodeType {
77 	    NoNode = 0, MiNode, MnNode, MfracNode, MrowNode, MsqrtNode,
78 	    MrootNode, MsupNode, MsubNode, MsubsupNode, MoNode,
79 	    MstyleNode, TextNode, MphantomNode, MfencedNode,
80 	    MtableNode, MtrNode, MtdNode, MoverNode, MunderNode,
81 	    MunderoverNode, MerrorNode, MtextNode, MpaddedNode,
82 	    MspaceNode, MalignMarkNode, UnknownNode
83     };
84 
85     enum MathVariant {
86 	    NormalMV	    = 0x0000,
87 	    BoldMV  	    = 0x0001,
88 	    ItalicMV	    = 0x0002,
89 	    DoubleStruckMV  = 0x0004,
90 	    ScriptMV        = 0x0008,
91 	    FrakturMV       = 0x0010,
92 	    SansSerifMV     = 0x0020,
93 	    MonospaceMV     = 0x0040
94     };
95 
96     enum FormType { PrefixForm, InfixForm, PostfixForm };
97     enum ColAlign { ColAlignLeft, ColAlignCenter, ColAlignRight };
98     enum RowAlign { RowAlignTop, RowAlignCenter, RowAlignBottom,
99 		    RowAlignAxis, RowAlignBaseline };
100     enum FrameType { FrameNone, FrameSolid, FrameDashed };
101 
102     struct FrameSpacing {
FrameSpacing__anon1299d46a0111::Mml::FrameSpacing103 	FrameSpacing(int hor = 0, int ver = 0)
104 	    : m_hor(hor), m_ver(ver) {}
105 	int m_hor, m_ver;
106     };
107 };
108 
109 struct OperSpec {
110     enum StretchDir { NoStretch, HStretch, VStretch, HVStretch };
111 
112     const char *name;
113     Mml::FormType form;
114     const char *attributes[g_oper_spec_rows];
115     StretchDir stretch_dir;
116 };
117 
118 struct NodeSpec
119 {
120     Mml::NodeType type;
121     const char *tag;
122     const char *type_str;
123     int child_spec;
124     const char *child_types;
125     const char *attributes;
126 
127     enum ChildSpec {
128 	    ChildAny     = -1, // any number of children allowed
129 	    ChildIgnore  = -2, // do not build subexpression of children
130 	    ImplicitMrow = -3  // if more than one child, build mrow
131     };
132 };
133 
134 struct EntitySpec
135 {
136     const char *name;
137     const char *value;
138 };
139 
140 typedef QMap<QString, QString> MmlAttributeMap;
141 class MmlNode;
142 } // namespace
143 
144 class MmlDocument : public Mml
145 {
146     public:
147 	MmlDocument();
148 	~MmlDocument();
149 	void clear();
150 
151 	bool setContent(QString text, QString *errorMsg = 0,
152 			    int *errorLine = 0, int *errorColumn = 0);
153 	void paint(QPainter *p, const QPoint &pos) const;
154 	void dump() const;
155 	QSize size() const;
156 	void layout();
157 
158 	QString fontName(QtMmlWidget::MmlFont type) const;
159 	void setFontName(QtMmlWidget::MmlFont type, const QString &name);
160 
baseFontPointSize() const161 	int baseFontPointSize() const
162 	    { return m_base_font_point_size; }
setBaseFontPointSize(int size)163 	void setBaseFontPointSize(int size)
164 	    { m_base_font_point_size = size; }
foregroundColor() const165 	QColor foregroundColor() const
166 	    { return m_foreground_color; }
setForegroundColor(const QColor & color)167 	void setForegroundColor(const QColor &color)
168 	    { m_foreground_color = color; }
backgroundColor() const169 	QColor backgroundColor() const
170 	    { return m_background_color; }
setBackgroundColor(const QColor & color)171 	void setBackgroundColor(const QColor &color)
172 	    { m_background_color = color; }
173 
174     private:
175 	void _dump(const MmlNode *node, QString &indent) const;
176 	bool insertChild(MmlNode *parent, MmlNode *new_node, QString *errorMsg);
177 
178 	MmlNode *domToMml(const QDomNode &dom_node, bool *ok, QString *errorMsg);
179 	MmlNode *createNode(NodeType type, const MmlAttributeMap &mml_attr,
180 				const QString &mml_value, QString *errorMsg);
181 	MmlNode *createImplicitMrowNode(const QDomNode &dom_node, bool *ok,
182 				    QString *errorMsg);
183 
184 	void insertOperator(MmlNode *node, const QString &text);
185 
186 	MmlNode *m_root_node;
187 
188 	QString m_normal_font_name;
189 	QString m_fraktur_font_name;
190 	QString m_sans_serif_font_name;
191 	QString m_script_font_name;
192 	QString m_monospace_font_name;
193 	QString m_doublestruck_font_name;
194 	int m_base_font_point_size;
195 	QColor m_foreground_color;
196 	QColor m_background_color;
197 };
198 
199 namespace {
200 class MmlNode : public Mml
201 {
202     friend class ::MmlDocument;
203 
204     public:
205 	MmlNode(NodeType type, MmlDocument *document, const MmlAttributeMap &attribute_map);
206 	virtual ~MmlNode();
207 
208 	// Mml stuff
nodeType() const209 	NodeType nodeType() const
210 	    { return m_node_type; }
211 
212 	virtual QString toStr() const;
213 
214 	void setRelOrigin(const QPoint &rel_origin);
relOrigin() const215 	QPoint relOrigin() const
216 	    { return m_rel_origin; }
217 	void stretchTo(const QRect &rect);
isStretched() const218 	bool isStretched() const
219 	    { return m_stretched; }
220 	QPoint devicePoint(const QPoint &p) const;
221 
myRect() const222 	QRect myRect() const
223 	    { return m_my_rect; }
224 	QRect parentRect() const;
225 	virtual QRect deviceRect() const;
226 	void updateMyRect();
setMyRect(const QRect & rect)227 	virtual void setMyRect(const QRect &rect)
228 	    { m_my_rect = rect; }
229 
230 	virtual void stretch();
231 	virtual void layout();
232 	virtual void paint(QPainter *p);
233 
234 	int basePos() const;
235 	int overlinePos() const;
236 	int underlinePos() const;
237 	int em() const;
238 	int ex() const;
239 
240 	QString explicitAttribute(const QString &name, const QString &def = QString()) const;
241 	QString inheritAttributeFromMrow(const QString &name, const QString &def = QString()) const;
242 
243 	virtual QFont font() const;
244 	virtual QColor color() const;
245 	virtual QColor background() const;
246 	virtual int scriptlevel(const MmlNode *child = 0) const;
247 
248 
249 	// Node stuff
document() const250 	MmlDocument *document() const
251 	    { return m_document; }
parent() const252 	MmlNode *parent() const
253 	    { return m_parent; }
firstChild() const254 	MmlNode *firstChild() const
255 	    { return m_first_child; }
nextSibling() const256 	MmlNode *nextSibling() const
257 	    { return m_next_sibling; }
previousSibling() const258 	MmlNode *previousSibling() const
259 	    { return m_previous_sibling; }
260 	MmlNode *lastSibling() const;
261 	MmlNode *firstSibling() const;
isLastSibling() const262 	bool isLastSibling() const
263 	    { return m_next_sibling == 0; }
isFirstSibling() const264 	bool isFirstSibling() const
265 	    { return m_previous_sibling == 0; }
hasChildNodes() const266 	bool hasChildNodes() const
267 	    { return m_first_child != 0; }
268 
269     protected:
270 	virtual void layoutSymbol();
271 	virtual void paintSymbol(QPainter *p) const;
symbolRect() const272 	virtual QRect symbolRect() const
273 	    { return QRect(0, 0, 0, 0); }
274 
275 	MmlNode *parentWithExplicitAttribute(const QString &name, NodeType type = NoNode);
276 	int interpretSpacing(const QString &value, bool *ok) const;
277 
278     private:
279 	MmlAttributeMap m_attribute_map;
280 	bool m_stretched;
281 	QRect m_my_rect, m_parent_rect;
282 	QPoint m_rel_origin;
283 
284 	NodeType m_node_type;
285 	MmlDocument *m_document;
286 
287 	MmlNode *m_parent,
288 		*m_first_child,
289 		*m_next_sibling,
290 		*m_previous_sibling;
291 };
292 
293 class MmlTokenNode : public MmlNode
294 {
295     public:
MmlTokenNode(NodeType type,MmlDocument * document,const MmlAttributeMap & attribute_map)296 	MmlTokenNode(NodeType type, MmlDocument *document,
297 			const MmlAttributeMap &attribute_map)
298 	    : MmlNode(type, document, attribute_map) {}
299 
300 	QString text() const;
301 };
302 
303 class MmlMphantomNode : public MmlNode
304 {
305     public:
MmlMphantomNode(MmlDocument * document,const MmlAttributeMap & attribute_map)306 	MmlMphantomNode(MmlDocument *document,
307 			    const MmlAttributeMap &attribute_map)
308 	    : MmlNode(MphantomNode, document, attribute_map) {}
309 
paint(QPainter *)310 	virtual void paint(QPainter *) {}
311 };
312 
313 class MmlUnknownNode : public MmlNode
314 {
315     public:
MmlUnknownNode(MmlDocument * document,const MmlAttributeMap & attribute_map)316 	MmlUnknownNode(MmlDocument *document,
317 			    const MmlAttributeMap &attribute_map)
318 	    : MmlNode(UnknownNode, document, attribute_map) {}
319 };
320 
321 class MmlMfencedNode : public MmlNode
322 {
323     public:
MmlMfencedNode(MmlDocument * document,const MmlAttributeMap & attribute_map)324 	MmlMfencedNode(MmlDocument *document,
325 			    const MmlAttributeMap &attribute_map)
326 	    : MmlNode(MfencedNode, document, attribute_map) {}
327 };
328 
329 class MmlMalignMarkNode : public MmlNode
330 {
331     public:
MmlMalignMarkNode(MmlDocument * document)332 	MmlMalignMarkNode(MmlDocument *document)
333 	    : MmlNode(MalignMarkNode, document, MmlAttributeMap()) {}
334 };
335 
336 class MmlMfracNode : public MmlNode
337 {
338     public:
MmlMfracNode(MmlDocument * document,const MmlAttributeMap & attribute_map)339 	MmlMfracNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
340 	    : MmlNode(MfracNode, document, attribute_map) {}
341 
342 	MmlNode *numerator() const;
343 		MmlNode *denominator() const;
344 
345     protected:
346 	virtual void layoutSymbol();
347 	virtual void paintSymbol(QPainter *p) const;
348 	virtual QRect symbolRect() const;
349 };
350 
351 class MmlMrowNode : public MmlNode
352 {
353     public:
MmlMrowNode(MmlDocument * document,const MmlAttributeMap & attribute_map)354 	MmlMrowNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
355 		    : MmlNode(MrowNode, document, attribute_map) {}
356 };
357 
358 class MmlRootBaseNode : public MmlNode
359 {
360     public:
MmlRootBaseNode(NodeType type,MmlDocument * document,const MmlAttributeMap & attribute_map)361 	MmlRootBaseNode(NodeType type, MmlDocument *document, const MmlAttributeMap &attribute_map)
362 		: MmlNode(type, document, attribute_map) {}
363 
364 	MmlNode *base() const;
365 	MmlNode *index() const;
366 
367 	virtual int scriptlevel(const MmlNode *child = 0) const;
368 
369     protected:
370 	virtual void layoutSymbol();
371 	virtual void paintSymbol(QPainter *p) const;
372 	virtual QRect symbolRect() const;
373 	int tailWidth() const;
374 };
375 
376 class MmlMrootNode : public MmlRootBaseNode
377 {
378     public:
MmlMrootNode(MmlDocument * document,const MmlAttributeMap & attribute_map)379 	MmlMrootNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
380 		: MmlRootBaseNode(MrootNode, document, attribute_map) {}
381 };
382 
383 class MmlMsqrtNode : public MmlRootBaseNode
384 {
385     public:
MmlMsqrtNode(MmlDocument * document,const MmlAttributeMap & attribute_map)386 	MmlMsqrtNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
387 		: MmlRootBaseNode(MsqrtNode, document, attribute_map) {}
388 
389 };
390 
391 
392 class MmlTextNode : public MmlNode
393 {
394     public:
395 	MmlTextNode(const QString &text, MmlDocument *document);
396 
397 	virtual QString toStr() const;
text() const398 	QString text() const
399 	    { return m_text; }
400 
401 	// TextNodes are not xml elements, so they can't have attributes of
402 	// their own. Everything is taken from the parent.
font() const403 	virtual QFont font() const
404 	    { return parent()->font(); }
scriptlevel(const MmlNode * =0) const405 	virtual int scriptlevel(const MmlNode* = 0) const
406 	    { return parent()->scriptlevel(this); }
color() const407 	virtual QColor color() const
408 	    { return parent()->color(); }
background() const409 	virtual QColor background() const
410 	    { return parent()->background(); }
411 
412      protected:
413 	virtual void paintSymbol(QPainter *p) const;
414 	virtual QRect symbolRect() const;
415 
416 	QString m_text;
417 };
418 
419 class MmlMiNode : public MmlTokenNode
420 {
421     public:
MmlMiNode(MmlDocument * document,const MmlAttributeMap & attribute_map)422 	MmlMiNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
423 		: MmlTokenNode(MiNode, document, attribute_map) {}
424 };
425 
426 class MmlMnNode : public MmlTokenNode
427 {
428     public:
MmlMnNode(MmlDocument * document,const MmlAttributeMap & attribute_map)429 	MmlMnNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
430 		: MmlTokenNode(MnNode, document, attribute_map) {}
431 };
432 
433 class MmlSubsupBaseNode : public MmlNode
434 {
435     public:
MmlSubsupBaseNode(NodeType type,MmlDocument * document,const MmlAttributeMap & attribute_map)436 	MmlSubsupBaseNode(NodeType type, MmlDocument *document, const MmlAttributeMap &attribute_map)
437 		: MmlNode(type, document, attribute_map) {}
438 
439 	MmlNode *base() const;
440 	MmlNode *sscript() const;
441 
442 	virtual int scriptlevel(const MmlNode *child = 0) const;
443 };
444 
445 class MmlMsupNode : public MmlSubsupBaseNode
446 {
447     public:
MmlMsupNode(MmlDocument * document,const MmlAttributeMap & attribute_map)448 	MmlMsupNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
449 		: MmlSubsupBaseNode(MsupNode, document, attribute_map) {}
450 
451     protected:
452 	virtual void layoutSymbol();
453 };
454 
455 class MmlMsubNode : public MmlSubsupBaseNode
456 {
457     public:
MmlMsubNode(MmlDocument * document,const MmlAttributeMap & attribute_map)458 	MmlMsubNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
459 		: MmlSubsupBaseNode(MsubNode, document, attribute_map) {}
460 
461     protected:
462 	virtual void layoutSymbol();
463 };
464 
465 class MmlMsubsupNode : public MmlNode
466 {
467     public:
MmlMsubsupNode(MmlDocument * document,const MmlAttributeMap & attribute_map)468 	MmlMsubsupNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
469 		: MmlNode(MsubsupNode, document, attribute_map) {}
470 
471 	MmlNode *base() const;
472 	MmlNode *superscript() const;
473 	MmlNode *subscript() const;
474 
475 	virtual int scriptlevel(const MmlNode *child = 0) const;
476 
477     protected:
478 	virtual void layoutSymbol();
479 };
480 
481 class MmlMoNode : public MmlTokenNode
482 {
483     public:
484 	MmlMoNode(MmlDocument *document, const MmlAttributeMap &attribute_map);
485 
486 	QString dictionaryAttribute(const QString &name) const;
487 	virtual void stretch();
488 	virtual int lspace() const;
489 	virtual int rspace() const;
490 
491 	virtual QString toStr() const;
492 
493     protected:
494 	virtual void layoutSymbol();
495 	virtual QRect symbolRect() const;
496 
497 	virtual FormType form() const;
498 
499     private:
500 	const OperSpec *m_oper_spec;
501 };
502 
503 class MmlMstyleNode : public MmlNode
504 {
505     public:
MmlMstyleNode(MmlDocument * document,const MmlAttributeMap & attribute_map)506 	MmlMstyleNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
507 		: MmlNode(MstyleNode, document, attribute_map) {}
508 };
509 
510 class MmlTableBaseNode : public MmlNode
511 {
512     public:
MmlTableBaseNode(NodeType type,MmlDocument * document,const MmlAttributeMap & attribute_map)513 	MmlTableBaseNode(NodeType type, MmlDocument *document, const MmlAttributeMap &attribute_map)
514 		: MmlNode(type, document, attribute_map) {}
515 };
516 
517 class MmlMtableNode : public MmlTableBaseNode
518 {
519     public:
MmlMtableNode(MmlDocument * document,const MmlAttributeMap & attribute_map)520 	MmlMtableNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
521 		: MmlTableBaseNode(MtableNode, document, attribute_map) {}
522 
523 	int rowspacing() const;
524 	int columnspacing() const;
525 	int framespacing_hor() const;
526 	int framespacing_ver() const;
527 	FrameType frame() const;
528 	FrameType columnlines(int idx) const;
529 	FrameType rowlines(int idx) const;
530 
531     protected:
532 	virtual void layoutSymbol();
533 	virtual QRect symbolRect() const;
534 	virtual void paintSymbol(QPainter *p) const;
535 
536     private:
537 	struct CellSizeData
538 	{
539 	    void init(const MmlNode *first_row);
540 	    QList<int> col_widths, row_heights;
numCols__anon1299d46a0211::MmlMtableNode::CellSizeData541 	    int numCols() const { return col_widths.count(); }
numRows__anon1299d46a0211::MmlMtableNode::CellSizeData542 	    int numRows() const { return row_heights.count(); }
543 	    uint colWidthSum() const;
544 	    uint rowHeightSum() const;
545 	};
546 
547 	CellSizeData m_cell_size_data;
548 	int m_content_width, m_content_height;
549 };
550 
551 class MmlMtrNode : public MmlTableBaseNode
552 {
553     public:
MmlMtrNode(MmlDocument * document,const MmlAttributeMap & attribute_map)554 	MmlMtrNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
555 		: MmlTableBaseNode(MtrNode, document, attribute_map) {}
556     void layoutCells(const QList<int> &col_widths, int col_spc);
557 };
558 
559 class MmlMtdNode : public MmlTableBaseNode
560 {
561     public:
MmlMtdNode(MmlDocument * document,const MmlAttributeMap & attribute_map)562 	MmlMtdNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
563 		: MmlTableBaseNode(MtdNode, document, attribute_map)
564 	    { m_scriptlevel_adjust = 0; }
565 	virtual void setMyRect(const QRect &rect);
566 
567 	ColAlign columnalign();
568 	RowAlign rowalign();
569 	uint colNum();
570 	uint rowNum();
571 	virtual int scriptlevel(const MmlNode *child = 0) const;
572 
573     private:
574 	int m_scriptlevel_adjust; // added or subtracted to scriptlevel to
575 				  // make contents fit the cell
576 };
577 
578 class MmlMoverNode : public MmlNode
579 {
580     public:
MmlMoverNode(MmlDocument * document,const MmlAttributeMap & attribute_map)581 	MmlMoverNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
582 		: MmlNode(MoverNode, document, attribute_map) {}
583 	virtual int scriptlevel(const MmlNode *node = 0) const;
584 
585     protected:
586 	virtual void layoutSymbol();
587 };
588 
589 class MmlMunderNode : public MmlNode
590 {
591     public:
MmlMunderNode(MmlDocument * document,const MmlAttributeMap & attribute_map)592 	MmlMunderNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
593 		: MmlNode(MunderNode, document, attribute_map) {}
594 	virtual int scriptlevel(const MmlNode *node = 0) const;
595 
596     protected:
597 	virtual void layoutSymbol();
598 };
599 
600 class MmlMunderoverNode : public MmlNode
601 {
602     public:
MmlMunderoverNode(MmlDocument * document,const MmlAttributeMap & attribute_map)603 	MmlMunderoverNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
604 		: MmlNode(MunderoverNode, document, attribute_map) {}
605 	virtual int scriptlevel(const MmlNode *node = 0) const;
606 
607     protected:
608 	virtual void layoutSymbol();
609 };
610 
611 class MmlMerrorNode : public MmlNode
612 {
613     public:
MmlMerrorNode(MmlDocument * document,const MmlAttributeMap & attribute_map)614 	MmlMerrorNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
615 		: MmlNode(MerrorNode, document, attribute_map) {}
616 };
617 
618 class MmlMtextNode : public MmlNode
619 {
620     public:
MmlMtextNode(MmlDocument * document,const MmlAttributeMap & attribute_map)621 	MmlMtextNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
622 		: MmlNode(MtextNode, document, attribute_map) {}
623 };
624 
625 class MmlMpaddedNode : public MmlNode
626 {
627     public:
MmlMpaddedNode(MmlDocument * document,const MmlAttributeMap & attribute_map)628 	MmlMpaddedNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
629 		: MmlNode(MpaddedNode, document, attribute_map) {}
630 
631     public:
632 	int lspace() const;
633 	int width() const;
634 	int height() const;
635 	int depth() const;
636 
637     protected:
638 	int interpretSpacing(QString value, int base_value, bool *ok) const;
639 	virtual void layoutSymbol();
640 	virtual QRect symbolRect() const;
641 };
642 
643 class MmlMspaceNode : public MmlNode
644 {
645     public:
MmlMspaceNode(MmlDocument * document,const MmlAttributeMap & attribute_map)646 	MmlMspaceNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
647 		: MmlNode(MspaceNode, document, attribute_map) {}
648 };
649 }
650 
651 static const NodeSpec *mmlFindNodeSpec(Mml::NodeType type);
652 static const NodeSpec *mmlFindNodeSpec(const QString &tag);
653 static bool mmlCheckChildType(Mml::NodeType parent_type,
654 			Mml::NodeType child_type, QString *error_str);
655 static bool mmlCheckAttributes(Mml::NodeType child_type,
656 			const MmlAttributeMap &attr, QString *error_str);
657 static QString mmlDictAttribute(const QString &name, const OperSpec *spec);
658 static const OperSpec *mmlFindOperSpec(const QString &name, Mml::FormType form);
659 static int interpretSpacing(QString name, int em, int ex, bool *ok);
660 static int interpretPercentSpacing(QString value, int base, bool *ok);
661 static uint interpretMathVariant(const QString &value, bool *ok);
662 static Mml::FormType interpretForm(const QString &value, bool *ok);
663 static Mml::FrameType interpretFrameType(const QString &value_list, uint idx, bool *ok);
664 static Mml::FrameSpacing interpretFrameSpacing(const QString &value_list, int em, int ex, bool *ok);
665 static Mml::ColAlign interpretColAlign(const QString &value_list, uint colnum, bool *ok);
666 static Mml::RowAlign interpretRowAlign(const QString &value_list, uint rownum, bool *ok);
667 static Mml::FrameType interpretFrameType(const QString &value_list, uint idx, bool *ok);
668 static QFont interpretDepreciatedFontAttr(const MmlAttributeMap &font_attr, QFont &fn, int em, int ex);
669 static QFont interpretMathSize(QString value, QFont &fn, int em, int ex, bool *ok);
670 static QString interpretListAttr(const QString &value_list, int idx, const QString &def);
671 static QString rectToStr(const QRect &rect);
672 static QString entityDeclarations();
673 
674 
675 #define MML_ATT_COMMON      " class style id xref actiontype "
676 #define MML_ATT_FONTSIZE    " fontsize fontweight fontstyle fontfamily color "
677 #define MML_ATT_MATHVARIANT " mathvariant mathsize mathcolor mathbackground "
678 #define MML_ATT_FONTINFO    MML_ATT_FONTSIZE MML_ATT_MATHVARIANT
679 #define MML_ATT_OPINFO      " form fence separator lspace rspace stretchy symmetric " \
680 			    " maxsize minsize largeop movablelimits accent "
681 #define MML_ATT_SIZEINFO    " width height depth "
682 #define MML_ATT_TABLEINFO   " align rowalign columnalign columnwidth groupalign " \
683 			    " alignmentscope side rowspacing columnspacing rowlines " \
684 			    " columnlines width frame framespacing equalrows " \
685 			    " equalcolumns displaystyle "
686 #define MML_ATT_MFRAC       " bevelled numalign denomalign linethickness "
687 #define MML_ATT_MSTYLE	    MML_ATT_FONTINFO MML_ATT_OPINFO \
688 			    " scriptlevel lquote rquote linethickness displaystyle " \
689 			    " scriptsizemultiplier scriptminsize background " \
690 			    " veryverythinmathspace verythinmathspace thinmathspace " \
691 			    " mediummathspace thickmathspace verythickmathspace " \
692 			    " veryverythickmathspace open close separators " \
693 			    " subscriptshift superscriptshift accentunder tableinfo " \
694 			    " rowspan columnspan edge selection bevelled "
695 #define MML_ATT_MTABLE	    " align rowalign columnalign groupalign alignmentscope " \
696 			    " columnwidth width rowspacing columnspacing rowlines columnlines " \
697 			    " frame framespacing equalrows equalcolumns displaystyle side " \
698 			    " minlabelspacing "
699 
700 static const NodeSpec g_node_spec_data[] = {
701 
702 //  	type	                tag             type_str            child_spec              child_types              attributes ""=none, 0=any
703 //      ----------------------- --------------- ------------------- ----------------------- ------------------------ ------------------------------------
704     {	Mml::MiNode,	    	"mi",	    	"MiNode",   	    NodeSpec::ChildAny,      " TextNode MalignMark ", MML_ATT_COMMON MML_ATT_FONTINFO     },
705     {	Mml::MnNode,	    	"mn",	    	"MnNode",   	    NodeSpec::ChildAny,      " TextNode MalignMark ", MML_ATT_COMMON MML_ATT_FONTINFO     },
706     {	Mml::MfracNode,   	"mfrac",    	"MfracNode",	    2,   		    0,                       MML_ATT_COMMON MML_ATT_MFRAC         },
707     {	Mml::MrowNode,    	"mrow",     	"MrowNode", 	    NodeSpec::ChildAny,     0,                       MML_ATT_COMMON " display mode "      },
708     {	Mml::MsqrtNode,   	"msqrt",    	"MsqrtNode",	    NodeSpec::ImplicitMrow, 0,                       MML_ATT_COMMON                      },
709     {	Mml::MrootNode,   	"mroot",    	"MrootNode",	    2,   		    0,                       MML_ATT_COMMON                       },
710     {	Mml::MsupNode,    	"msup",     	"MsupNode", 	    2,	    	    	    0,                       MML_ATT_COMMON " subscriptshift "    },
711     {	Mml::MsubNode,    	"msub",     	"MsubNode", 	    2,	    	    	    0,                       MML_ATT_COMMON " superscriptshift "  },
712     {	Mml::MsubsupNode, 	"msubsup",  	"MsubsupNode",	    3,	    	    	    0,                       MML_ATT_COMMON " subscriptshift superscriptshift " },
713     {	Mml::MoNode,	    	"mo",	    	"MoNode",   	    NodeSpec::ChildAny,     " TextNode MalignMark ", MML_ATT_COMMON MML_ATT_FONTINFO MML_ATT_OPINFO    },
714     {	Mml::MstyleNode,  	"mstyle",   	"MstyleNode",	    NodeSpec::ImplicitMrow, 0,                       MML_ATT_COMMON MML_ATT_MSTYLE       },
715     {	Mml::MphantomNode,  	"mphantom",   	"MphantomNode",	    NodeSpec::ImplicitMrow, 0,                       MML_ATT_COMMON         	    	  },
716     {	Mml::MalignMarkNode,	"malignmark",	"MalignMarkNode",   0,	    	    	    0,	    	             ""	    	    	    	         },
717     {	Mml::MfencedNode,	"mfenced",	"MfencedNode",      NodeSpec::ChildAny,	    0,	    	             MML_ATT_COMMON " open close separators "	        },
718     {	Mml::MtableNode,  	"mtable",   	"MtableNode",	    NodeSpec::ChildAny,	    " MtrNode ",    	     MML_ATT_COMMON MML_ATT_MTABLE  	 },
719     {	Mml::MtrNode,  	        "mtr",   	"MtrNode",	    NodeSpec::ChildAny,	    " MtdNode ",    	     MML_ATT_COMMON " rowalign columnalign groupalign " },
720     {	Mml::MtdNode,  	        "mtd",   	"MtdNode",	    NodeSpec::ImplicitMrow, 0,    	     	     MML_ATT_COMMON " rowspan columnspan rowalign columnalign groupalign " },
721     {	Mml::MoverNode,  	"mover",   	"MoverNode",	    2,	    	    	    0,    	     	     MML_ATT_COMMON " accent "	    	 },
722     {	Mml::MunderNode,  	"munder",   	"MunderNode",	    2,	    	    	    0,    	     	     MML_ATT_COMMON " accentunder "	 },
723     {	Mml::MunderoverNode,    "munderover",   "MunderoverNode",   3,	    	    	    0,    	     	     MML_ATT_COMMON " accentunder accent " },
724     {	Mml::MerrorNode,  	"merror",   	"MerrorNode",	    NodeSpec::ImplicitMrow, 0,                       MML_ATT_COMMON 	    	    	 },
725     {	Mml::MtextNode,  	"mtext",   	"MtextNode",	    1,	    	    	    " TextNode ",            MML_ATT_COMMON " width height depth linebreak " },
726     {	Mml::MpaddedNode,  	"mpadded",   	"MpaddedNode",	    NodeSpec::ImplicitMrow, 0,                       MML_ATT_COMMON " width height depth lspace " },
727     {	Mml::MspaceNode,  	"mspace",   	"MspaceNode",	    NodeSpec::ImplicitMrow, 0,                       MML_ATT_COMMON " width height depth linebreak " },
728     {	Mml::TextNode,    	0,  	    	"TextNode", 	    NodeSpec::ChildIgnore,  0,                       ""                                  },
729     {	Mml::UnknownNode,	0,	      	"UnknownNode",      NodeSpec::ChildAny,     0,                       0         	    	    	         },
730     {	Mml::NoNode,	    	0,	      	0,  	    	    0,       	            0,                       0         	    	    	         }
731 };
732 
733 static const char *g_oper_spec_names[g_oper_spec_rows] = {                          	     "accent",                 "fence",               "largeop",                "lspace",               "minsize",         "movablelimits",                "rspace",             "separator",              "stretchy"	    /* stretchdir */ };
734 static const OperSpec g_oper_spec_data[] = {
735 
736 	{ "!!"		    	    	,		Mml::PostfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "!!"
737 	{ "!"		    	    	,		Mml::PostfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "!"
738 	{ "!="		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "!="
739 	{ "&And;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,       "mediummathspace",			0,			 0,	  "mediummathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&And;"
740 	{ "&ApplyFunction;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "&ApplyFunction;"
741 	{ "&Assign;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Assign;"
742 	{ "&Backslash;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	 "thinmathspace",			0,			 0,	    "thinmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&Backslash;"
743 	{ "&Because;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Because;"
744 	{ "&Breve;"		    	,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "&Breve;"
745 	{ "&Cap;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	 "thinmathspace",			0,			 0,	    "thinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Cap;"
746 	{ "&CapitalDifferentialD;"       ,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,	"verythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // &CapitalDifferentialD;"
747 	{ "&Cedilla;"		    	,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "&Cedilla;"
748 	{ "&CenterDot;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	 "thinmathspace",			0,			 0,	    "thinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&CenterDot;"
749 	{ "&CircleDot;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&CircleDot;"
750 	{ "&CircleMinus;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	 "thinmathspace",			0,			 0,	    "thinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&CircleMinus;"
751 	{ "&CirclePlus;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	 "thinmathspace",			0,			 0,	    "thinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&CirclePlus;"
752 	{ "&CircleTimes;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	 "thinmathspace",			0,			 0,	    "thinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&CircleTimes;"
753 	{ "&ClockwiseContourIntegral;"   ,		 Mml::PrefixForm, {			    0,  		     0, 		 "true",		   "0em",			0,			 0,		      "0em",			   0,			"true"},            OperSpec::VStretch }, // &ClockwiseContourIntegral;"
754 	{ "&CloseCurlyDoubleQuote;"      ,		Mml::PostfixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // &CloseCurlyDoubleQuote;"
755 	{ "&CloseCurlyQuote;"		,		Mml::PostfixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "&CloseCurlyQuote;"
756 	{ "&Colon;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Colon;"
757 	{ "&Congruent;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Congruent;"
758 	{ "&ContourIntegral;"		,		 Mml::PrefixForm, {			    0,  		     0, 		 "true",		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // "&ContourIntegral;"
759 	{ "&Coproduct;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	 "thinmathspace",			0,			 0,	    "thinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Coproduct;"
760 	{ "&CounterClockwiseContourIntegral;",		 Mml::PrefixForm, {		            0,  		     0, 		 "true",		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // &CounterClockwiseContourInteg
761 	{ "&Cross;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Cross;"
762 	{ "&Cup;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	 "thinmathspace",			0,			 0,	    "thinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Cup;"
763 	{ "&CupCap;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&CupCap;"
764 	{ "&Del;"		    	,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,	"verythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Del;"
765 	{ "&DiacriticalAcute;"		,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "&DiacriticalAcute;"
766 	{ "&DiacriticalDot;"		,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "&DiacriticalDot;"
767 	{ "&DiacriticalDoubleAcute;" 	,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // &DiacriticalDoubleAcute;"
768 	{ "&DiacriticalGrave;"		,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "&DiacriticalGrave;"
769 	{ "&DiacriticalLeftArrow;"   	,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::HStretch }, // &DiacriticalLeftArrow;"
770 	{ "&DiacriticalLeftRightArrow;"  ,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::HStretch }, // &DiacriticalLeftRightArrow;"
771 	{ "&DiacriticalLeftRightVector;" ,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::HStretch }, // &DiacriticalLeftRightVector;"
772 	{ "&DiacriticalLeftVector;"      ,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::HStretch }, // &DiacriticalLeftVector;"
773 	{ "&DiacriticalRightArrow;"  	,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::HStretch }, // &DiacriticalRightArrow;"
774 	{ "&DiacriticalRightVector;" 	,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::HStretch }, // &DiacriticalRightVector;"
775 	{ "&DiacriticalTilde;"		,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },           OperSpec::NoStretch }, // "&DiacriticalTilde;"
776 	{ "&Diamond;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	 "thinmathspace",			0,			 0,	    "thinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Diamond;"
777 	{ "&DifferentialD;"		,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,	"verythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&DifferentialD;"
778 	{ "&DotEqual;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&DotEqual;"
779 	{ "&DoubleContourIntegral;"      ,		 Mml::PrefixForm, {			    0,  		     0, 		 "true",		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // &DoubleContourIntegral;"
780 	{ "&DoubleDot;"		    	,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "&DoubleDot;"
781 	{ "&DoubleDownArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&DoubleDownArrow;"
782 	{ "&DoubleLeftArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&DoubleLeftArrow;"
783 	{ "&DoubleLeftRightArrow;"       ,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // &DoubleLeftRightArrow;"
784 	{ "&DoubleLeftTee;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&DoubleLeftTee;"
785 	{ "&DoubleLongLeftArrow;"	,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&DoubleLongLeftArrow;"
786 	{ "&DoubleLongLeftRightArrow;"	,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::HStretch }, // &DoubleLongLeftRightArrow;"
787 	{ "&DoubleLongRightArrow;"       ,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::HStretch }, // &DoubleLongRightArrow;"
788 	{ "&DoubleRightArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&DoubleRightArrow;"
789 	{ "&DoubleRightTee;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&DoubleRightTee;"
790 	{ "&DoubleUpArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&DoubleUpArrow;"
791 	{ "&DoubleUpDownArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&DoubleUpDownArrow;"
792 	{ "&DoubleVerticalBar;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&DoubleVerticalBar;"
793 	{ "&DownArrow;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&DownArrow;"
794 	{ "&DownArrowBar;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&DownArrowBar;"
795 	{ "&DownArrowUpArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&DownArrowUpArrow;"
796 	{ "&DownBreve;"		    	,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "&DownBreve;"
797 	{ "&DownLeftRightVector;"	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&DownLeftRightVector;"
798 	{ "&DownLeftTeeVector;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&DownLeftTeeVector;"
799 	{ "&DownLeftVector;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&DownLeftVector;"
800 	{ "&DownLeftVectorBar;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&DownLeftVectorBar;"
801 	{ "&DownRightTeeVector;"	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&DownRightTeeVector;"
802 	{ "&DownRightVector;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&DownRightVector;"
803 	{ "&DownRightVectorBar;"	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&DownRightVectorBar;"
804 	{ "&DownTee;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&DownTee;"
805 	{ "&DownTeeArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&DownTeeArrow;"
806 	{ "&Element;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Element;"
807 	{ "&Equal;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Equal;"
808 	{ "&EqualTilde;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&EqualTilde;"
809 	{ "&Equilibrium;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&Equilibrium;"
810 	{ "&Exists;"		    	,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Exists;"
811 	{ "&ForAll;"		    	,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&ForAll;"
812 	{ "&GreaterEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&GreaterEqual;"
813 	{ "&GreaterEqualLess;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&GreaterEqualLess;"
814 	{ "&GreaterFullEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&GreaterFullEqual;"
815 	{ "&GreaterGreater;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&GreaterGreater;"
816 	{ "&GreaterLess;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&GreaterLess;"
817 	{ "&GreaterSlantEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&GreaterSlantEqual;"
818 	{ "&GreaterTilde;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&GreaterTilde;"
819 	{ "&Hacek;"		    	,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },           OperSpec::NoStretch }, // "&Hacek;"
820 	{ "&Hat;"		    	,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::HStretch }, // "&Hat;"
821 	{ "&HorizontalLine;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,		   "0em",		      "0",			 0,		      "0em",			   0,		       "true" },            OperSpec::HStretch }, // "&HorizontalLine;"
822 	{ "&HumpDownHump;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&HumpDownHump;"
823 	{ "&HumpEqual;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&HumpEqual;"
824 	{ "&Implies;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&Implies;"
825 	{ "&Integral;"		    	,		 Mml::PrefixForm, {			    0,  		     0, 		 "true",		   "0em",			0,			 0,		      "0em",			   0,		            0 },           OperSpec::NoStretch }, // "&Integral;"
826 	{ "&Intersection;"		,		 Mml::PrefixForm, {			    0,  		     0, 		 "true",		   "0em",			0,		    "true",	    "thinmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&Intersection;"
827 	{ "&InvisibleComma;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,		      "0em",		      "true",			    0 },           OperSpec::NoStretch }, // "&InvisibleComma;"
828 	{ "&InvisibleTimes;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "&InvisibleTimes;"
829 	{ "&LeftAngleBracket;"		,		 Mml::PrefixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // "&LeftAngleBracket;"
830 	{ "&LeftArrow;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&LeftArrow;"
831 	{ "&LeftArrowBar;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&LeftArrowBar;"
832 	{ "&LeftArrowRightArrow;"	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&LeftArrowRightArrow;"
833 	{ "&LeftBracketingBar;"		,		 Mml::PrefixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // "&LeftBracketingBar;"
834 	{ "&LeftCeiling;"		,		 Mml::PrefixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // "&LeftCeiling;"
835 	{ "&LeftDoubleBracket;"		,		 Mml::PrefixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::HStretch }, // "&LeftDoubleBracket;"
836 	{ "&LeftDoubleBracketingBar;"    ,		 Mml::PrefixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::HStretch }, // &LeftDoubleBracketingBar;"
837 	{ "&LeftDownTeeVector;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&LeftDownTeeVector;"
838 	{ "&LeftDownVector;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&LeftDownVector;"
839 	{ "&LeftDownVectorBar;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&LeftDownVectorBar;"
840 	{ "&LeftFloor;"		    	,		 Mml::PrefixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // "&LeftFloor;"
841 	{ "&LeftRightArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&LeftRightArrow;"
842 	{ "&LeftRightVector;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&LeftRightVector;"
843 	{ "&LeftSkeleton;"		,		 Mml::PrefixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "&LeftSkeleton;"
844 	{ "&LeftTee;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&LeftTee;"
845 	{ "&LeftTeeArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&LeftTeeArrow;"
846 	{ "&LeftTeeVector;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&LeftTeeVector;"
847 	{ "&LeftTriangle;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&LeftTriangle;"
848 	{ "&LeftTriangleBar;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&LeftTriangleBar;"
849 	{ "&LeftTriangleEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&LeftTriangleEqual;"
850 	{ "&LeftUpDownVector;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&LeftUpDownVector;"
851 	{ "&LeftUpTeeVector;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&LeftUpTeeVector;"
852 	{ "&LeftUpVector;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&LeftUpVector;"
853 	{ "&LeftUpVectorBar;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&LeftUpVectorBar;"
854 	{ "&LeftVector;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&LeftVector;"
855 	{ "&LeftVectorBar;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&LeftVectorBar;"
856 	{ "&LessEqualGreater;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&LessEqualGreater;"
857 	{ "&LessFullEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&LessFullEqual;"
858 	{ "&LessGreater;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&LessGreater;"
859 	{ "&LessLess;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&LessLess;"
860 	{ "&LessSlantEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&LessSlantEqual;"
861 	{ "&LessTilde;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&LessTilde;"
862 	{ "&LongLeftArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&LongLeftArrow;"
863 	{ "&LongLeftRightArrow;"    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&LongLeftRightArrow;"
864 	{ "&LongRightArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&LongRightArrow;"
865 	{ "&LowerLeftArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&LowerLeftArrow;"
866 	{ "&LowerRightArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&LowerRightArrow;"
867 	{ "&MinusPlus;"		    	,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0, "veryverythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&MinusPlus;"
868 	{ "&NestedGreaterGreater;"       ,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // &NestedGreaterGreater;"
869 	{ "&NestedLessLess;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NestedLessLess;"
870 	{ "&Not;"		    	,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Not;"
871 	{ "&NotCongruent;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotCongruent;"
872 	{ "&NotCupCap;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotCupCap;"
873 	{ "&NotDoubleVerticalBar;"       ,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // &NotDoubleVerticalBar;"
874 	{ "&NotElement;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotElement;"
875 	{ "&NotEqual;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotEqual;"
876 	{ "&NotEqualTilde;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotEqualTilde;"
877 	{ "&NotExists;"		    	,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotExists;"
878 	{ "&NotGreater;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotGreater;"
879 	{ "&NotGreaterEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotGreaterEqual;"
880 	{ "&NotGreaterFullEqual;"	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotGreaterFullEqual;"
881 	{ "&NotGreaterGreater;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotGreaterGreater;"
882 	{ "&NotGreaterLess;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotGreaterLess;"
883 	{ "&NotGreaterSlantEqual;"       ,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // &NotGreaterSlantEqual;"
884 	{ "&NotGreaterTilde;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotGreaterTilde;"
885 	{ "&NotHumpDownHump;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotHumpDownHump;"
886 	{ "&NotHumpEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotHumpEqual;"
887 	{ "&NotLeftTriangle;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotLeftTriangle;"
888 	{ "&NotLeftTriangleBar;"	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotLeftTriangleBar;"
889 	{ "&NotLeftTriangleEqual;"       ,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // &NotLeftTriangleEqual;"
890 	{ "&NotLess;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotLess;"
891 	{ "&NotLessEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotLessEqual;"
892 	{ "&NotLessFullEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotLessFullEqual;"
893 	{ "&NotLessGreater;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotLessGreater;"
894 	{ "&NotLessLess;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotLessLess;"
895 	{ "&NotLessSlantEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotLessSlantEqual;"
896 	{ "&NotLessTilde;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotLessTilde;"
897 	{ "&NotNestedGreaterGreater;"    ,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // &NotNestedGreaterGreater;"
898 	{ "&NotNestedLessLess;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotNestedLessLess;"
899 	{ "&NotPrecedes;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotPrecedes;"
900 	{ "&NotPrecedesEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotPrecedesEqual;"
901 	{ "&NotPrecedesSlantEqual;"      ,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // &NotPrecedesSlantEqual;"
902 	{ "&NotPrecedesTilde;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotPrecedesTilde;"
903 	{ "&NotReverseElement;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotReverseElement;"
904 	{ "&NotRightTriangle;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotRightTriangle;"
905 	{ "&NotRightTriangleBar;"   	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotRightTriangleBar;"
906 	{ "&NotRightTriangleEqual;"  	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // &NotRightTriangleEqual;"
907 	{ "&NotSquareSubset;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotSquareSubset;"
908 	{ "&NotSquareSubsetEqual;"   	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // &NotSquareSubsetEqual;"
909 	{ "&NotSquareSuperset;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotSquareSuperset;"
910 	{ "&NotSquareSupersetEqual;"     ,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // &NotSquareSupersetEqual;"
911 	{ "&NotSubset;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotSubset;"
912 	{ "&NotSubsetEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotSubsetEqual;"
913 	{ "&NotSucceeds;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotSucceeds;"
914 	{ "&NotSucceedsEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotSucceedsEqual;"
915 	{ "&NotSucceedsSlantEqual;"      ,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // &NotSucceedsSlantEqual;"
916 	{ "&NotSucceedsTilde;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotSucceedsTilde;"
917 	{ "&NotSuperset;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotSuperset;"
918 	{ "&NotSupersetEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotSupersetEqual;"
919 	{ "&NotTilde;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotTilde;"
920 	{ "&NotTildeEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotTildeEqual;"
921 	{ "&NotTildeFullEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotTildeFullEqual;"
922 	{ "&NotTildeTilde;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotTildeTilde;"
923 	{ "&NotVerticalBar;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&NotVerticalBar;"
924 	{ "&OpenCurlyDoubleQuote;"       ,		 Mml::PrefixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // &OpenCurlyDoubleQuote;"
925 	{ "&OpenCurlyQuote;"		,		 Mml::PrefixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "&OpenCurlyQuote;"
926 	{ "&Or;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,       "mediummathspace",			0,			 0,	  "mediummathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&Or;"
927 	{ "&OverBar;"		    	,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::HStretch }, // "&OverBar;"
928 	{ "&OverBrace;"		    	,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::HStretch }, // "&OverBrace;"
929 	{ "&OverBracket;"		,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::HStretch }, // "&OverBracket;"
930 	{ "&OverParenthesis;"		,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // "&OverParenthesis;"
931 	{ "&PartialD;"		    	,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,	"verythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&PartialD;"
932 	{ "&PlusMinus;"		    	,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0, "veryverythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&PlusMinus;"
933 	{ "&Precedes;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Precedes;"
934 	{ "&PrecedesEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&PrecedesEqual;"
935 	{ "&PrecedesSlantEqual;"	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&PrecedesSlantEqual;"
936 	{ "&PrecedesTilde;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&PrecedesTilde;"
937 	{ "&Product;"		    	,		 Mml::PrefixForm, {			    0,  		     0, 		 "true",		   "0em",			0,		    "true",	    "thinmathspace",			   0,		            0 },           OperSpec::NoStretch }, // "&Product;"
938 	{ "&Proportion;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Proportion;"
939 	{ "&Proportional;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Proportional;"
940 	{ "&ReverseElement;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&ReverseElement;"
941 	{ "&ReverseEquilibrium;"	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&ReverseEquilibrium;"
942 	{ "&ReverseUpEquilibrium;"   	,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::HStretch }, // &ReverseUpEquilibrium;"
943 	{ "&RightAngleBracket;"		,		Mml::PostfixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // "&RightAngleBracket;"
944 	{ "&RightArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&RightArrow;"
945 	{ "&RightArrowBar;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&RightArrowBar;"
946 	{ "&RightArrowLeftArrow;"	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&RightArrowLeftArrow;"
947 	{ "&RightBracketingBar;"	,		Mml::PostfixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // "&RightBracketingBar;"
948 	{ "&RightCeiling;"		,		Mml::PostfixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // "&RightCeiling;"
949 	{ "&RightDoubleBracket;"	,		Mml::PostfixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // "&RightDoubleBracket;"
950 	{ "&RightDoubleBracketingBar;"   ,		Mml::PostfixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::HStretch }, // &RightDoubleBracketingBar;"
951 	{ "&RightDownTeeVector;"	,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&RightDownTeeVector;"
952 	{ "&RightDownVector;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&RightDownVector;"
953 	{ "&RightDownVectorBar;"	,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&RightDownVectorBar;"
954 	{ "&RightFloor;"		,		Mml::PostfixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // "&RightFloor;"
955 	{ "&RightSkeleton;"		,		Mml::PostfixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "&RightSkeleton;"
956 	{ "&RightTee;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&RightTee;"
957 	{ "&RightTeeArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&RightTeeArrow;"
958 	{ "&RightTeeVector;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&RightTeeVector;"
959 	{ "&RightTriangle;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&RightTriangle;"
960 	{ "&RightTriangleBar;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&RightTriangleBar;"
961 	{ "&RightTriangleEqual;"	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&RightTriangleEqual;"
962 	{ "&RightUpDownVector;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&RightUpDownVector;"
963 	{ "&RightUpTeeVector;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&RightUpTeeVector;"
964 	{ "&RightUpVector;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&RightUpVector;"
965 	{ "&RightUpVectorBar;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&RightUpVectorBar;"
966 	{ "&RightVector;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&RightVector;"
967 	{ "&RightVectorBar;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::HStretch }, // "&RightVectorBar;"
968 	{ "&RoundImplies;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&RoundImplies;"
969 	{ "&ShortDownArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&ShortDownArrow;"
970 	{ "&ShortLeftArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },            OperSpec::HStretch }, // "&ShortLeftArrow;"
971 	{ "&ShortRightArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },            OperSpec::HStretch }, // "&ShortRightArrow;"
972 	{ "&ShortUpArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,			    0 },            OperSpec::VStretch }, // "&ShortUpArrow;"
973 	{ "&SmallCircle;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&SmallCircle;"
974 	{ "&Sqrt;"		    	,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&Sqrt;"
975 	{ "&Square;"		    	,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,	"verythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Square;"
976 	{ "&SquareIntersection;"	,		  Mml::InfixForm, {			    0,  		     0, 		      0,       "mediummathspace",			0,			 0,	  "mediummathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&SquareIntersection;"
977 	{ "&SquareSubset;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&SquareSubset;"
978 	{ "&SquareSubsetEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&SquareSubsetEqual;"
979 	{ "&SquareSuperset;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&SquareSuperset;"
980 	{ "&SquareSupersetEqual;"	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&SquareSupersetEqual;"
981 	{ "&SquareUnion;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,       "mediummathspace",			0,			 0,	  "mediummathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&SquareUnion;"
982 	{ "&Star;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	 "thinmathspace",			0,			 0,	    "thinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Star;"
983 	{ "&Subset;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Subset;"
984 	{ "&SubsetEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&SubsetEqual;"
985 	{ "&Succeeds;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Succeeds;"
986 	{ "&SucceedsEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&SucceedsEqual;"
987 	{ "&SucceedsSlantEqual;"	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&SucceedsSlantEqual;"
988 	{ "&SucceedsTilde;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&SucceedsTilde;"
989 	{ "&SuchThat;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&SuchThat;"
990 	{ "&Sum;"		    	,		 Mml::PrefixForm, {			    0,  		     0, 		 "true",		   "0em",			0,		    "true",	    "thinmathspace",			   0,		            0 },           OperSpec::NoStretch }, // "&Sum;"
991 	{ "&Superset;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Superset;"
992 	{ "&SupersetEqual;"		,   	    	  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&SupersetEqual;"
993 	{ "&Therefore;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Therefore;"
994 	{ "&Tilde;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Tilde;"
995 	{ "&TildeEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&TildeEqual;"
996 	{ "&TildeFullEqual;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&TildeFullEqual;"
997 	{ "&TildeTilde;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&TildeTilde;"
998 	{ "&TripleDot;"		    	,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "&TripleDot;"
999 	{ "&UnderBar;"		    	,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::HStretch }, // "&UnderBar;"
1000 	{ "&UnderBrace;"		,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::HStretch }, // "&UnderBrace;"
1001 	{ "&UnderBracket;"		,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },           OperSpec::HStretch }, // "&UnderBracket;"
1002 	{ "&UnderParenthesis;"		,		Mml::PostfixForm, {		       "true",  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::HStretch }, // "&UnderParenthesis;"
1003 	{ "&Union;"		    	,		 Mml::PrefixForm, {			    0,  		     0, 		 "true",		   "0em",			0,		    "true",	    "thinmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&Union;"
1004 	{ "&UnionPlus;"		    	,		 Mml::PrefixForm, {			    0,  		     0, 		 "true",		   "0em",			0,		    "true",	    "thinmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&UnionPlus;"
1005 	{ "&UpArrow;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&UpArrow;"
1006 	{ "&UpArrowBar;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&UpArrowBar;"
1007 	{ "&UpArrowDownArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&UpArrowDownArrow;"
1008 	{ "&UpDownArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&UpDownArrow;"
1009 	{ "&UpEquilibrium;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&UpEquilibrium;"
1010 	{ "&UpTee;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&UpTee;"
1011 	{ "&UpTeeArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&UpTeeArrow;"
1012 	{ "&UpperLeftArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&UpperLeftArrow;"
1013 	{ "&UpperRightArrow;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },           OperSpec::HVStretch }, // "&UpperRightArrow;"
1014 	{ "&Vee;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	 "thinmathspace",			0,			 0,	    "thinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Vee;"
1015 	{ "&VerticalBar;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&VerticalBar;"
1016 	{ "&VerticalLine;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,		   "0em",		      "0",			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // "&VerticalLine;"
1017 	{ "&VerticalSeparator;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "&VerticalSeparator;"
1018 	{ "&VerticalTilde;"		,		  Mml::InfixForm, {			    0,  		     0, 		      0,	 "thinmathspace",			0,			 0,	    "thinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&VerticalTilde;"
1019 	{ "&Wedge;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	 "thinmathspace",			0,			 0,	    "thinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&Wedge;"
1020 	{ "&amp;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&amp;"
1021 	{ "&amp;&amp;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&amp;&amp;"
1022 	{ "&le;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&le;"
1023 	{ "&lt;"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&lt;"
1024 	{ "&lt;="		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&lt;="
1025 	{ "&lt;>"		    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "&lt;>"
1026 	{ "'"		    	    	,		Mml::PostfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "'"
1027 	{ "("		    	    	,		 Mml::PrefixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // "("
1028 	{ ")"		    	    	,		Mml::PostfixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // ")"
1029 	{ "*"		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	 "thinmathspace",			0,			 0,	    "thinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "*"
1030 	{ "**"		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "**"
1031 	{ "*="		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "*="
1032 	{ "+"		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "+"
1033 	{ "+"		    	    	,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0, "veryverythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "+"
1034 	{ "++"		    	    	,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,	"verythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "++"
1035 	{ "+="		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "+="
1036 	{ ","		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,    "verythickmathspace",		      "true",			    0 },           OperSpec::NoStretch }, // ","
1037 	{ "-"		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "-"
1038 	{ "-"		    	    	,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0, "veryverythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "-"
1039 	{ "--"		    	    	,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,	"verythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, //   "--"
1040 	{ "-="		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "-="
1041 	{ "->"		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "->"
1042 	{ "."		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "."
1043 	{ ".."		    	    	,		Mml::PostfixForm, {			    0,  		     0, 		      0,       "mediummathspace",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // ".."
1044 	{ "..."		    	    	,		Mml::PostfixForm, {			    0,  		     0, 		      0,       "mediummathspace",			0,			 0,		      "0em",			   0,			    0 },           OperSpec::NoStretch }, // "..."
1045 	{ "/"		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	 "thinmathspace",			0,			 0,	    "thinmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "/"
1046 	{ "//"		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "//"
1047 	{ "/="		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "/="
1048 	{ ":"		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // ":"
1049 	{ ":="		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // ":="
1050 	{ ";"		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,    "verythickmathspace",		      "true",			    0 },           OperSpec::NoStretch }, // ";"
1051 	{ ";"		    	    	,		Mml::PostfixForm, {			    0,  		     0, 		      0,		   "0em",			0,			 0,		      "0em",		      "true",			    0 },           OperSpec::NoStretch }, // ";"
1052 	{ "="		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "="
1053 	{ "=="		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "=="
1054 	{ ">"		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // ">"
1055 	{ ">="		                ,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,			    0 },           OperSpec::NoStretch }, // ">="
1056 	{ "?"		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "?"
1057 	{ "@"		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "@"
1058 	{ "["		    	    	,		 Mml::PrefixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // "["
1059 	{ "]"		    	    	,		Mml::PostfixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // "]"
1060 	{ "^"		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "^"
1061 	{ "_"		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "_"
1062 	{ "lim"		    	    	,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,		    "true",	    "thinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "lim"
1063 	{ "max"		    	    	,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,		    "true",	    "thinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "max"
1064 	{ "min"		    	    	,		 Mml::PrefixForm, {			    0,  		     0, 		      0,		   "0em",			0,		    "true",	    "thinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "min"
1065 	{ "{"              		,		 Mml::PrefixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // "{"
1066 	{ "|"		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,	"thickmathspace",			0,			 0,	   "thickmathspace",			   0,		       "true" },            OperSpec::VStretch }, // "|"
1067 	{ "||"		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,       "mediummathspace",			0,			 0,	  "mediummathspace",			   0,			    0 },           OperSpec::NoStretch }, // "||"
1068 	{ "}"		    	    	,		Mml::PostfixForm, {			    0,  		"true", 		      0,		   "0em",			0,			 0,		      "0em",			   0,		       "true" },            OperSpec::VStretch }, // "}"
1069 	{ "~"		    	    	,		  Mml::InfixForm, {			    0,  		     0, 		      0,     "verythinmathspace",			0,			 0,	"verythinmathspace",			   0,			    0 },           OperSpec::NoStretch }, // "~"
1070 
1071 	{  0                            ,                 Mml::InfixForm, { 	    	            0,                       0,                       0,            	       0,                     	0, 		         0, 	    	    	  0,                 	   0, 	              	    0 },           OperSpec::NoStretch }
1072 };
1073 
1074 static const OperSpec g_oper_spec_defaults =
1075 	{  0                            ,                 Mml::InfixForm, { 	    	      "false",                 "false",                 "false",         "thickmathspace",                     "1", 		   "false", 	   "thickmathspace",                 "false", 	              "false" },           OperSpec::NoStretch  };
1076 
1077 static const uint g_oper_spec_count = sizeof(g_oper_spec_data)/sizeof(OperSpec) - 1;
1078 
1079 static const EntitySpec g_xml_entity_data[] = {
1080     { "angzarr",	"&#x0237C;" },
1081     { "cirmid",	"&#x02AEF;" },
1082     { "cudarrl",	"&#x02938;" },
1083     { "cudarrr",	"&#x02935;" },
1084     { "cularr",	"&#x021B6;" },
1085     { "cularrp",	"&#x0293D;" },
1086     { "curarr",	"&#x021B7;" },
1087     { "curarrm",	"&#x0293C;" },
1088     { "Darr",	"&#x021A1;" },
1089     { "dArr",	"&#x021D3;" },
1090     { "ddarr",	"&#x021CA;" },
1091     { "DDotrahd",	"&#x02911;" },
1092     { "dfisht",	"&#x0297F;" },
1093     { "dHar",	"&#x02965;" },
1094     { "dharl",	"&#x021C3;" },
1095     { "dharr",	"&#x021C2;" },
1096     { "duarr",	"&#x021F5;" },
1097     { "duhar",	"&#x0296F;" },
1098     { "dzigrarr",	"&#x027FF;" },
1099     { "erarr",	"&#x02971;" },
1100     { "hArr",	"&#x021D4;" },
1101     { "harr",	"&#x02194;" },
1102     { "harrcir",	"&#x02948;" },
1103     { "harrw",	"&#x021AD;" },
1104     { "hoarr",	"&#x021FF;" },
1105     { "imof",	"&#x022B7;" },
1106     { "lAarr",	"&#x021DA;" },
1107     { "Larr",	"&#x0219E;" },
1108     { "larrbfs",	"&#x0291F;" },
1109     { "larrfs",	"&#x0291D;" },
1110     { "larrhk",	"&#x021A9;" },
1111     { "larrlp",	"&#x021AB;" },
1112     { "larrpl",	"&#x02939;" },
1113     { "larrsim",	"&#x02973;" },
1114     { "larrtl",	"&#x021A2;" },
1115     { "lAtail",	"&#x0291B;" },
1116     { "latail",	"&#x02919;" },
1117     { "lBarr",	"&#x0290E;" },
1118     { "lbarr",	"&#x0290C;" },
1119     { "ldca",	"&#x02936;" },
1120     { "ldrdhar",	"&#x02967;" },
1121     { "ldrushar",	"&#x0294B;" },
1122     { "ldsh",	"&#x021B2;" },
1123     { "lfisht",	"&#x0297C;" },
1124     { "lHar",	"&#x02962;" },
1125     { "lhard",	"&#x021BD;" },
1126     { "lharu",	"&#x021BC;" },
1127     { "lharul",	"&#x0296A;" },
1128     { "llarr",	"&#x021C7;" },
1129     { "llhard",	"&#x0296B;" },
1130     { "loarr",	"&#x021FD;" },
1131     { "lrarr",	"&#x021C6;" },
1132     { "lrhar",	"&#x021CB;" },
1133     { "lrhard",	"&#x0296D;" },
1134     { "lsh",	"&#x021B0;" },
1135     { "lurdshar",	"&#x0294A;" },
1136     { "luruhar",	"&#x02966;" },
1137     { "Map",	"&#x02905;" },
1138     { "map",	"&#x021A6;" },
1139     { "midcir",	"&#x02AF0;" },
1140     { "mumap",	"&#x022B8;" },
1141     { "nearhk",	"&#x02924;" },
1142     { "neArr",	"&#x021D7;" },
1143     { "nearr",	"&#x02197;" },
1144     { "nesear",	"&#x02928;" },
1145     { "nhArr",	"&#x021CE;" },
1146     { "nharr",	"&#x021AE;" },
1147     { "nlArr",	"&#x021CD;" },
1148     { "nlarr",	"&#x0219A;" },
1149     { "nrArr",	"&#x021CF;" },
1150     { "nrarr",	"&#x0219B;" },
1151     { "nrarrc",	"&#x02933;&#x00338;" },
1152     { "nrarrw",	"&#x0219D;&#x00338;" },
1153     { "nvHarr",	"&#x02904;" },
1154     { "nvlArr",	"&#x02902;" },
1155     { "nvrArr",	"&#x02903;" },
1156     { "nwarhk",	"&#x02923;" },
1157     { "nwArr",	"&#x021D6;" },
1158     { "nwarr",	"&#x02196;" },
1159     { "nwnear",	"&#x02927;" },
1160     { "olarr",	"&#x021BA;" },
1161     { "orarr",	"&#x021BB;" },
1162     { "origof",	"&#x022B6;" },
1163     { "rAarr",	"&#x021DB;" },
1164     { "Rarr",	"&#x021A0;" },
1165     { "rarrap",	"&#x02975;" },
1166     { "rarrbfs",	"&#x02920;" },
1167     { "rarrc",	"&#x02933;" },
1168     { "rarrfs",	"&#x0291E;" },
1169     { "rarrhk",	"&#x021AA;" },
1170     { "rarrlp",	"&#x021AC;" },
1171     { "rarrpl",	"&#x02945;" },
1172     { "rarrsim",	"&#x02974;" },
1173     { "Rarrtl",	"&#x02916;" },
1174     { "rarrtl",	"&#x021A3;" },
1175     { "rarrw",	"&#x0219D;" },
1176     { "rAtail",	"&#x0291C;" },
1177     { "ratail",	"&#x0291A;" },
1178     { "RBarr",	"&#x02910;" },
1179     { "rBarr",	"&#x0290F;" },
1180     { "rbarr",	"&#x0290D;" },
1181     { "rdca",	"&#x02937;" },
1182     { "rdldhar",	"&#x02969;" },
1183     { "rdsh",	"&#x021B3;" },
1184     { "rfisht",	"&#x0297D;" },
1185     { "rHar",	"&#x02964;" },
1186     { "rhard",	"&#x021C1;" },
1187     { "rharu",	"&#x021C0;" },
1188     { "rharul",	"&#x0296C;" },
1189     { "rlarr",	"&#x021C4;" },
1190     { "rlhar",	"&#x021CC;" },
1191     { "roarr",	"&#x021FE;" },
1192     { "rrarr",	"&#x021C9;" },
1193     { "rsh",	"&#x021B1;" },
1194     { "ruluhar",	"&#x02968;" },
1195     { "searhk",	"&#x02925;" },
1196     { "seArr",	"&#x021D8;" },
1197     { "searr",	"&#x02198;" },
1198     { "seswar",	"&#x02929;" },
1199     { "simrarr",	"&#x02972;" },
1200     { "slarr",	"&#x02190;" },
1201     { "srarr",	"&#x02192;" },
1202     { "swarhk",	"&#x02926;" },
1203     { "swArr",	"&#x021D9;" },
1204     { "swarr",	"&#x02199;" },
1205     { "swnwar",	"&#x0292A;" },
1206     { "Uarr",	"&#x0219F;" },
1207     { "uArr",	"&#x021D1;" },
1208     { "Uarrocir",	"&#x02949;" },
1209     { "udarr",	"&#x021C5;" },
1210     { "udhar",	"&#x0296E;" },
1211     { "ufisht",	"&#x0297E;" },
1212     { "uHar",	"&#x02963;" },
1213     { "uharl",	"&#x021BF;" },
1214     { "uharr",	"&#x021BE;" },
1215     { "uuarr",	"&#x021C8;" },
1216     { "vArr",	"&#x021D5;" },
1217     { "varr",	"&#x02195;" },
1218     { "xhArr",	"&#x027FA;" },
1219     { "xharr",	"&#x027F7;" },
1220     { "xlArr",	"&#x027F8;" },
1221     { "xlarr",	"&#x027F5;" },
1222     { "xmap",	"&#x027FC;" },
1223     { "xrArr",	"&#x027F9;" },
1224     { "xrarr",	"&#x027F6;" },
1225     { "zigrarr",	"&#x021DD;" },
1226     { "ac",	"&#x0223E;" },
1227     { "acE",	"&#x0223E;&#x00333;" },
1228     { "amalg",	"&#x02A3F;" },
1229     { "barvee",	"&#x022BD;" },
1230     { "Barwed",	"&#x02306;" },
1231     { "barwed",	"&#x02305;" },
1232     { "bsolb",	"&#x029C5;" },
1233     { "Cap",	"&#x022D2;" },
1234     { "capand",	"&#x02A44;" },
1235     { "capbrcup",	"&#x02A49;" },
1236     { "capcap",	"&#x02A4B;" },
1237     { "capcup",	"&#x02A47;" },
1238     { "capdot",	"&#x02A40;" },
1239     { "caps",	"&#x02229;&#x0FE00;" },
1240     { "ccaps",	"&#x02A4D;" },
1241     { "ccups",	"&#x02A4C;" },
1242     { "ccupssm",	"&#x02A50;" },
1243     { "coprod",	"&#x02210;" },
1244     { "Cup",	"&#x022D3;" },
1245     { "cupbrcap",	"&#x02A48;" },
1246     { "cupcap",	"&#x02A46;" },
1247     { "cupcup",	"&#x02A4A;" },
1248     { "cupdot",	"&#x0228D;" },
1249     { "cupor",	"&#x02A45;" },
1250     { "cups",	"&#x0222A;&#x0FE00;" },
1251     { "cuvee",	"&#x022CE;" },
1252     { "cuwed",	"&#x022CF;" },
1253     { "Dagger",	"&#x02021;" },
1254     { "dagger",	"&#x02020;" },
1255     { "diam",	"&#x022C4;" },
1256     { "divonx",	"&#x022C7;" },
1257     { "eplus",	"&#x02A71;" },
1258     { "hercon",	"&#x022B9;" },
1259     { "intcal",	"&#x022BA;" },
1260     { "iprod",	"&#x02A3C;" },
1261     { "loplus",	"&#x02A2D;" },
1262     { "lotimes",	"&#x02A34;" },
1263     { "lthree",	"&#x022CB;" },
1264     { "ltimes",	"&#x022C9;" },
1265     { "midast",	"&#x0002A;" },
1266     { "minusb",	"&#x0229F;" },
1267     { "minusd",	"&#x02238;" },
1268     { "minusdu",	"&#x02A2A;" },
1269     { "ncap",	"&#x02A43;" },
1270     { "ncup",	"&#x02A42;" },
1271     { "oast",	"&#x0229B;" },
1272     { "ocir",	"&#x0229A;" },
1273     { "odash",	"&#x0229D;" },
1274     { "odiv",	"&#x02A38;" },
1275     { "odot",	"&#x02299;" },
1276     { "odsold",	"&#x029BC;" },
1277     { "ofcir",	"&#x029BF;" },
1278     { "ogt",	"&#x029C1;" },
1279     { "ohbar",	"&#x029B5;" },
1280     { "olcir",	"&#x029BE;" },
1281     { "olt",	"&#x029C0;" },
1282     { "omid",	"&#x029B6;" },
1283     { "ominus",	"&#x02296;" },
1284     { "opar",	"&#x029B7;" },
1285     { "operp",	"&#x029B9;" },
1286     { "oplus",	"&#x02295;" },
1287     { "osol",	"&#x02298;" },
1288     { "Otimes",	"&#x02A37;" },
1289     { "otimes",	"&#x02297;" },
1290     { "otimesas",	"&#x02A36;" },
1291     { "ovbar",	"&#x0233D;" },
1292     { "plusacir",	"&#x02A23;" },
1293     { "plusb",	"&#x0229E;" },
1294     { "pluscir",	"&#x02A22;" },
1295     { "plusdo",	"&#x02214;" },
1296     { "plusdu",	"&#x02A25;" },
1297     { "pluse",	"&#x02A72;" },
1298     { "plussim",	"&#x02A26;" },
1299     { "plustwo",	"&#x02A27;" },
1300     { "prod",	"&#x0220F;" },
1301     { "race",	"&#x029DA;" },
1302     { "roplus",	"&#x02A2E;" },
1303     { "rotimes",	"&#x02A35;" },
1304     { "rthree",	"&#x022CC;" },
1305     { "rtimes",	"&#x022CA;" },
1306     { "sdot",	"&#x022C5;" },
1307     { "sdotb",	"&#x022A1;" },
1308     { "setmn",	"&#x02216;" },
1309     { "simplus",	"&#x02A24;" },
1310     { "smashp",	"&#x02A33;" },
1311     { "solb",	"&#x029C4;" },
1312     { "sqcap",	"&#x02293;" },
1313     { "sqcaps",	"&#x02293;&#x0FE00;" },
1314     { "sqcup",	"&#x02294;" },
1315     { "sqcups",	"&#x02294;&#x0FE00;" },
1316     { "ssetmn",	"&#x02216;" },
1317     { "sstarf",	"&#x022C6;" },
1318     { "subdot",	"&#x02ABD;" },
1319     { "sum",	"&#x02211;" },
1320     { "supdot",	"&#x02ABE;" },
1321     { "timesb",	"&#x022A0;" },
1322     { "timesbar",	"&#x02A31;" },
1323     { "timesd",	"&#x02A30;" },
1324     { "tridot",	"&#x025EC;" },
1325     { "triminus",	"&#x02A3A;" },
1326     { "triplus",	"&#x02A39;" },
1327     { "trisb",	"&#x029CD;" },
1328     { "tritime",	"&#x02A3B;" },
1329     { "uplus",	"&#x0228E;" },
1330     { "veebar",	"&#x022BB;" },
1331     { "wedbar",	"&#x02A5F;" },
1332     { "wreath",	"&#x02240;" },
1333     { "xcap",	"&#x022C2;" },
1334     { "xcirc",	"&#x025EF;" },
1335     { "xcup",	"&#x022C3;" },
1336     { "xdtri",	"&#x025BD;" },
1337     { "xodot",	"&#x02A00;" },
1338     { "xoplus",	"&#x02A01;" },
1339     { "xotime",	"&#x02A02;" },
1340     { "xsqcup",	"&#x02A06;" },
1341     { "xuplus",	"&#x02A04;" },
1342     { "xutri",	"&#x025B3;" },
1343     { "xvee",	"&#x022C1;" },
1344     { "xwedge",	"&#x022C0;" },
1345     { "dlcorn",	"&#x0231E;" },
1346     { "drcorn",	"&#x0231F;" },
1347     { "gtlPar",	"&#x02995;" },
1348     { "langd",	"&#x02991;" },
1349     { "lbrke",	"&#x0298B;" },
1350     { "lbrksld",	"&#x0298F;" },
1351     { "lbrkslu",	"&#x0298D;" },
1352     { "lceil",	"&#x02308;" },
1353     { "lfloor",	"&#x0230A;" },
1354     { "lmoust",	"&#x023B0;" },
1355     { "lparlt",	"&#x02993;" },
1356     { "ltrPar",	"&#x02996;" },
1357     { "rangd",	"&#x02992;" },
1358     { "rbrke",	"&#x0298C;" },
1359     { "rbrksld",	"&#x0298E;" },
1360     { "rbrkslu",	"&#x02990;" },
1361     { "rceil",	"&#x02309;" },
1362     { "rfloor",	"&#x0230B;" },
1363     { "rmoust",	"&#x023B1;" },
1364     { "rpargt",	"&#x02994;" },
1365     { "ulcorn",	"&#x0231C;" },
1366     { "urcorn",	"&#x0231D;" },
1367     { "gnap",	"&#x02A8A;" },
1368     { "gnE",	"&#x02269;" },
1369     { "gne",	"&#x02A88;" },
1370     { "gnsim",	"&#x022E7;" },
1371     { "gvnE",	"&#x02269;&#x0FE00;" },
1372     { "lnap",	"&#x02A89;" },
1373     { "lnE",	"&#x02268;" },
1374     { "lne",	"&#x02A87;" },
1375     { "lnsim",	"&#x022E6;" },
1376     { "lvnE",	"&#x02268;&#x0FE00;" },
1377     { "nap",	"&#x02249;" },
1378     { "napE",	"&#x02A70;&#x00338;" },
1379     { "napid",	"&#x0224B;&#x00338;" },
1380     { "ncong",	"&#x02247;" },
1381     { "ncongdot",	"&#x02A6D;&#x00338;" },
1382     { "nequiv",	"&#x02262;" },
1383     { "ngE",	"&#x02267;&#x00338;" },
1384     { "nge",	"&#x02271;" },
1385     { "nges",	"&#x02A7E;&#x00338;" },
1386     { "nGg",	"&#x022D9;&#x00338;" },
1387     { "ngsim",	"&#x02275;" },
1388     { "nGt",	"&#x0226B;&#x020D2;" },
1389     { "ngt",	"&#x0226F;" },
1390     { "nGtv",	"&#x0226B;&#x00338;" },
1391     { "nlE",	"&#x02266;&#x00338;" },
1392     { "nle",	"&#x02270;" },
1393     { "nles",	"&#x02A7D;&#x00338;" },
1394     { "nLl",	"&#x022D8;&#x00338;" },
1395     { "nlsim",	"&#x02274;" },
1396     { "nLt",	"&#x0226A;&#x020D2;" },
1397     { "nlt",	"&#x0226E;" },
1398     { "nltri",	"&#x022EA;" },
1399     { "nltrie",	"&#x022EC;" },
1400     { "nLtv",	"&#x0226A;&#x00338;" },
1401     { "nmid",	"&#x02224;" },
1402     { "npar",	"&#x02226;" },
1403     { "npr",	"&#x02280;" },
1404     { "nprcue",	"&#x022E0;" },
1405     { "npre",	"&#x02AAF;&#x00338;" },
1406     { "nrtri",	"&#x022EB;" },
1407     { "nrtrie",	"&#x022ED;" },
1408     { "nsc",	"&#x02281;" },
1409     { "nsccue",	"&#x022E1;" },
1410     { "nsce",	"&#x02AB0;&#x00338;" },
1411     { "nsim",	"&#x02241;" },
1412     { "nsime",	"&#x02244;" },
1413     { "nsmid",	"&#x02224;" },
1414     { "nspar",	"&#x02226;" },
1415     { "nsqsube",	"&#x022E2;" },
1416     { "nsqsupe",	"&#x022E3;" },
1417     { "nsub",	"&#x02284;" },
1418     { "nsubE",	"&#x02AC5;&#x0338;" },
1419     { "nsube",	"&#x02288;" },
1420     { "nsup",	"&#x02285;" },
1421     { "nsupE",	"&#x02AC6;&#x0338;" },
1422     { "nsupe",	"&#x02289;" },
1423     { "ntgl",	"&#x02279;" },
1424     { "ntlg",	"&#x02278;" },
1425     { "nvap",	"&#x0224D;&#x020D2;" },
1426     { "nVDash",	"&#x022AF;" },
1427     { "nVdash",	"&#x022AE;" },
1428     { "nvDash",	"&#x022AD;" },
1429     { "nvdash",	"&#x022AC;" },
1430     { "nvge",	"&#x02265;&#x020D2;" },
1431     { "nvgt",	"&#x0003E;&#x020D2;" },
1432     { "nvle",	"&#x02264;&#x020D2;" },
1433     { "nvlt",	"&#x0003C;&#x020D2;" },
1434     { "nvltrie",	"&#x022B4;&#x020D2;" },
1435     { "nvrtrie",	"&#x022B5;&#x020D2;" },
1436     { "nvsim",	"&#x0223C;&#x020D2;" },
1437     { "parsim",	"&#x02AF3;" },
1438     { "prnap",	"&#x02AB9;" },
1439     { "prnE",	"&#x02AB5;" },
1440     { "prnsim",	"&#x022E8;" },
1441     { "rnmid",	"&#x02AEE;" },
1442     { "scnap",	"&#x02ABA;" },
1443     { "scnE",	"&#x02AB6;" },
1444     { "scnsim",	"&#x022E9;" },
1445     { "simne",	"&#x02246;" },
1446     { "solbar",	"&#x0233F;" },
1447     { "subnE",	"&#x02ACB;" },
1448     { "subne",	"&#x0228A;" },
1449     { "supnE",	"&#x02ACC;" },
1450     { "supne",	"&#x0228B;" },
1451     { "vnsub",	"&#x02282;&#x020D2;" },
1452     { "vnsup",	"&#x02283;&#x020D2;" },
1453     { "vsubnE",	"&#x02ACB;&#x0FE00;" },
1454     { "vsubne",	"&#x0228A;&#x0FE00;" },
1455     { "vsupnE",	"&#x02ACC;&#x0FE00;" },
1456     { "vsupne",	"&#x0228B;&#x0FE00;" },
1457     { "ang",	"&#x02220;" },
1458     { "ange",	"&#x029A4;" },
1459     { "angmsd",	"&#x02221;" },
1460     { "angmsdaa",	"&#x029A8;" },
1461     { "angmsdab",	"&#x029A9;" },
1462     { "angmsdac",	"&#x029AA;" },
1463     { "angmsdad",	"&#x029AB;" },
1464     { "angmsdae",	"&#x029AC;" },
1465     { "angmsdaf",	"&#x029AD;" },
1466     { "angmsdag",	"&#x029AE;" },
1467     { "angmsdah",	"&#x029AF;" },
1468     { "angrtvb",	"&#x022BE;" },
1469     { "angrtvbd",	"&#x0299D;" },
1470     { "bbrk",	"&#x023B5;" },
1471     { "bemptyv",	"&#x029B0;" },
1472     { "beth",	"&#x02136;" },
1473     { "boxbox",	"&#x029C9;" },
1474     { "bprime",	"&#x02035;" },
1475     { "bsemi",	"&#x0204F;" },
1476     { "cemptyv",	"&#x029B2;" },
1477     { "cirE",	"&#x029C3;" },
1478     { "cirscir",	"&#x029C2;" },
1479     { "comp",	"&#x02201;" },
1480     { "daleth",	"&#x02138;" },
1481     { "demptyv",	"&#x029B1;" },
1482     { "ell",	"&#x02113;" },
1483     { "empty",	"&#x02205;" },
1484     { "emptyv",	"&#x02205;" },
1485     { "gimel",	"&#x02137;" },
1486     { "iiota",	"&#x02129;" },
1487     { "image",	"&#x02111;" },
1488     { "imath",	"&#x00131;" },
1489     { "jmath",	"&#x0006A;" },
1490     { "laemptyv",	"&#x029B4;" },
1491     { "lltri",	"&#x025FA;" },
1492     { "lrtri",	"&#x022BF;" },
1493     { "mho",	"&#x02127;" },
1494     { "nang",	"&#x02220;&#x020D2;" },
1495     { "nexist",	"&#x02204;" },
1496     { "oS",	"&#x024C8;" },
1497     { "planck",	"&#x0210F;" },
1498     { "plankv",	"&#x0210F;" },
1499     { "raemptyv",	"&#x029B3;" },
1500     { "range",	"&#x029A5;" },
1501     { "real",	"&#x0211C;" },
1502     { "tbrk",	"&#x023B4;" },
1503     { "ultri",	"&#x025F8;" },
1504     { "urtri",	"&#x025F9;" },
1505     { "vzigzag",	"&#x0299A;" },
1506     { "weierp",	"&#x02118;" },
1507     { "apE",	"&#x02A70;" },
1508     { "ape",	"&#x0224A;" },
1509     { "apid",	"&#x0224B;" },
1510     { "asymp",	"&#x02248;" },
1511     { "Barv",	"&#x02AE7;" },
1512     { "bcong",	"&#x0224C;" },
1513     { "bepsi",	"&#x003F6;" },
1514     { "bowtie",	"&#x022C8;" },
1515     { "bsim",	"&#x0223D;" },
1516     { "bsime",	"&#x022CD;" },
1517     { "bsolhsub",	"&#x0005C;&#x02282;" },
1518     { "bump",	"&#x0224E;" },
1519     { "bumpE",	"&#x02AAE;" },
1520     { "bumpe",	"&#x0224F;" },
1521     { "cire",	"&#x02257;" },
1522     { "Colon",	"&#x02237;" },
1523     { "Colone",	"&#x02A74;" },
1524     { "colone",	"&#x02254;" },
1525     { "congdot",	"&#x02A6D;" },
1526     { "csub",	"&#x02ACF;" },
1527     { "csube",	"&#x02AD1;" },
1528     { "csup",	"&#x02AD0;" },
1529     { "csupe",	"&#x02AD2;" },
1530     { "cuepr",	"&#x022DE;" },
1531     { "cuesc",	"&#x022DF;" },
1532     { "Dashv",	"&#x02AE4;" },
1533     { "dashv",	"&#x022A3;" },
1534     { "easter",	"&#x02A6E;" },
1535     { "ecir",	"&#x02256;" },
1536     { "ecolon",	"&#x02255;" },
1537     { "eDDot",	"&#x02A77;" },
1538     { "eDot",	"&#x02251;" },
1539     { "efDot",	"&#x02252;" },
1540     { "eg",	"&#x02A9A;" },
1541     { "egs",	"&#x02A96;" },
1542     { "egsdot",	"&#x02A98;" },
1543     { "el",	"&#x02A99;" },
1544     { "els",	"&#x02A95;" },
1545     { "elsdot",	"&#x02A97;" },
1546     { "equest",	"&#x0225F;" },
1547     { "equivDD",	"&#x02A78;" },
1548     { "erDot",	"&#x02253;" },
1549     { "esdot",	"&#x02250;" },
1550     { "Esim",	"&#x02A73;" },
1551     { "esim",	"&#x02242;" },
1552     { "fork",	"&#x022D4;" },
1553     { "forkv",	"&#x02AD9;" },
1554     { "frown",	"&#x02322;" },
1555     { "gap",	"&#x02A86;" },
1556     { "gE",	"&#x02267;" },
1557     { "gEl",	"&#x02A8C;" },
1558     { "gel",	"&#x022DB;" },
1559     { "ges",	"&#x02A7E;" },
1560     { "gescc",	"&#x02AA9;" },
1561     { "gesdot",	"&#x02A80;" },
1562     { "gesdoto",	"&#x02A82;" },
1563     { "gesdotol",	"&#x02A84;" },
1564     { "gesl",	"&#x022DB;&#x0FE00;" },
1565     { "gesles",	"&#x02A94;" },
1566     { "Gg",	"&#x022D9;" },
1567     { "gl",	"&#x02277;" },
1568     { "gla",	"&#x02AA5;" },
1569     { "glE",	"&#x02A92;" },
1570     { "glj",	"&#x02AA4;" },
1571     { "gsim",	"&#x02273;" },
1572     { "gsime",	"&#x02A8E;" },
1573     { "gsiml",	"&#x02A90;" },
1574     { "Gt",	"&#x0226B;" },
1575     { "gtcc",	"&#x02AA7;" },
1576     { "gtcir",	"&#x02A7A;" },
1577     { "gtdot",	"&#x022D7;" },
1578     { "gtquest",	"&#x02A7C;" },
1579     { "gtrarr",	"&#x02978;" },
1580     { "homtht",	"&#x0223B;" },
1581     { "lap",	"&#x02A85;" },
1582     { "lat",	"&#x02AAB;" },
1583     { "late",	"&#x02AAD;" },
1584     { "lates",	"&#x02AAD;&#x0FE00;" },
1585     { "lE",	"&#x02266;" },
1586     { "lEg",	"&#x02A8B;" },
1587     { "leg",	"&#x022DA;" },
1588     { "les",	"&#x02A7D;" },
1589     { "lescc",	"&#x02AA8;" },
1590     { "lesdot",	"&#x02A7F;" },
1591     { "lesdoto",	"&#x02A81;" },
1592     { "lesdotor",	"&#x02A83;" },
1593     { "lesg",	"&#x022DA;&#x0FE00;" },
1594     { "lesges",	"&#x02A93;" },
1595     { "lg",	"&#x02276;" },
1596     { "lgE",	"&#x02A91;" },
1597     { "Ll",	"&#x022D8;" },
1598     { "lsim",	"&#x02272;" },
1599     { "lsime",	"&#x02A8D;" },
1600     { "lsimg",	"&#x02A8F;" },
1601     { "Lt",	"&#x0226A;" },
1602     { "ltcc",	"&#x02AA6;" },
1603     { "ltcir",	"&#x02A79;" },
1604     { "ltdot",	"&#x022D6;" },
1605     { "ltlarr",	"&#x02976;" },
1606     { "ltquest",	"&#x02A7B;" },
1607     { "ltrie",	"&#x022B4;" },
1608     { "mcomma",	"&#x02A29;" },
1609     { "mDDot",	"&#x0223A;" },
1610     { "mid",	"&#x02223;" },
1611     { "mlcp",	"&#x02ADB;" },
1612     { "models",	"&#x022A7;" },
1613     { "mstpos",	"&#x0223E;" },
1614     { "Pr",	"&#x02ABB;" },
1615     { "pr",	"&#x0227A;" },
1616     { "prap",	"&#x02AB7;" },
1617     { "prcue",	"&#x0227C;" },
1618     { "prE",	"&#x02AB3;" },
1619     { "pre",	"&#x02AAF;" },
1620     { "prsim",	"&#x0227E;" },
1621     { "prurel",	"&#x022B0;" },
1622     { "ratio",	"&#x02236;" },
1623     { "rtrie",	"&#x022B5;" },
1624     { "rtriltri",	"&#x029CE;" },
1625     { "Sc",	"&#x02ABC;" },
1626     { "sc",	"&#x0227B;" },
1627     { "scap",	"&#x02AB8;" },
1628     { "sccue",	"&#x0227D;" },
1629     { "scE",	"&#x02AB4;" },
1630     { "sce",	"&#x02AB0;" },
1631     { "scsim",	"&#x0227F;" },
1632     { "sdote",	"&#x02A66;" },
1633     { "simg",	"&#x02A9E;" },
1634     { "simgE",	"&#x02AA0;" },
1635     { "siml",	"&#x02A9D;" },
1636     { "simlE",	"&#x02A9F;" },
1637     { "smid",	"&#x02223;" },
1638     { "smile",	"&#x02323;" },
1639     { "smt",	"&#x02AAA;" },
1640     { "smte",	"&#x02AAC;" },
1641     { "smtes",	"&#x02AAC;&#x0FE00;" },
1642     { "spar",	"&#x02225;" },
1643     { "sqsub",	"&#x0228F;" },
1644     { "sqsube",	"&#x02291;" },
1645     { "sqsup",	"&#x02290;" },
1646     { "sqsupe",	"&#x02292;" },
1647     { "Sub",	"&#x022D0;" },
1648     { "subE",	"&#x02AC5;" },
1649     { "subedot",	"&#x02AC3;" },
1650     { "submult",	"&#x02AC1;" },
1651     { "subplus",	"&#x02ABF;" },
1652     { "subrarr",	"&#x02979;" },
1653     { "subsim",	"&#x02AC7;" },
1654     { "subsub",	"&#x02AD5;" },
1655     { "subsup",	"&#x02AD3;" },
1656     { "Sup",	"&#x022D1;" },
1657     { "supdsub",	"&#x02AD8;" },
1658     { "supE",	"&#x02AC6;" },
1659     { "supedot",	"&#x02AC4;" },
1660     { "suphsol",	"&#x02283;&#x00338;" },
1661     { "suphsub",	"&#x02AD7;" },
1662     { "suplarr",	"&#x0297B;" },
1663     { "supmult",	"&#x02AC2;" },
1664     { "supplus",	"&#x02AC0;" },
1665     { "supsim",	"&#x02AC8;" },
1666     { "supsub",	"&#x02AD4;" },
1667     { "supsup",	"&#x02AD6;" },
1668     { "thkap",	"&#x02248;" },
1669     { "topfork",	"&#x02ADA;" },
1670     { "trie",	"&#x0225C;" },
1671     { "twixt",	"&#x0226C;" },
1672     { "Vbar",	"&#x02AEB;" },
1673     { "vBar",	"&#x02AE8;" },
1674     { "vBarv",	"&#x02AE9;" },
1675     { "VDash",	"&#x022AB;" },
1676     { "Vdash",	"&#x022A9;" },
1677     { "vDash",	"&#x022A8;" },
1678     { "vdash",	"&#x022A2;" },
1679     { "Vdashl",	"&#x02AE6;" },
1680     { "vltri",	"&#x022B2;" },
1681     { "vprop",	"&#x0221D;" },
1682     { "vrtri",	"&#x022B3;" },
1683     { "Vvdash",	"&#x022AA;" },
1684     { "alpha",	"&#x003B1;" },
1685     { "beta",	"&#x003B2;" },
1686     { "chi",	"&#x003C7;" },
1687     { "Delta",	"&#x00394;" },
1688     { "delta",	"&#x003B4;" },
1689     { "epsi",	"&#x003B5;" },
1690     { "epsiv",	"&#x0025B;" },
1691     { "eta",	"&#x003B7;" },
1692     { "Gamma",	"&#x00393;" },
1693     { "gamma",	"&#x003B3;" },
1694     { "Gammad",	"&#x003DC;" },
1695     { "gammad",	"&#x003DD;" },
1696     { "iota",	"&#x003B9;" },
1697     { "kappa",	"&#x003BA;" },
1698     { "kappav",	"&#x003F0;" },
1699     { "Lambda",	"&#x0039B;" },
1700     { "lambda",	"&#x003BB;" },
1701     { "mu",	"&#x003BC;" },
1702     { "nu",	"&#x003BD;" },
1703     { "Omega",	"&#x003A9;" },
1704     { "omega",	"&#x003C9;" },
1705     { "Phi",	"&#x003A6;" },
1706     { "phi",	"&#x003D5;" },
1707     { "phiv",	"&#x003C6;" },
1708     { "Pi",	"&#x003A0;" },
1709     { "pi",	"&#x003C0;" },
1710     { "piv",	"&#x003D6;" },
1711     { "Psi",	"&#x003A8;" },
1712     { "psi",	"&#x003C8;" },
1713     { "rho",	"&#x003C1;" },
1714     { "rhov",	"&#x003F1;" },
1715     { "Sigma",	"&#x003A3;" },
1716     { "sigma",	"&#x003C3;" },
1717     { "sigmav",	"&#x003C2;" },
1718     { "tau",	"&#x003C4;" },
1719     { "Theta",	"&#x00398;" },
1720     { "theta",	"&#x003B8;" },
1721     { "thetav",	"&#x003D1;" },
1722     { "Upsi",	"&#x003D2;" },
1723     { "upsi",	"&#x003C5;" },
1724     { "Xi",	"&#x0039E;" },
1725     { "xi",	"&#x003BE;" },
1726     { "zeta",	"&#x003B6;" },
1727     { "Cfr",	"&#x0212D;" },
1728     { "Hfr",	"&#x0210C;" },
1729     { "Ifr",	"&#x02111;" },
1730     { "Rfr",	"&#x0211C;" },
1731     { "Zfr",	"&#x02128;" },
1732     { "Copf",	"&#x02102;" },
1733     { "Hopf",	"&#x0210D;" },
1734     { "Nopf",	"&#x02115;" },
1735     { "Popf",	"&#x02119;" },
1736     { "Qopf",	"&#x0211A;" },
1737     { "Ropf",	"&#x0211D;" },
1738     { "Zopf",	"&#x02124;" },
1739     { "Bscr",	"&#x0212C;" },
1740     { "Escr",	"&#x02130;" },
1741     { "escr",	"&#x0212F;" },
1742     { "Fscr",	"&#x02131;" },
1743     { "gscr",	"&#x0210A;" },
1744     { "Hscr",	"&#x0210B;" },
1745     { "Iscr",	"&#x02110;" },
1746     { "Lscr",	"&#x02112;" },
1747     { "Mscr",	"&#x02133;" },
1748     { "oscr",	"&#x02134;" },
1749     { "pscr",	"&#x1D4C5;" },
1750     { "Rscr",	"&#x0211B;" },
1751     { "acd",	"&#x0223F;" },
1752     { "aleph",	"&#x02135;" },
1753     { "And",	"&#x02A53;" },
1754     { "and",	"&#x02227;" },
1755     { "andand",	"&#x02A55;" },
1756     { "andd",	"&#x02A5C;" },
1757     { "andslope",	"&#x02A58;" },
1758     { "andv",	"&#x02A5A;" },
1759     { "angrt",	"&#x0221F;" },
1760     { "angsph",	"&#x02222;" },
1761     { "angst",	"&#x0212B;" },
1762     { "ap",	"&#x02248;" },
1763     { "apacir",	"&#x02A6F;" },
1764     { "awconint",	"&#x02233;" },
1765     { "awint",	"&#x02A11;" },
1766     { "becaus",	"&#x02235;" },
1767     { "bernou",	"&#x0212C;" },
1768     { "bne",	"&#x0003D;&#x020E5;" },
1769     { "bnequiv",	"&#x02261;&#x020E5;" },
1770     { "bNot",	"&#x02AED;" },
1771     { "bnot",	"&#x02310;" },
1772     { "bottom",	"&#x022A5;" },
1773     { "cap",	"&#x02229;" },
1774     { "Cconint",	"&#x02230;" },
1775     { "cirfnint",	"&#x02A10;" },
1776     { "compfn",	"&#x02218;" },
1777     { "cong",	"&#x02245;" },
1778     { "Conint",	"&#x0222F;" },
1779     { "conint",	"&#x0222E;" },
1780     { "ctdot",	"&#x022EF;" },
1781     { "cup",	"&#x0222A;" },
1782     { "cwconint",	"&#x02232;" },
1783     { "cwint",	"&#x02231;" },
1784     { "cylcty",	"&#x0232D;" },
1785     { "disin",	"&#x022F2;" },
1786     { "Dot",	"&#x000A8;" },
1787     { "DotDot",	"&#x020DC;" },
1788     { "dsol",	"&#x029F6;" },
1789     { "dtdot",	"&#x022F1;" },
1790     { "dwangle",	"&#x029A6;" },
1791     { "epar",	"&#x022D5;" },
1792     { "eparsl",	"&#x029E3;" },
1793     { "equiv",	"&#x02261;" },
1794     { "eqvparsl",	"&#x029E5;" },
1795     { "exist",	"&#x02203;" },
1796     { "fnof",	"&#x00192;" },
1797     { "forall",	"&#x02200;" },
1798     { "fpartint",	"&#x02A0D;" },
1799     { "ge",	"&#x02265;" },
1800     { "hamilt",	"&#x0210B;" },
1801     { "iff",	"&#x021D4;" },
1802     { "iinfin",	"&#x029DC;" },
1803     { "infin",	"&#x0221E;" },
1804     { "Int",	"&#x0222C;" },
1805     { "int",	"&#x0222B;" },
1806     { "intlarhk",	"&#x02A17;" },
1807     { "isin",	"&#x02208;" },
1808     { "isindot",	"&#x022F5;" },
1809     { "isinE",	"&#x022F9;" },
1810     { "isins",	"&#x022F4;" },
1811     { "isinsv",	"&#x022F3;" },
1812     { "isinv",	"&#x02208;" },
1813     { "lagran",	"&#x02112;" },
1814     { "Lang",	"&#x0300A;" },
1815     { "lang",	"&#x02329;" },
1816     { "lArr",	"&#x021D0;" },
1817     { "lbbrk",	"&#x03014;" },
1818     { "le",	"&#x02264;" },
1819     { "loang",	"&#x03018;" },
1820     { "lobrk",	"&#x0301A;" },
1821     { "lopar",	"&#x02985;" },
1822     { "lowast",	"&#x02217;" },
1823     { "minus",	"&#x02212;" },
1824     { "mnplus",	"&#x02213;" },
1825     { "nabla",	"&#x02207;" },
1826     { "ne",	"&#x02260;" },
1827     { "nedot",	"&#x02250;&#x00338;" },
1828     { "nhpar",	"&#x02AF2;" },
1829     { "ni",	"&#x0220B;" },
1830     { "nis",	"&#x022FC;" },
1831     { "nisd",	"&#x022FA;" },
1832     { "niv",	"&#x0220B;" },
1833     { "Not",	"&#x02AEC;" },
1834     { "notin",	"&#x02209;" },
1835     { "notindot",	"&#x022F5;&#x00338;" },
1836     { "notinva",	"&#x02209;" },
1837     { "notinvb",	"&#x022F7;" },
1838     { "notinvc",	"&#x022F6;" },
1839     { "notni",	"&#x0220C;" },
1840     { "notniva",	"&#x0220C;" },
1841     { "notnivb",	"&#x022FE;" },
1842     { "notnivc",	"&#x022FD;" },
1843     { "nparsl",	"&#x02AFD;&#x020E5;" },
1844     { "npart",	"&#x02202;&#x00338;" },
1845     { "npolint",	"&#x02A14;" },
1846     { "nvinfin",	"&#x029DE;" },
1847     { "olcross",	"&#x029BB;" },
1848     { "Or",	"&#x02A54;" },
1849     { "or",	"&#x02228;" },
1850     { "ord",	"&#x02A5D;" },
1851     { "order",	"&#x02134;" },
1852     { "oror",	"&#x02A56;" },
1853     { "orslope",	"&#x02A57;" },
1854     { "orv",	"&#x02A5B;" },
1855     { "par",	"&#x02225;" },
1856     { "parsl",	"&#x02AFD;" },
1857     { "part",	"&#x02202;" },
1858     { "permil",	"&#x02030;" },
1859     { "perp",	"&#x022A5;" },
1860     { "pertenk",	"&#x02031;" },
1861     { "phmmat",	"&#x02133;" },
1862     { "pointint",	"&#x02A15;" },
1863     { "Prime",	"&#x02033;" },
1864     { "prime",	"&#x02032;" },
1865     { "profalar",	"&#x0232E;" },
1866     { "profline",	"&#x02312;" },
1867     { "profsurf",	"&#x02313;" },
1868     { "prop",	"&#x0221D;" },
1869     { "qint",	"&#x02A0C;" },
1870     { "qprime",	"&#x02057;" },
1871     { "quatint",	"&#x02A16;" },
1872     { "radic",	"&#x0221A;" },
1873     { "Rang",	"&#x0300B;" },
1874     { "rang",	"&#x0232A;" },
1875     { "rArr",	"&#x021D2;" },
1876     { "rbbrk",	"&#x03015;" },
1877     { "roang",	"&#x03019;" },
1878     { "robrk",	"&#x0301B;" },
1879     { "ropar",	"&#x02986;" },
1880     { "rppolint",	"&#x02A12;" },
1881     { "scpolint",	"&#x02A13;" },
1882     { "sim",	"&#x0223C;" },
1883     { "simdot",	"&#x02A6A;" },
1884     { "sime",	"&#x02243;" },
1885     { "smeparsl",	"&#x029E4;" },
1886     { "square",	"&#x025A1;" },
1887     { "squarf",	"&#x025AA;" },
1888     { "sub",	"&#x02282;" },
1889     { "sube",	"&#x02286;" },
1890     { "sup",	"&#x02283;" },
1891     { "supe",	"&#x02287;" },
1892     { "tdot",	"&#x020DB;" },
1893     { "there4",	"&#x02234;" },
1894     { "tint",	"&#x0222D;" },
1895     { "top",	"&#x022A4;" },
1896     { "topbot",	"&#x02336;" },
1897     { "topcir",	"&#x02AF1;" },
1898     { "tprime",	"&#x02034;" },
1899     { "utdot",	"&#x022F0;" },
1900     { "uwangle",	"&#x029A7;" },
1901     { "vangrt",	"&#x0299C;" },
1902     { "veeeq",	"&#x0225A;" },
1903     { "Verbar",	"&#x02016;" },
1904     { "wedgeq",	"&#x02259;" },
1905     { "xnis",	"&#x022FB;" },
1906     { "boxDL",	"&#x02557;" },
1907     { "boxDl",	"&#x02556;" },
1908     { "boxdL",	"&#x02555;" },
1909     { "boxdl",	"&#x02510;" },
1910     { "boxDR",	"&#x02554;" },
1911     { "boxDr",	"&#x02553;" },
1912     { "boxdR",	"&#x02552;" },
1913     { "boxdr",	"&#x0250C;" },
1914     { "boxH",	"&#x02550;" },
1915     { "boxh",	"&#x02500;" },
1916     { "boxHD",	"&#x02566;" },
1917     { "boxHd",	"&#x02564;" },
1918     { "boxhD",	"&#x02565;" },
1919     { "boxhd",	"&#x0252C;" },
1920     { "boxHU",	"&#x02569;" },
1921     { "boxHu",	"&#x02567;" },
1922     { "boxhU",	"&#x02568;" },
1923     { "boxhu",	"&#x02534;" },
1924     { "boxUL",	"&#x0255D;" },
1925     { "boxUl",	"&#x0255C;" },
1926     { "boxuL",	"&#x0255B;" },
1927     { "boxul",	"&#x02518;" },
1928     { "boxUR",	"&#x0255A;" },
1929     { "boxUr",	"&#x02559;" },
1930     { "boxuR",	"&#x02558;" },
1931     { "boxur",	"&#x02514;" },
1932     { "boxV",	"&#x02551;" },
1933     { "boxv",	"&#x02502;" },
1934     { "boxVH",	"&#x0256C;" },
1935     { "boxVh",	"&#x0256B;" },
1936     { "boxvH",	"&#x0256A;" },
1937     { "boxvh",	"&#x0253C;" },
1938     { "boxVL",	"&#x02563;" },
1939     { "boxVl",	"&#x02562;" },
1940     { "boxvL",	"&#x02561;" },
1941     { "boxvl",	"&#x02524;" },
1942     { "boxVR",	"&#x02560;" },
1943     { "boxVr",	"&#x0255F;" },
1944     { "boxvR",	"&#x0255E;" },
1945     { "boxvr",	"&#x0251C;" },
1946     { "Acy",	"&#x00410;" },
1947     { "acy",	"&#x00430;" },
1948     { "Bcy",	"&#x00411;" },
1949     { "bcy",	"&#x00431;" },
1950     { "CHcy",	"&#x00427;" },
1951     { "chcy",	"&#x00447;" },
1952     { "Dcy",	"&#x00414;" },
1953     { "dcy",	"&#x00434;" },
1954     { "Ecy",	"&#x0042D;" },
1955     { "ecy",	"&#x0044D;" },
1956     { "Fcy",	"&#x00424;" },
1957     { "fcy",	"&#x00444;" },
1958     { "Gcy",	"&#x00413;" },
1959     { "gcy",	"&#x00433;" },
1960     { "HARDcy",	"&#x0042A;" },
1961     { "hardcy",	"&#x0044A;" },
1962     { "Icy",	"&#x00418;" },
1963     { "icy",	"&#x00438;" },
1964     { "IEcy",	"&#x00415;" },
1965     { "iecy",	"&#x00435;" },
1966     { "IOcy",	"&#x00401;" },
1967     { "iocy",	"&#x00451;" },
1968     { "Jcy",	"&#x00419;" },
1969     { "jcy",	"&#x00439;" },
1970     { "Kcy",	"&#x0041A;" },
1971     { "kcy",	"&#x0043A;" },
1972     { "KHcy",	"&#x00425;" },
1973     { "khcy",	"&#x00445;" },
1974     { "Lcy",	"&#x0041B;" },
1975     { "lcy",	"&#x0043B;" },
1976     { "Mcy",	"&#x0041C;" },
1977     { "mcy",	"&#x0043C;" },
1978     { "Ncy",	"&#x0041D;" },
1979     { "ncy",	"&#x0043D;" },
1980     { "numero",	"&#x02116;" },
1981     { "Ocy",	"&#x0041E;" },
1982     { "ocy",	"&#x0043E;" },
1983     { "Pcy",	"&#x0041F;" },
1984     { "pcy",	"&#x0043F;" },
1985     { "Rcy",	"&#x00420;" },
1986     { "rcy",	"&#x00440;" },
1987     { "Scy",	"&#x00421;" },
1988     { "scy",	"&#x00441;" },
1989     { "SHCHcy",	"&#x00429;" },
1990     { "shchcy",	"&#x00449;" },
1991     { "SHcy",	"&#x00428;" },
1992     { "shcy",	"&#x00448;" },
1993     { "SOFTcy",	"&#x0042C;" },
1994     { "softcy",	"&#x0044C;" },
1995     { "Tcy",	"&#x00422;" },
1996     { "tcy",	"&#x00442;" },
1997     { "TScy",	"&#x00426;" },
1998     { "tscy",	"&#x00446;" },
1999     { "Ucy",	"&#x00423;" },
2000     { "ucy",	"&#x00443;" },
2001     { "Vcy",	"&#x00412;" },
2002     { "vcy",	"&#x00432;" },
2003     { "YAcy",	"&#x0042F;" },
2004     { "yacy",	"&#x0044F;" },
2005     { "Ycy",	"&#x0042B;" },
2006     { "ycy",	"&#x0044B;" },
2007     { "YUcy",	"&#x0042E;" },
2008     { "yucy",	"&#x0044E;" },
2009     { "Zcy",	"&#x00417;" },
2010     { "zcy",	"&#x00437;" },
2011     { "ZHcy",	"&#x00416;" },
2012     { "zhcy",	"&#x00436;" },
2013     { "DJcy",	"&#x00402;" },
2014     { "djcy",	"&#x00452;" },
2015     { "DScy",	"&#x00405;" },
2016     { "dscy",	"&#x00455;" },
2017     { "DZcy",	"&#x0040F;" },
2018     { "dzcy",	"&#x0045F;" },
2019     { "GJcy",	"&#x00403;" },
2020     { "gjcy",	"&#x00453;" },
2021     { "Iukcy",	"&#x00406;" },
2022     { "iukcy",	"&#x00456;" },
2023     { "Jsercy",	"&#x00408;" },
2024     { "jsercy",	"&#x00458;" },
2025     { "Jukcy",	"&#x00404;" },
2026     { "jukcy",	"&#x00454;" },
2027     { "KJcy",	"&#x0040C;" },
2028     { "kjcy",	"&#x0045C;" },
2029     { "LJcy",	"&#x00409;" },
2030     { "ljcy",	"&#x00459;" },
2031     { "NJcy",	"&#x0040A;" },
2032     { "njcy",	"&#x0045A;" },
2033     { "TSHcy",	"&#x0040B;" },
2034     { "tshcy",	"&#x0045B;" },
2035     { "Ubrcy",	"&#x0040E;" },
2036     { "ubrcy",	"&#x0045E;" },
2037     { "YIcy",	"&#x00407;" },
2038     { "yicy",	"&#x00457;" },
2039     { "acute",	"&#x000B4;" },
2040     { "breve",	"&#x002D8;" },
2041     { "caron",	"&#x002C7;" },
2042     { "cedil",	"&#x000B8;" },
2043     { "circ",	"&#x002C6;" },
2044     { "dblac",	"&#x002DD;" },
2045     { "die",	"&#x000A8;" },
2046     { "dot",	"&#x002D9;" },
2047     { "grave",	"&#x00060;" },
2048     { "macr",	"&#x000AF;" },
2049     { "ogon",	"&#x002DB;" },
2050     { "ring",	"&#x002DA;" },
2051     { "tilde",	"&#x002DC;" },
2052     { "uml",	"&#x000A8;" },
2053     { "Aacute",	"&#x000C1;" },
2054     { "aacute",	"&#x000E1;" },
2055     { "Acirc",	"&#x000C2;" },
2056     { "acirc",	"&#x000E2;" },
2057     { "AElig",	"&#x000C6;" },
2058     { "aelig",	"&#x000E6;" },
2059     { "Agrave",	"&#x000C0;" },
2060     { "agrave",	"&#x000E0;" },
2061     { "Aring",	"&#x000C5;" },
2062     { "aring",	"&#x000E5;" },
2063     { "Atilde",	"&#x000C3;" },
2064     { "atilde",	"&#x000E3;" },
2065     { "Auml",	"&#x000C4;" },
2066     { "auml",	"&#x000E4;" },
2067     { "Ccedil",	"&#x000C7;" },
2068     { "ccedil",	"&#x000E7;" },
2069     { "Eacute",	"&#x000C9;" },
2070     { "eacute",	"&#x000E9;" },
2071     { "Ecirc",	"&#x000CA;" },
2072     { "ecirc",	"&#x000EA;" },
2073     { "Egrave",	"&#x000C8;" },
2074     { "egrave",	"&#x000E8;" },
2075     { "ETH",	"&#x000D0;" },
2076     { "eth",	"&#x000F0;" },
2077     { "Euml",	"&#x000CB;" },
2078     { "euml",	"&#x000EB;" },
2079     { "Iacute",	"&#x000CD;" },
2080     { "iacute",	"&#x000ED;" },
2081     { "Icirc",	"&#x000CE;" },
2082     { "icirc",	"&#x000EE;" },
2083     { "Igrave",	"&#x000CC;" },
2084     { "igrave",	"&#x000EC;" },
2085     { "Iuml",	"&#x000CF;" },
2086     { "iuml",	"&#x000EF;" },
2087     { "Ntilde",	"&#x000D1;" },
2088     { "ntilde",	"&#x000F1;" },
2089     { "Oacute",	"&#x000D3;" },
2090     { "oacute",	"&#x000F3;" },
2091     { "Ocirc",	"&#x000D4;" },
2092     { "ocirc",	"&#x000F4;" },
2093     { "Ograve",	"&#x000D2;" },
2094     { "ograve",	"&#x000F2;" },
2095     { "Oslash",	"&#x000D8;" },
2096     { "oslash",	"&#x000F8;" },
2097     { "Otilde",	"&#x000D5;" },
2098     { "otilde",	"&#x000F5;" },
2099     { "Ouml",	"&#x000D6;" },
2100     { "ouml",	"&#x000F6;" },
2101     { "szlig",	"&#x000DF;" },
2102     { "THORN",	"&#x000DE;" },
2103     { "thorn",	"&#x000FE;" },
2104     { "Uacute",	"&#x000DA;" },
2105     { "uacute",	"&#x000FA;" },
2106     { "Ucirc",	"&#x000DB;" },
2107     { "ucirc",	"&#x000FB;" },
2108     { "Ugrave",	"&#x000D9;" },
2109     { "ugrave",	"&#x000F9;" },
2110     { "Uuml",	"&#x000DC;" },
2111     { "uuml",	"&#x000FC;" },
2112     { "Yacute",	"&#x000DD;" },
2113     { "yacute",	"&#x000FD;" },
2114     { "yuml",	"&#x000FF;" },
2115     { "Abreve",	"&#x00102;" },
2116     { "abreve",	"&#x00103;" },
2117     { "Amacr",	"&#x00100;" },
2118     { "amacr",	"&#x00101;" },
2119     { "Aogon",	"&#x00104;" },
2120     { "aogon",	"&#x00105;" },
2121     { "Cacute",	"&#x00106;" },
2122     { "cacute",	"&#x00107;" },
2123     { "Ccaron",	"&#x0010C;" },
2124     { "ccaron",	"&#x0010D;" },
2125     { "Ccirc",	"&#x00108;" },
2126     { "ccirc",	"&#x00109;" },
2127     { "Cdot",	"&#x0010A;" },
2128     { "cdot",	"&#x0010B;" },
2129     { "Dcaron",	"&#x0010E;" },
2130     { "dcaron",	"&#x0010F;" },
2131     { "Dstrok",	"&#x00110;" },
2132     { "dstrok",	"&#x00111;" },
2133     { "Ecaron",	"&#x0011A;" },
2134     { "ecaron",	"&#x0011B;" },
2135     { "Edot",	"&#x00116;" },
2136     { "edot",	"&#x00117;" },
2137     { "Emacr",	"&#x00112;" },
2138     { "emacr",	"&#x00113;" },
2139     { "ENG",	"&#x0014A;" },
2140     { "eng",	"&#x0014B;" },
2141     { "Eogon",	"&#x00118;" },
2142     { "eogon",	"&#x00119;" },
2143     { "gacute",	"&#x001F5;" },
2144     { "Gbreve",	"&#x0011E;" },
2145     { "gbreve",	"&#x0011F;" },
2146     { "Gcedil",	"&#x00122;" },
2147     { "Gcirc",	"&#x0011C;" },
2148     { "gcirc",	"&#x0011D;" },
2149     { "Gdot",	"&#x00120;" },
2150     { "gdot",	"&#x00121;" },
2151     { "Hcirc",	"&#x00124;" },
2152     { "hcirc",	"&#x00125;" },
2153     { "Hstrok",	"&#x00126;" },
2154     { "hstrok",	"&#x00127;" },
2155     { "Idot",	"&#x00130;" },
2156     { "IJlig",	"&#x00132;" },
2157     { "ijlig",	"&#x00133;" },
2158     { "Imacr",	"&#x0012A;" },
2159     { "imacr",	"&#x0012B;" },
2160     { "inodot",	"&#x00131;" },
2161     { "Iogon",	"&#x0012E;" },
2162     { "iogon",	"&#x0012F;" },
2163     { "Itilde",	"&#x00128;" },
2164     { "itilde",	"&#x00129;" },
2165     { "Jcirc",	"&#x00134;" },
2166     { "jcirc",	"&#x00135;" },
2167     { "Kcedil",	"&#x00136;" },
2168     { "kcedil",	"&#x00137;" },
2169     { "kgreen",	"&#x00138;" },
2170     { "Lacute",	"&#x00139;" },
2171     { "lacute",	"&#x0013A;" },
2172     { "Lcaron",	"&#x0013D;" },
2173     { "lcaron",	"&#x0013E;" },
2174     { "Lcedil",	"&#x0013B;" },
2175     { "lcedil",	"&#x0013C;" },
2176     { "Lmidot",	"&#x0013F;" },
2177     { "lmidot",	"&#x00140;" },
2178     { "Lstrok",	"&#x00141;" },
2179     { "lstrok",	"&#x00142;" },
2180     { "Nacute",	"&#x00143;" },
2181     { "nacute",	"&#x00144;" },
2182     { "napos",	"&#x00149;" },
2183     { "Ncaron",	"&#x00147;" },
2184     { "ncaron",	"&#x00148;" },
2185     { "Ncedil",	"&#x00145;" },
2186     { "ncedil",	"&#x00146;" },
2187     { "Odblac",	"&#x00150;" },
2188     { "odblac",	"&#x00151;" },
2189     { "OElig",	"&#x00152;" },
2190     { "oelig",	"&#x00153;" },
2191     { "Omacr",	"&#x0014C;" },
2192     { "omacr",	"&#x0014D;" },
2193     { "Racute",	"&#x00154;" },
2194     { "racute",	"&#x00155;" },
2195     { "Rcaron",	"&#x00158;" },
2196     { "rcaron",	"&#x00159;" },
2197     { "Rcedil",	"&#x00156;" },
2198     { "rcedil",	"&#x00157;" },
2199     { "Sacute",	"&#x0015A;" },
2200     { "sacute",	"&#x0015B;" },
2201     { "Scaron",	"&#x00160;" },
2202     { "scaron",	"&#x00161;" },
2203     { "Scedil",	"&#x0015E;" },
2204     { "scedil",	"&#x0015F;" },
2205     { "Scirc",	"&#x0015C;" },
2206     { "scirc",	"&#x0015D;" },
2207     { "Tcaron",	"&#x00164;" },
2208     { "tcaron",	"&#x00165;" },
2209     { "Tcedil",	"&#x00162;" },
2210     { "tcedil",	"&#x00163;" },
2211     { "Tstrok",	"&#x00166;" },
2212     { "tstrok",	"&#x00167;" },
2213     { "Ubreve",	"&#x0016C;" },
2214     { "ubreve",	"&#x0016D;" },
2215     { "Udblac",	"&#x00170;" },
2216     { "udblac",	"&#x00171;" },
2217     { "Umacr",	"&#x0016A;" },
2218     { "umacr",	"&#x0016B;" },
2219     { "Uogon",	"&#x00172;" },
2220     { "uogon",	"&#x00173;" },
2221     { "Uring",	"&#x0016E;" },
2222     { "uring",	"&#x0016F;" },
2223     { "Utilde",	"&#x00168;" },
2224     { "utilde",	"&#x00169;" },
2225     { "Wcirc",	"&#x00174;" },
2226     { "wcirc",	"&#x00175;" },
2227     { "Ycirc",	"&#x00176;" },
2228     { "ycirc",	"&#x00177;" },
2229     { "Yuml",	"&#x00178;" },
2230     { "Zacute",	"&#x00179;" },
2231     { "zacute",	"&#x0017A;" },
2232     { "Zcaron",	"&#x0017D;" },
2233     { "zcaron",	"&#x0017E;" },
2234     { "Zdot",	"&#x0017B;" },
2235     { "zdot",	"&#x0017C;" },
2236     { "apos",	"&#x00027;" },
2237     { "ast",	"&#x0002A;" },
2238     { "brvbar",	"&#x000A6;" },
2239     { "bsol",	"&#x0005C;" },
2240     { "cent",	"&#x000A2;" },
2241     { "colon",	"&#x0003A;" },
2242     { "comma",	"&#x0002C;" },
2243     { "commat",	"&#x00040;" },
2244     { "copy",	"&#x000A9;" },
2245     { "curren",	"&#x000A4;" },
2246     { "darr",	"&#x02193;" },
2247     { "deg",	"&#x000B0;" },
2248     { "divide",	"&#x000F7;" },
2249     { "dollar",	"&#x00024;" },
2250     { "equals",	"&#x0003D;" },
2251     { "excl",	"&#x00021;" },
2252     { "frac12",	"&#x000BD;" },
2253     { "frac14",	"&#x000BC;" },
2254     { "frac18",	"&#x0215B;" },
2255     { "frac34",	"&#x000BE;" },
2256     { "frac38",	"&#x0215C;" },
2257     { "frac58",	"&#x0215D;" },
2258     { "frac78",	"&#x0215E;" },
2259     { "gt",	"&#x0003E;" },
2260     { "half",	"&#x000BD;" },
2261     { "horbar",	"&#x02015;" },
2262     { "hyphen",	"&#x02010;" },
2263     { "iexcl",	"&#x000A1;" },
2264     { "iquest",	"&#x000BF;" },
2265     { "laquo",	"&#x000AB;" },
2266     { "larr",	"&#x02190;" },
2267     { "lcub",	"&#x0007B;" },
2268     { "ldquo",	"&#x0201C;" },
2269     { "lowbar",	"&#x0005F;" },
2270     { "lpar",	"&#x00028;" },
2271     { "lsqb",	"&#x0005B;" },
2272     { "lsquo",	"&#x02018;" },
2273     { "lt",	"&#x0003C;" },
2274     { "micro",	"&#x000B5;" },
2275     { "middot",	"&#x000B7;" },
2276     { "nbsp",	"&#x000A0;" },
2277     { "not",	"&#x000AC;" },
2278     { "num",	"&#x00023;" },
2279     { "ohm",	"&#x02126;" },
2280     { "ordf",	"&#x000AA;" },
2281     { "ordm",	"&#x000BA;" },
2282     { "para",	"&#x000B6;" },
2283     { "percnt",	"&#x00025;" },
2284     { "period",	"&#x0002E;" },
2285     { "plus",	"&#x0002B;" },
2286     { "plusmn",	"&#x000B1;" },
2287     { "pound",	"&#x000A3;" },
2288     { "quest",	"&#x0003F;" },
2289     { "quot",	"&#x00022;" },
2290     { "raquo",	"&#x000BB;" },
2291     { "rarr",	"&#x02192;" },
2292     { "rcub",	"&#x0007D;" },
2293     { "rdquo",	"&#x0201D;" },
2294     { "reg",	"&#x000AE;" },
2295     { "rpar",	"&#x00029;" },
2296     { "rsqb",	"&#x0005D;" },
2297     { "rsquo",	"&#x02019;" },
2298     { "sect",	"&#x000A7;" },
2299     { "semi",	"&#x0003B;" },
2300     { "shy",	"&#x000AD;" },
2301     { "sol",	"&#x0002F;" },
2302     { "sung",	"&#x0266A;" },
2303     { "sup1",	"&#x000B9;" },
2304     { "sup2",	"&#x000B2;" },
2305     { "sup3",	"&#x000B3;" },
2306     { "times",	"&#x000D7;" },
2307     { "trade",	"&#x02122;" },
2308     { "uarr",	"&#x02191;" },
2309     { "verbar",	"&#x0007C;" },
2310     { "yen",	"&#x000A5;" },
2311     { "blank",	"&#x02423;" },
2312     { "blk12",	"&#x02592;" },
2313     { "blk14",	"&#x02591;" },
2314     { "blk34",	"&#x02593;" },
2315     { "block",	"&#x02588;" },
2316     { "bull",	"&#x02022;" },
2317     { "caret",	"&#x02041;" },
2318     { "check",	"&#x02713;" },
2319     { "cir",	"&#x025CB;" },
2320     { "clubs",	"&#x02663;" },
2321     { "copysr",	"&#x02117;" },
2322     { "cross",	"&#x02717;" },
2323     { "Dagger",	"&#x02021;" },
2324     { "dagger",	"&#x02020;" },
2325     { "dash",	"&#x02010;" },
2326     { "diams",	"&#x02666;" },
2327     { "dlcrop",	"&#x0230D;" },
2328     { "drcrop",	"&#x0230C;" },
2329     { "dtri",	"&#x025BF;" },
2330     { "dtrif",	"&#x025BE;" },
2331     { "emsp",	"&#x02003;" },
2332     { "emsp13",	"&#x02004;" },
2333     { "emsp14",	"&#x02005;" },
2334     { "ensp",	"&#x02002;" },
2335     { "female",	"&#x02640;" },
2336     { "ffilig",	"&#x0FB03;" },
2337     { "fflig",	"&#x0FB00;" },
2338     { "ffllig",	"&#x0FB04;" },
2339     { "filig",	"&#x0FB01;" },
2340     { "flat",	"&#x0266D;" },
2341     { "fllig",	"&#x0FB02;" },
2342     { "frac13",	"&#x02153;" },
2343     { "frac15",	"&#x02155;" },
2344     { "frac16",	"&#x02159;" },
2345     { "frac23",	"&#x02154;" },
2346     { "frac25",	"&#x02156;" },
2347     { "frac35",	"&#x02157;" },
2348     { "frac45",	"&#x02158;" },
2349     { "frac56",	"&#x0215A;" },
2350     { "hairsp",	"&#x0200A;" },
2351     { "hearts",	"&#x02665;" },
2352     { "hellip",	"&#x02026;" },
2353     { "hybull",	"&#x02043;" },
2354     { "incare",	"&#x02105;" },
2355     { "ldquor",	"&#x0201E;" },
2356     { "lhblk",	"&#x02584;" },
2357     { "loz",	"&#x025CA;" },
2358     { "lozf",	"&#x029EB;" },
2359     { "lsquor",	"&#x0201A;" },
2360     { "ltri",	"&#x025C3;" },
2361     { "ltrif",	"&#x025C2;" },
2362     { "male",	"&#x02642;" },
2363     { "malt",	"&#x02720;" },
2364     { "marker",	"&#x025AE;" },
2365     { "mdash",	"&#x02014;" },
2366     { "mldr",	"&#x02026;" },
2367     { "natur",	"&#x0266E;" },
2368     { "ndash",	"&#x02013;" },
2369     { "nldr",	"&#x02025;" },
2370     { "numsp",	"&#x02007;" },
2371     { "phone",	"&#x0260E;" },
2372     { "puncsp",	"&#x02008;" },
2373     { "rdquor",	"&#x0201D;" },
2374     { "rect",	"&#x025AD;" },
2375     { "rsquor",	"&#x02019;" },
2376     { "rtri",	"&#x025B9;" },
2377     { "rtrif",	"&#x025B8;" },
2378     { "rx",	"&#x0211E;" },
2379     { "sext",	"&#x02736;" },
2380     { "sharp",	"&#x0266F;" },
2381     { "spades",	"&#x02660;" },
2382     { "squ",	"&#x025A1;" },
2383     { "squf",	"&#x025AA;" },
2384     { "star",	"&#x02606;" },
2385     { "starf",	"&#x02605;" },
2386     { "target",	"&#x02316;" },
2387     { "telrec",	"&#x02315;" },
2388     { "thinsp",	"&#x02009;" },
2389     { "uhblk",	"&#x02580;" },
2390     { "ulcrop",	"&#x0230F;" },
2391     { "urcrop",	"&#x0230E;" },
2392     { "utri",	"&#x025B5;" },
2393     { "utrif",	"&#x025B4;" },
2394     { "vellip",	"&#x022EE;" },
2395     { "af",	"&#x02061;" },
2396     { "asympeq",	"&#x0224D;" },
2397     { "Cross",	"&#x02A2F;" },
2398     { "DD",	"&#x02145;" },
2399     { "dd",	"&#x02146;" },
2400     { "DownArrowBar",	"&#x02913;" },
2401     { "DownBreve",	"&#x00311;" },
2402     { "DownLeftRightVector",	"&#x02950;" },
2403     { "DownLeftTeeVector",	"&#x0295E;" },
2404     { "DownLeftVectorBar",	"&#x02956;" },
2405     { "DownRightTeeVector",	"&#x0295F;" },
2406     { "DownRightVectorBar",	"&#x02957;" },
2407     { "ee",	"&#x02147;" },
2408     { "EmptySmallSquare",	"&#x025FB;" },
2409     { "EmptyVerySmallSquare",	"&#x025AB;" },
2410     { "Equal",	"&#x02A75;" },
2411     { "FilledSmallSquare",	"&#x025FC;" },
2412     { "FilledVerySmallSquare",	"&#x025AA;" },
2413     { "GreaterGreater",	"&#x02AA2;" },
2414     { "Hat",	"&#x0005E;" },
2415     { "HorizontalLine",	"&#x02500;" },
2416     { "ic",	"&#x02063;" },
2417     { "ii",	"&#x02148;" },
2418     { "it",	"&#x02062;" },
2419     { "larrb",	"&#x021E4;" },
2420     { "LeftDownTeeVector",	"&#x02961;" },
2421     { "LeftDownVectorBar",	"&#x02959;" },
2422     { "LeftRightVector",	"&#x0294E;" },
2423     { "LeftTeeVector",	"&#x0295A;" },
2424     { "LeftTriangleBar",	"&#x029CF;" },
2425     { "LeftUpDownVector",	"&#x02951;" },
2426     { "LeftUpTeeVector",	"&#x02960;" },
2427     { "LeftUpVectorBar",	"&#x02958;" },
2428     { "LeftVectorBar",	"&#x02952;" },
2429     { "LessLess",	"&#x02AA1;" },
2430     { "mapstodown",	"&#x021A7;" },
2431     { "mapstoleft",	"&#x021A4;" },
2432     { "mapstoup",	"&#x021A5;" },
2433     { "MediumSpace",	"&#x0205F;" },
2434     { "nbump",	"&#x0224E;&#x00338;" },
2435     { "nbumpe",	"&#x0224F;&#x00338;" },
2436     { "nesim",	"&#x02242;&#x00338;" },
2437     { "NewLine",	"&#x0000A;" },
2438     { "NoBreak",	"&#x02060;" },
2439     { "NotCupCap",	"&#x0226D;" },
2440     { "NotHumpEqual",	"&#x0224F;&#x00338;" },
2441     { "NotLeftTriangleBar",	"&#x029CF;&#x00338;" },
2442     { "NotNestedGreaterGreater",	"&#x02AA2;&#x00338;" },
2443     { "NotNestedLessLess",	"&#x02AA1;&#x00338;" },
2444     { "NotRightTriangleBar",	"&#x029D0;&#x00338;" },
2445     { "NotSquareSubset",	"&#x0228F;&#x00338;" },
2446     { "NotSquareSuperset",	"&#x02290;&#x00338;" },
2447     { "NotSucceedsTilde",	"&#x0227F;&#x00338;" },
2448     { "OverBar",	"&#x000AF;" },
2449     { "OverBrace",	"&#x0FE37;" },
2450     { "OverBracket",	"&#x023B4;" },
2451     { "OverParenthesis",	"&#x0FE35;" },
2452     { "planckh",	"&#x0210E;" },
2453     { "Product",	"&#x0220F;" },
2454     { "rarrb",	"&#x021E5;" },
2455     { "RightDownTeeVector",	"&#x0295D;" },
2456     { "RightDownVectorBar",	"&#x02955;" },
2457     { "RightTeeVector",	"&#x0295B;" },
2458     { "RightTriangleBar",	"&#x029D0;" },
2459     { "RightUpDownVector",	"&#x0294F;" },
2460     { "RightUpTeeVector",	"&#x0295C;" },
2461     { "RightUpVectorBar",	"&#x02954;" },
2462     { "RightVectorBar",	"&#x02953;" },
2463     { "RoundImplies",	"&#x02970;" },
2464     { "RuleDelayed",	"&#x029F4;" },
2465     { "Tab",	"&#x00009;" },
2466     { "ThickSpace",	"&#x02009;&#x0200A;&#x0200A;" },
2467     { "UnderBar",	"&#x00332;" },
2468     { "UnderBrace",	"&#x0FE38;" },
2469     { "UnderBracket",	"&#x023B5;" },
2470     { "UnderParenthesis",	"&#x0FE36;" },
2471     { "UpArrowBar",	"&#x02912;" },
2472     { "Upsilon",	"&#x003A5;" },
2473     { "VerticalLine",	"&#x0007C;" },
2474     { "VerticalSeparator",	"&#x02758;" },
2475     { "ZeroWidthSpace",	"&#x0200B;" },
2476     { "angle",	"&#x02220;" },
2477     { "ApplyFunction",	"&#x02061;" },
2478     { "approx",	"&#x02248;" },
2479     { "approxeq",	"&#x0224A;" },
2480     { "Assign",	"&#x02254;" },
2481     { "backcong",	"&#x0224C;" },
2482     { "backepsilon",	"&#x003F6;" },
2483     { "backprime",	"&#x02035;" },
2484     { "backsim",	"&#x0223D;" },
2485     { "backsimeq",	"&#x022CD;" },
2486     { "Backslash",	"&#x02216;" },
2487     { "barwedge",	"&#x02305;" },
2488     { "Because",	"&#x02235;" },
2489     { "because",	"&#x02235;" },
2490     { "Bernoullis",	"&#x0212C;" },
2491     { "between",	"&#x0226C;" },
2492     { "bigcap",	"&#x022C2;" },
2493     { "bigcirc",	"&#x025EF;" },
2494     { "bigcup",	"&#x022C3;" },
2495     { "bigodot",	"&#x02A00;" },
2496     { "bigoplus",	"&#x02A01;" },
2497     { "bigotimes",	"&#x02A02;" },
2498     { "bigsqcup",	"&#x02A06;" },
2499     { "bigstar",	"&#x02605;" },
2500     { "bigtriangledown",	"&#x025BD;" },
2501     { "bigtriangleup",	"&#x025B3;" },
2502     { "biguplus",	"&#x02A04;" },
2503     { "bigvee",	"&#x022C1;" },
2504     { "bigwedge",	"&#x022C0;" },
2505     { "bkarow",	"&#x0290D;" },
2506     { "blacklozenge",	"&#x029EB;" },
2507     { "blacksquare",	"&#x025AA;" },
2508     { "blacktriangle",	"&#x025B4;" },
2509     { "blacktriangledown",	"&#x025BE;" },
2510     { "blacktriangleleft",	"&#x025C2;" },
2511     { "blacktriangleright",	"&#x025B8;" },
2512     { "bot",	"&#x022A5;" },
2513     { "boxminus",	"&#x0229F;" },
2514     { "boxplus",	"&#x0229E;" },
2515     { "boxtimes",	"&#x022A0;" },
2516     { "Breve",	"&#x002D8;" },
2517     { "bullet",	"&#x02022;" },
2518     { "Bumpeq",	"&#x0224E;" },
2519     { "bumpeq",	"&#x0224F;" },
2520     { "CapitalDifferentialD",	"&#x02145;" },
2521     { "Cayleys",	"&#x0212D;" },
2522     { "Cedilla",	"&#x000B8;" },
2523     { "CenterDot",	"&#x000B7;" },
2524     { "centerdot",	"&#x000B7;" },
2525     { "checkmark",	"&#x02713;" },
2526     { "circeq",	"&#x02257;" },
2527     { "circlearrowleft",	"&#x021BA;" },
2528     { "circlearrowright",	"&#x021BB;" },
2529     { "circledast",	"&#x0229B;" },
2530     { "circledcirc",	"&#x0229A;" },
2531     { "circleddash",	"&#x0229D;" },
2532     { "CircleDot",	"&#x02299;" },
2533     { "circledR",	"&#x000AE;" },
2534     { "circledS",	"&#x024C8;" },
2535     { "CircleMinus",	"&#x02296;" },
2536     { "CirclePlus",	"&#x02295;" },
2537     { "CircleTimes",	"&#x02297;" },
2538     { "ClockwiseContourIntegral",	"&#x02232;" },
2539     { "CloseCurlyDoubleQuote",	"&#x0201D;" },
2540     { "CloseCurlyQuote",	"&#x02019;" },
2541     { "clubsuit",	"&#x02663;" },
2542     { "coloneq",	"&#x02254;" },
2543     { "complement",	"&#x02201;" },
2544     { "complexes",	"&#x02102;" },
2545     { "Congruent",	"&#x02261;" },
2546     { "ContourIntegral",	"&#x0222E;" },
2547     { "Coproduct",	"&#x02210;" },
2548     { "CounterClockwiseContourIntegral",	"&#x02233;" },
2549     { "CupCap",	"&#x0224D;" },
2550     { "curlyeqprec",	"&#x022DE;" },
2551     { "curlyeqsucc",	"&#x022DF;" },
2552     { "curlyvee",	"&#x022CE;" },
2553     { "curlywedge",	"&#x022CF;" },
2554     { "curvearrowleft",	"&#x021B6;" },
2555     { "curvearrowright",	"&#x021B7;" },
2556     { "dbkarow",	"&#x0290F;" },
2557     { "ddagger",	"&#x02021;" },
2558     { "ddotseq",	"&#x02A77;" },
2559     { "Del",	"&#x02207;" },
2560     { "DiacriticalAcute",	"&#x000B4;" },
2561     { "DiacriticalDot",	"&#x002D9;" },
2562     { "DiacriticalDoubleAcute",	"&#x002DD;" },
2563     { "DiacriticalGrave",	"&#x00060;" },
2564     { "DiacriticalTilde",	"&#x002DC;" },
2565     { "Diamond",	"&#x022C4;" },
2566     { "diamond",	"&#x022C4;" },
2567     { "diamondsuit",	"&#x02666;" },
2568     { "DifferentialD",	"&#x02146;" },
2569     { "digamma",	"&#x003DD;" },
2570     { "div",	"&#x000F7;" },
2571     { "divideontimes",	"&#x022C7;" },
2572     { "doteq",	"&#x02250;" },
2573     { "doteqdot",	"&#x02251;" },
2574     { "DotEqual",	"&#x02250;" },
2575     { "dotminus",	"&#x02238;" },
2576     { "dotplus",	"&#x02214;" },
2577     { "dotsquare",	"&#x022A1;" },
2578     { "doublebarwedge",	"&#x02306;" },
2579     { "DoubleContourIntegral",	"&#x0222F;" },
2580     { "DoubleDot",	"&#x000A8;" },
2581     { "DoubleDownArrow",	"&#x021D3;" },
2582     { "DoubleLeftArrow",	"&#x021D0;" },
2583     { "DoubleLeftRightArrow",	"&#x021D4;" },
2584     { "DoubleLeftTee",	"&#x02AE4;" },
2585     { "DoubleLongLeftArrow",	"&#x027F8;" },
2586     { "DoubleLongLeftRightArrow",	"&#x027FA;" },
2587     { "DoubleLongRightArrow",	"&#x027F9;" },
2588     { "DoubleRightArrow",	"&#x021D2;" },
2589     { "DoubleRightTee",	"&#x022A8;" },
2590     { "DoubleUpArrow",	"&#x021D1;" },
2591     { "DoubleUpDownArrow",	"&#x021D5;" },
2592     { "DoubleVerticalBar",	"&#x02225;" },
2593     { "DownArrow",	"&#x02193;" },
2594     { "Downarrow",	"&#x021D3;" },
2595     { "downarrow",	"&#x02193;" },
2596     { "DownArrowUpArrow",	"&#x021F5;" },
2597     { "downdownarrows",	"&#x021CA;" },
2598     { "downharpoonleft",	"&#x021C3;" },
2599     { "downharpoonright",	"&#x021C2;" },
2600     { "DownLeftVector",	"&#x021BD;" },
2601     { "DownRightVector",	"&#x021C1;" },
2602     { "DownTee",	"&#x022A4;" },
2603     { "DownTeeArrow",	"&#x021A7;" },
2604     { "drbkarow",	"&#x02910;" },
2605     { "Element",	"&#x02208;" },
2606     { "emptyset",	"&#x02205;" },
2607     { "eqcirc",	"&#x02256;" },
2608     { "eqcolon",	"&#x02255;" },
2609     { "eqsim",	"&#x02242;" },
2610     { "eqslantgtr",	"&#x02A96;" },
2611     { "eqslantless",	"&#x02A95;" },
2612     { "EqualTilde",	"&#x02242;" },
2613     { "Equilibrium",	"&#x021CC;" },
2614     { "Exists",	"&#x02203;" },
2615     { "expectation",	"&#x02130;" },
2616     { "ExponentialE",	"&#x02147;" },
2617     { "exponentiale",	"&#x02147;" },
2618     { "fallingdotseq",	"&#x02252;" },
2619     { "ForAll",	"&#x02200;" },
2620     { "Fouriertrf",	"&#x02131;" },
2621     { "geq",	"&#x02265;" },
2622     { "geqq",	"&#x02267;" },
2623     { "geqslant",	"&#x02A7E;" },
2624     { "gg",	"&#x0226B;" },
2625     { "ggg",	"&#x022D9;" },
2626     { "gnapprox",	"&#x02A8A;" },
2627     { "gneq",	"&#x02A88;" },
2628     { "gneqq",	"&#x02269;" },
2629     { "GreaterEqual",	"&#x02265;" },
2630     { "GreaterEqualLess",	"&#x022DB;" },
2631     { "GreaterFullEqual",	"&#x02267;" },
2632     { "GreaterLess",	"&#x02277;" },
2633     { "GreaterSlantEqual",	"&#x02A7E;" },
2634     { "GreaterTilde",	"&#x02273;" },
2635     { "gtrapprox",	"&#x02A86;" },
2636     { "gtrdot",	"&#x022D7;" },
2637     { "gtreqless",	"&#x022DB;" },
2638     { "gtreqqless",	"&#x02A8C;" },
2639     { "gtrless",	"&#x02277;" },
2640     { "gtrsim",	"&#x02273;" },
2641     { "gvertneqq",	"&#x02269;&#x0FE00;" },
2642     { "Hacek",	"&#x002C7;" },
2643     { "hbar",	"&#x0210F;" },
2644     { "heartsuit",	"&#x02665;" },
2645     { "HilbertSpace",	"&#x0210B;" },
2646     { "hksearow",	"&#x02925;" },
2647     { "hkswarow",	"&#x02926;" },
2648     { "hookleftarrow",	"&#x021A9;" },
2649     { "hookrightarrow",	"&#x021AA;" },
2650     { "hslash",	"&#x0210F;" },
2651     { "HumpDownHump",	"&#x0224E;" },
2652     { "HumpEqual",	"&#x0224F;" },
2653     { "iiiint",	"&#x02A0C;" },
2654     { "iiint",	"&#x0222D;" },
2655     { "Im",	"&#x02111;" },
2656     { "ImaginaryI",	"&#x02148;" },
2657     { "imagline",	"&#x02110;" },
2658     { "imagpart",	"&#x02111;" },
2659     { "Implies",	"&#x021D2;" },
2660     { "in",	"&#x02208;" },
2661     { "integers",	"&#x02124;" },
2662     { "Integral",	"&#x0222B;" },
2663     { "intercal",	"&#x022BA;" },
2664     { "Intersection",	"&#x022C2;" },
2665     { "intprod",	"&#x02A3C;" },
2666     { "InvisibleComma",	"&#x02063;" },
2667     { "InvisibleTimes",	"&#x02062;" },
2668     { "langle",	"&#x02329;" },
2669     { "Laplacetrf",	"&#x02112;" },
2670     { "lbrace",	"&#x0007B;" },
2671     { "lbrack",	"&#x0005B;" },
2672     { "LeftAngleBracket",	"&#x02329;" },
2673     { "LeftArrow",	"&#x02190;" },
2674     { "Leftarrow",	"&#x021D0;" },
2675     { "leftarrow",	"&#x02190;" },
2676     { "LeftArrowBar",	"&#x021E4;" },
2677     { "LeftArrowRightArrow",	"&#x021C6;" },
2678     { "leftarrowtail",	"&#x021A2;" },
2679     { "LeftCeiling",	"&#x02308;" },
2680     { "LeftDoubleBracket",	"&#x0301A;" },
2681     { "LeftDownVector",	"&#x021C3;" },
2682     { "LeftFloor",	"&#x0230A;" },
2683     { "leftharpoondown",	"&#x021BD;" },
2684     { "leftharpoonup",	"&#x021BC;" },
2685     { "leftleftarrows",	"&#x021C7;" },
2686     { "LeftRightArrow",	"&#x02194;" },
2687     { "Leftrightarrow",	"&#x021D4;" },
2688     { "leftrightarrow",	"&#x02194;" },
2689     { "leftrightarrows",	"&#x021C6;" },
2690     { "leftrightharpoons",	"&#x021CB;" },
2691     { "leftrightsquigarrow",	"&#x021AD;" },
2692     { "LeftTee",	"&#x022A3;" },
2693     { "LeftTeeArrow",	"&#x021A4;" },
2694     { "leftthreetimes",	"&#x022CB;" },
2695     { "LeftTriangle",	"&#x022B2;" },
2696     { "LeftTriangleEqual",	"&#x022B4;" },
2697     { "LeftUpVector",	"&#x021BF;" },
2698     { "LeftVector",	"&#x021BC;" },
2699     { "leq",	"&#x02264;" },
2700     { "leqq",	"&#x02266;" },
2701     { "leqslant",	"&#x02A7D;" },
2702     { "lessapprox",	"&#x02A85;" },
2703     { "lessdot",	"&#x022D6;" },
2704     { "lesseqgtr",	"&#x022DA;" },
2705     { "lesseqqgtr",	"&#x02A8B;" },
2706     { "LessEqualGreater",	"&#x022DA;" },
2707     { "LessFullEqual",	"&#x02266;" },
2708     { "LessGreater",	"&#x02276;" },
2709     { "lessgtr",	"&#x02276;" },
2710     { "lesssim",	"&#x02272;" },
2711     { "LessSlantEqual",	"&#x02A7D;" },
2712     { "LessTilde",	"&#x02272;" },
2713     { "ll",	"&#x0226A;" },
2714     { "llcorner",	"&#x0231E;" },
2715     { "Lleftarrow",	"&#x021DA;" },
2716     { "lmoustache",	"&#x023B0;" },
2717     { "lnapprox",	"&#x02A89;" },
2718     { "lneq",	"&#x02A87;" },
2719     { "lneqq",	"&#x02268;" },
2720     { "LongLeftArrow",	"&#x027F5;" },
2721     { "Longleftarrow",	"&#x027F8;" },
2722     { "longleftarrow",	"&#x027F5;" },
2723     { "LongLeftRightArrow",	"&#x027F7;" },
2724     { "Longleftrightarrow",	"&#x027FA;" },
2725     { "longleftrightarrow",	"&#x027F7;" },
2726     { "longmapsto",	"&#x027FC;" },
2727     { "LongRightArrow",	"&#x027F6;" },
2728     { "Longrightarrow",	"&#x027F9;" },
2729     { "longrightarrow",	"&#x027F6;" },
2730     { "looparrowleft",	"&#x021AB;" },
2731     { "looparrowright",	"&#x021AC;" },
2732     { "LowerLeftArrow",	"&#x02199;" },
2733     { "LowerRightArrow",	"&#x02198;" },
2734     { "lozenge",	"&#x025CA;" },
2735     { "lrcorner",	"&#x0231F;" },
2736     { "Lsh",	"&#x021B0;" },
2737     { "lvertneqq",	"&#x02268;&#x0FE00;" },
2738     { "maltese",	"&#x02720;" },
2739     { "mapsto",	"&#x021A6;" },
2740     { "measuredangle",	"&#x02221;" },
2741     { "Mellintrf",	"&#x02133;" },
2742     { "MinusPlus",	"&#x02213;" },
2743     { "mp",	"&#x02213;" },
2744     { "multimap",	"&#x022B8;" },
2745     { "napprox",	"&#x02249;" },
2746     { "natural",	"&#x0266E;" },
2747     { "naturals",	"&#x02115;" },
2748     { "nearrow",	"&#x02197;" },
2749     { "NegativeMediumSpace",	"&#x0200B;" },
2750     { "NegativeThickSpace",	"&#x0200B;" },
2751     { "NegativeThinSpace",	"&#x0200B;" },
2752     { "NegativeVeryThinSpace",	"&#x0200B;" },
2753     { "NestedGreaterGreater",	"&#x0226B;" },
2754     { "NestedLessLess",	"&#x0226A;" },
2755     { "nexists",	"&#x02204;" },
2756     { "ngeq",	"&#x02271;" },
2757     { "ngeqq",	"&#x02267;&#x00338;" },
2758     { "ngeqslant",	"&#x02A7E;&#x00338;" },
2759     { "ngtr",	"&#x0226F;" },
2760     { "nLeftarrow",	"&#x021CD;" },
2761     { "nleftarrow",	"&#x0219A;" },
2762     { "nLeftrightarrow",	"&#x021CE;" },
2763     { "nleftrightarrow",	"&#x021AE;" },
2764     { "nleq",	"&#x02270;" },
2765     { "nleqq",	"&#x02266;&#x00338;" },
2766     { "nleqslant",	"&#x02A7D;&#x00338;" },
2767     { "nless",	"&#x0226E;" },
2768     { "NonBreakingSpace",	"&#x000A0;" },
2769     { "NotCongruent",	"&#x02262;" },
2770     { "NotDoubleVerticalBar",	"&#x02226;" },
2771     { "NotElement",	"&#x02209;" },
2772     { "NotEqual",	"&#x02260;" },
2773     { "NotEqualTilde",	"&#x02242;&#x00338;" },
2774     { "NotExists",	"&#x02204;" },
2775     { "NotGreater",	"&#x0226F;" },
2776     { "NotGreaterEqual",	"&#x02271;" },
2777     { "NotGreaterFullEqual",	"&#x02266;&#x00338;" },
2778     { "NotGreaterGreater",	"&#x0226B;&#x00338;" },
2779     { "NotGreaterLess",	"&#x02279;" },
2780     { "NotGreaterSlantEqual",	"&#x02A7E;&#x00338;" },
2781     { "NotGreaterTilde",	"&#x02275;" },
2782     { "NotHumpDownHump",	"&#x0224E;&#x00338;" },
2783     { "NotLeftTriangle",	"&#x022EA;" },
2784     { "NotLeftTriangleEqual",	"&#x022EC;" },
2785     { "NotLess",	"&#x0226E;" },
2786     { "NotLessEqual",	"&#x02270;" },
2787     { "NotLessGreater",	"&#x02278;" },
2788     { "NotLessLess",	"&#x0226A;&#x00338;" },
2789     { "NotLessSlantEqual",	"&#x02A7D;&#x00338;" },
2790     { "NotLessTilde",	"&#x02274;" },
2791     { "NotPrecedes",	"&#x02280;" },
2792     { "NotPrecedesEqual",	"&#x02AAF;&#x00338;" },
2793     { "NotPrecedesSlantEqual",	"&#x022E0;" },
2794     { "NotReverseElement",	"&#x0220C;" },
2795     { "NotRightTriangle",	"&#x022EB;" },
2796     { "NotRightTriangleEqual",	"&#x022ED;" },
2797     { "NotSquareSubsetEqual",	"&#x022E2;" },
2798     { "NotSquareSupersetEqual",	"&#x022E3;" },
2799     { "NotSubset",	"&#x02282;&#x020D2;" },
2800     { "NotSubsetEqual",	"&#x02288;" },
2801     { "NotSucceeds",	"&#x02281;" },
2802     { "NotSucceedsEqual",	"&#x02AB0;&#x00338;" },
2803     { "NotSucceedsSlantEqual",	"&#x022E1;" },
2804     { "NotSuperset",	"&#x02283;&#x020D2;" },
2805     { "NotSupersetEqual",	"&#x02289;" },
2806     { "NotTilde",	"&#x02241;" },
2807     { "NotTildeEqual",	"&#x02244;" },
2808     { "NotTildeFullEqual",	"&#x02247;" },
2809     { "NotTildeTilde",	"&#x02249;" },
2810     { "NotVerticalBar",	"&#x02224;" },
2811     { "nparallel",	"&#x02226;" },
2812     { "nprec",	"&#x02280;" },
2813     { "npreceq",	"&#x02AAF;&#x00338;" },
2814     { "nRightarrow",	"&#x021CF;" },
2815     { "nrightarrow",	"&#x0219B;" },
2816     { "nshortmid",	"&#x02224;" },
2817     { "nshortparallel",	"&#x02226;" },
2818     { "nsimeq",	"&#x02244;" },
2819     { "nsubset",	"&#x02282;&#x020D2;" },
2820     { "nsubseteq",	"&#x02288;" },
2821     { "nsubseteqq",	"&#x02AC5;&#x0338;" },
2822     { "nsucc",	"&#x02281;" },
2823     { "nsucceq",	"&#x02AB0;&#x00338;" },
2824     { "nsupset",	"&#x02283;&#x020D2;" },
2825     { "nsupseteq",	"&#x02289;" },
2826     { "nsupseteqq",	"&#x02AC6;&#x0338;" },
2827     { "ntriangleleft",	"&#x022EA;" },
2828     { "ntrianglelefteq",	"&#x022EC;" },
2829     { "ntriangleright",	"&#x022EB;" },
2830     { "ntrianglerighteq",	"&#x022ED;" },
2831     { "nwarrow",	"&#x02196;" },
2832     { "oint",	"&#x0222E;" },
2833     { "OpenCurlyDoubleQuote",	"&#x0201C;" },
2834     { "OpenCurlyQuote",	"&#x02018;" },
2835     { "orderof",	"&#x02134;" },
2836     { "parallel",	"&#x02225;" },
2837     { "PartialD",	"&#x02202;" },
2838     { "pitchfork",	"&#x022D4;" },
2839     { "PlusMinus",	"&#x000B1;" },
2840     { "pm",	"&#x000B1;" },
2841     { "Poincareplane",	"&#x0210C;" },
2842     { "prec",	"&#x0227A;" },
2843     { "precapprox",	"&#x02AB7;" },
2844     { "preccurlyeq",	"&#x0227C;" },
2845     { "Precedes",	"&#x0227A;" },
2846     { "PrecedesEqual",	"&#x02AAF;" },
2847     { "PrecedesSlantEqual",	"&#x0227C;" },
2848     { "PrecedesTilde",	"&#x0227E;" },
2849     { "preceq",	"&#x02AAF;" },
2850     { "precnapprox",	"&#x02AB9;" },
2851     { "precneqq",	"&#x02AB5;" },
2852     { "precnsim",	"&#x022E8;" },
2853     { "precsim",	"&#x0227E;" },
2854     { "primes",	"&#x02119;" },
2855     { "Proportion",	"&#x02237;" },
2856     { "Proportional",	"&#x0221D;" },
2857     { "propto",	"&#x0221D;" },
2858     { "quaternions",	"&#x0210D;" },
2859     { "questeq",	"&#x0225F;" },
2860     { "rangle",	"&#x0232A;" },
2861     { "rationals",	"&#x0211A;" },
2862     { "rbrace",	"&#x0007D;" },
2863     { "rbrack",	"&#x0005D;" },
2864     { "Re",	"&#x0211C;" },
2865     { "realine",	"&#x0211B;" },
2866     { "realpart",	"&#x0211C;" },
2867     { "reals",	"&#x0211D;" },
2868     { "ReverseElement",	"&#x0220B;" },
2869     { "ReverseEquilibrium",	"&#x021CB;" },
2870     { "ReverseUpEquilibrium",	"&#x0296F;" },
2871     { "RightAngleBracket",	"&#x0232A;" },
2872     { "RightArrow",	"&#x02192;" },
2873     { "Rightarrow",	"&#x021D2;" },
2874     { "rightarrow",	"&#x02192;" },
2875     { "RightArrowBar",	"&#x021E5;" },
2876     { "RightArrowLeftArrow",	"&#x021C4;" },
2877     { "rightarrowtail",	"&#x021A3;" },
2878     { "RightCeiling",	"&#x02309;" },
2879     { "RightDoubleBracket",	"&#x0301B;" },
2880     { "RightDownVector",	"&#x021C2;" },
2881     { "RightFloor",	"&#x0230B;" },
2882     { "rightharpoondown",	"&#x021C1;" },
2883     { "rightharpoonup",	"&#x021C0;" },
2884     { "rightleftarrows",	"&#x021C4;" },
2885     { "rightleftharpoons",	"&#x021CC;" },
2886     { "rightrightarrows",	"&#x021C9;" },
2887     { "rightsquigarrow",	"&#x0219D;" },
2888     { "RightTee",	"&#x022A2;" },
2889     { "RightTeeArrow",	"&#x021A6;" },
2890     { "rightthreetimes",	"&#x022CC;" },
2891     { "RightTriangle",	"&#x022B3;" },
2892     { "RightTriangleEqual",	"&#x022B5;" },
2893     { "RightUpVector",	"&#x021BE;" },
2894     { "RightVector",	"&#x021C0;" },
2895     { "risingdotseq",	"&#x02253;" },
2896     { "rmoustache",	"&#x023B1;" },
2897     { "Rrightarrow",	"&#x021DB;" },
2898     { "Rsh",	"&#x021B1;" },
2899     { "searrow",	"&#x02198;" },
2900     { "setminus",	"&#x02216;" },
2901     { "ShortDownArrow",	"&#x02193;" },
2902     { "ShortLeftArrow",	"&#x02190;" },
2903     { "shortmid",	"&#x02223;" },
2904     { "shortparallel",	"&#x02225;" },
2905     { "ShortRightArrow",	"&#x02192;" },
2906     { "ShortUpArrow",	"&#x02191;" },
2907     { "simeq",	"&#x02243;" },
2908     { "SmallCircle",	"&#x02218;" },
2909     { "smallsetminus",	"&#x02216;" },
2910     { "spadesuit",	"&#x02660;" },
2911     { "Sqrt",	"&#x0221A;" },
2912     { "sqsubset",	"&#x0228F;" },
2913     { "sqsubseteq",	"&#x02291;" },
2914     { "sqsupset",	"&#x02290;" },
2915     { "sqsupseteq",	"&#x02292;" },
2916     { "Square",	"&#x025A1;" },
2917     { "SquareIntersection",	"&#x02293;" },
2918     { "SquareSubset",	"&#x0228F;" },
2919     { "SquareSubsetEqual",	"&#x02291;" },
2920     { "SquareSuperset",	"&#x02290;" },
2921     { "SquareSupersetEqual",	"&#x02292;" },
2922     { "SquareUnion",	"&#x02294;" },
2923     { "Star",	"&#x022C6;" },
2924     { "straightepsilon",	"&#x003B5;" },
2925     { "straightphi",	"&#x003D5;" },
2926     { "Subset",	"&#x022D0;" },
2927     { "subset",	"&#x02282;" },
2928     { "subseteq",	"&#x02286;" },
2929     { "subseteqq",	"&#x02AC5;" },
2930     { "SubsetEqual",	"&#x02286;" },
2931     { "subsetneq",	"&#x0228A;" },
2932     { "subsetneqq",	"&#x02ACB;" },
2933     { "succ",	"&#x0227B;" },
2934     { "succapprox",	"&#x02AB8;" },
2935     { "succcurlyeq",	"&#x0227D;" },
2936     { "Succeeds",	"&#x0227B;" },
2937     { "SucceedsEqual",	"&#x02AB0;" },
2938     { "SucceedsSlantEqual",	"&#x0227D;" },
2939     { "SucceedsTilde",	"&#x0227F;" },
2940     { "succeq",	"&#x02AB0;" },
2941     { "succnapprox",	"&#x02ABA;" },
2942     { "succneqq",	"&#x02AB6;" },
2943     { "succnsim",	"&#x022E9;" },
2944     { "succsim",	"&#x0227F;" },
2945     { "SuchThat",	"&#x0220B;" },
2946     { "Sum",	"&#x02211;" },
2947     { "Superset",	"&#x02283;" },
2948     { "SupersetEqual",	"&#x02287;" },
2949     { "Supset",	"&#x022D1;" },
2950     { "supset",	"&#x02283;" },
2951     { "supseteq",	"&#x02287;" },
2952     { "supseteqq",	"&#x02AC6;" },
2953     { "supsetneq",	"&#x0228B;" },
2954     { "supsetneqq",	"&#x02ACC;" },
2955     { "swarrow",	"&#x02199;" },
2956     { "Therefore",	"&#x02234;" },
2957     { "therefore",	"&#x02234;" },
2958     { "thickapprox",	"&#x02248;" },
2959     { "thicksim",	"&#x0223C;" },
2960     { "ThinSpace",	"&#x02009;" },
2961     { "Tilde",	"&#x0223C;" },
2962     { "TildeEqual",	"&#x02243;" },
2963     { "TildeFullEqual",	"&#x02245;" },
2964     { "TildeTilde",	"&#x02248;" },
2965     { "toea",	"&#x02928;" },
2966     { "tosa",	"&#x02929;" },
2967     { "triangle",	"&#x025B5;" },
2968     { "triangledown",	"&#x025BF;" },
2969     { "triangleleft",	"&#x025C3;" },
2970     { "trianglelefteq",	"&#x022B4;" },
2971     { "triangleq",	"&#x0225C;" },
2972     { "triangleright",	"&#x025B9;" },
2973     { "trianglerighteq",	"&#x022B5;" },
2974     { "TripleDot",	"&#x020DB;" },
2975     { "twoheadleftarrow",	"&#x0219E;" },
2976     { "twoheadrightarrow",	"&#x021A0;" },
2977     { "ulcorner",	"&#x0231C;" },
2978     { "Union",	"&#x022C3;" },
2979     { "UnionPlus",	"&#x0228E;" },
2980     { "UpArrow",	"&#x02191;" },
2981     { "Uparrow",	"&#x021D1;" },
2982     { "uparrow",	"&#x02191;" },
2983     { "UpArrowDownArrow",	"&#x021C5;" },
2984     { "UpDownArrow",	"&#x02195;" },
2985     { "Updownarrow",	"&#x021D5;" },
2986     { "updownarrow",	"&#x02195;" },
2987     { "UpEquilibrium",	"&#x0296E;" },
2988     { "upharpoonleft",	"&#x021BF;" },
2989     { "upharpoonright",	"&#x021BE;" },
2990     { "UpperLeftArrow",	"&#x02196;" },
2991     { "UpperRightArrow",	"&#x02197;" },
2992     { "upsilon",	"&#x003C5;" },
2993     { "UpTee",	"&#x022A5;" },
2994     { "UpTeeArrow",	"&#x021A5;" },
2995     { "upuparrows",	"&#x021C8;" },
2996     { "urcorner",	"&#x0231D;" },
2997     { "varepsilon",	"&#x0025B;" },
2998     { "varkappa",	"&#x003F0;" },
2999     { "varnothing",	"&#x02205;" },
3000     { "varphi",	"&#x003C6;" },
3001     { "varpi",	"&#x003D6;" },
3002     { "varpropto",	"&#x0221D;" },
3003     { "varrho",	"&#x003F1;" },
3004     { "varsigma",	"&#x003C2;" },
3005     { "varsubsetneq",	"&#x0228A;&#x0FE00;" },
3006     { "varsubsetneqq",	"&#x02ACB;&#x0FE00;" },
3007     { "varsupsetneq",	"&#x0228B;&#x0FE00;" },
3008     { "varsupsetneqq",	"&#x02ACC;&#x0FE00;" },
3009     { "vartheta",	"&#x003D1;" },
3010     { "vartriangleleft",	"&#x022B2;" },
3011     { "vartriangleright",	"&#x022B3;" },
3012     { "Vee",	"&#x022C1;" },
3013     { "vee",	"&#x02228;" },
3014     { "Vert",	"&#x02016;" },
3015     { "vert",	"&#x0007C;" },
3016     { "VerticalBar",	"&#x02223;" },
3017     { "VerticalTilde",	"&#x02240;" },
3018     { "VeryThinSpace",	"&#x0200A;" },
3019     { "Wedge",	"&#x022C0;" },
3020     { "wedge",	"&#x02227;" },
3021     { "wp",	"&#x02118;" },
3022     { "wr",	"&#x02240;" },
3023     { "zeetrf",	"&#x02128;" },
3024     { 0, 0 }
3025 };
3026 
3027 // *******************************************************************
3028 // MmlDocument
3029 // *******************************************************************
3030 
fontName(QtMmlWidget::MmlFont type) const3031 QString MmlDocument::fontName(QtMmlWidget::MmlFont type) const
3032 {
3033     switch (type) {
3034 	case QtMmlWidget::NormalFont:
3035 	    return m_normal_font_name;
3036 	case QtMmlWidget::FrakturFont:
3037 	    return m_fraktur_font_name;
3038 	case QtMmlWidget::SansSerifFont:
3039 	    return m_sans_serif_font_name;
3040 	case QtMmlWidget::ScriptFont:
3041 	    return m_script_font_name;
3042 	case QtMmlWidget::MonospaceFont:
3043 	    return m_monospace_font_name;
3044 	case QtMmlWidget::DoublestruckFont:
3045 	    return m_doublestruck_font_name;
3046     };
3047 
3048     return QString();
3049 }
3050 
setFontName(QtMmlWidget::MmlFont type,const QString & name)3051 void MmlDocument::setFontName(QtMmlWidget::MmlFont type, const QString &name)
3052 {
3053     switch (type) {
3054 	case QtMmlWidget::NormalFont:
3055 	    m_normal_font_name = name;
3056 	    break;
3057 	case QtMmlWidget::FrakturFont:
3058 	    m_fraktur_font_name = name;
3059 	    break;
3060 	case QtMmlWidget::SansSerifFont:
3061 	    m_sans_serif_font_name = name;
3062 	    break;
3063 	case QtMmlWidget::ScriptFont:
3064 	    m_script_font_name = name;
3065 	    break;
3066 	case QtMmlWidget::MonospaceFont:
3067 	    m_monospace_font_name = name;
3068 	    break;
3069 	case QtMmlWidget::DoublestruckFont:
3070 	    m_doublestruck_font_name = name;
3071 	    break;
3072     };
3073 }
3074 
domToMmlNodeType(const QDomNode & dom_node)3075 Mml::NodeType domToMmlNodeType(const QDomNode &dom_node)
3076 {
3077     Mml::NodeType mml_type = Mml::NoNode;
3078 
3079     switch (dom_node.nodeType()) {
3080 	case QDomNode::ElementNode: {
3081 	    QString tag = dom_node.nodeName();
3082 	    const NodeSpec *spec = mmlFindNodeSpec(tag);
3083 
3084 	    // treat urecognised tags as mrow
3085 	    if (spec == 0)
3086 		mml_type = Mml::UnknownNode;
3087 	    else
3088 		mml_type = spec->type;
3089 
3090 	    break;
3091 	}
3092 	case QDomNode::TextNode:
3093 	    mml_type = Mml::TextNode;
3094 	    break;
3095 
3096 	case QDomNode::DocumentNode:
3097 	    mml_type = Mml::MrowNode;
3098 	    break;
3099 
3100 	case QDomNode::EntityReferenceNode:
3101 //	    qWarning("EntityReferenceNode: name=\"" + dom_node.nodeName() + "\" value=\"" + dom_node.nodeValue() + "\"");
3102 	    break;
3103 
3104 	case QDomNode::AttributeNode:
3105 	case QDomNode::CDATASectionNode:
3106 	case QDomNode::EntityNode:
3107 	case QDomNode::ProcessingInstructionNode:
3108 	case QDomNode::CommentNode:
3109 	case QDomNode::DocumentTypeNode:
3110 	case QDomNode::DocumentFragmentNode:
3111 	case QDomNode::NotationNode:
3112 	case QDomNode::BaseNode:
3113 	case QDomNode::CharacterDataNode:
3114 	    break;
3115     }
3116 
3117     return mml_type;
3118 }
3119 
3120 
MmlDocument()3121 MmlDocument::MmlDocument()
3122 {
3123     m_root_node = 0;
3124 
3125     // Some defaults which happen to work on my computer,
3126     // but probably won't work on other's
3127 #if defined(Q_WS_WIN)
3128     m_normal_font_name = "Times New Roman";
3129 #else
3130     m_normal_font_name = "Century Schoolbook L";
3131 #endif
3132     m_fraktur_font_name = "Fraktur";
3133     m_sans_serif_font_name = "Luxi Sans";
3134     m_script_font_name = "Urw Chancery L";
3135     m_monospace_font_name = "Luxi Mono";
3136     m_doublestruck_font_name = "Doublestruck";
3137     m_base_font_point_size = 16;
3138     m_foreground_color = Qt::black;
3139     m_background_color = Qt::white;
3140 }
3141 
~MmlDocument()3142 MmlDocument::~MmlDocument()
3143 {
3144     clear();
3145 }
3146 
clear()3147 void MmlDocument::clear()
3148 {
3149     delete m_root_node;
3150     m_root_node = 0;
3151 }
3152 
dump() const3153 void MmlDocument::dump() const
3154 {
3155     if (m_root_node == 0)
3156     	return;
3157 
3158     QString indent;
3159     _dump(m_root_node, indent);
3160 }
3161 
_dump(const MmlNode * node,QString & indent) const3162 void MmlDocument::_dump(const MmlNode *node, QString &indent) const
3163 {
3164     if (node == 0) return;
3165 
3166     qWarning("%s", (indent + node->toStr()).toLatin1().data());
3167 
3168     indent += "  ";
3169     const MmlNode *child = node->firstChild();
3170     for (; child != 0; child = child->nextSibling())
3171 	_dump(child, indent);
3172     indent.truncate(indent.length() - 2);
3173 }
3174 
setContent(QString text,QString * errorMsg,int * errorLine,int * errorColumn)3175 bool MmlDocument::setContent(QString text, QString *errorMsg,
3176 				    int *errorLine, int *errorColumn)
3177 {
3178     clear();
3179 
3180     QString prefix = "<?xml version=\"2.0\"?>\n";
3181     prefix.append(entityDeclarations());
3182 
3183     uint prefix_lines = 0;
3184     for (int i = 0; i < prefix.length(); ++i) {
3185 	if (prefix.at(i) == '\n')
3186 	    ++prefix_lines;
3187     }
3188 
3189     QDomDocument dom;
3190     if (!dom.setContent(prefix + text, false, errorMsg, errorLine, errorColumn)) {
3191 	if (errorLine != 0)
3192 	    *errorLine -= prefix_lines;
3193 	return false;
3194     }
3195 
3196     // we don't have access to line info from now on
3197     if (errorLine != 0) *errorLine = -1;
3198     if (errorColumn != 0) *errorColumn = -1;
3199 
3200     bool ok;
3201     MmlNode *root_node = domToMml(dom, &ok, errorMsg);
3202     if (!ok)
3203 	return false;
3204 
3205     if (root_node == 0) {
3206 	if (errorMsg != 0)
3207 	    *errorMsg = "empty document";
3208 	return false;
3209     }
3210 
3211     insertChild(0, root_node, 0);
3212     layout();
3213 
3214 /*    QFile of("/tmp/dump.xml");
3215     of.open(IO_WriteOnly);
3216     QTextStream os(&of);
3217     os.setEncoding(QTextStream::UnicodeUTF8);
3218     os << dom.toString(); */
3219 
3220     return true;
3221 }
3222 
layout()3223 void MmlDocument::layout()
3224 {
3225     if (m_root_node == 0)
3226     	return;
3227 
3228     m_root_node->layout();
3229     m_root_node->stretch();
3230 //    dump();
3231 }
3232 
insertChild(MmlNode * parent,MmlNode * new_node,QString * errorMsg)3233 bool MmlDocument::insertChild(MmlNode *parent, MmlNode *new_node,
3234 				QString *errorMsg)
3235 {
3236     if (new_node == 0)
3237 	return true;
3238 
3239     Q_ASSERT(new_node->parent() == 0
3240 		&& new_node->nextSibling() == 0
3241 		&& new_node->previousSibling() == 0);
3242 
3243     if (parent != 0) {
3244 	if (!mmlCheckChildType(parent->nodeType(), new_node->nodeType(), errorMsg))
3245 	    return false;
3246     }
3247 
3248     if (parent == 0) {
3249 	if (m_root_node == 0)
3250 	    m_root_node = new_node;
3251 	else {
3252 	    MmlNode *n = m_root_node->lastSibling();
3253 	    n->m_next_sibling = new_node;
3254 	    new_node->m_previous_sibling = n;
3255 	}
3256     }
3257     else {
3258 	new_node->m_parent = parent;
3259 	if (parent->hasChildNodes()) {
3260 	    MmlNode *n = parent->firstChild()->lastSibling();
3261 	    n->m_next_sibling = new_node;
3262 	    new_node->m_previous_sibling = n;
3263 	}
3264 	else parent->m_first_child = new_node;
3265     }
3266 
3267     return true;
3268 }
3269 
createNode(NodeType type,const MmlAttributeMap & mml_attr,const QString & mml_value,QString * errorMsg)3270 MmlNode *MmlDocument::createNode(NodeType type,
3271 				    const MmlAttributeMap &mml_attr,
3272 				    const QString &mml_value,
3273 				    QString *errorMsg)
3274 {
3275     Q_ASSERT(type != NoNode);
3276 
3277     MmlNode *mml_node = 0;
3278 
3279     if (!mmlCheckAttributes(type, mml_attr, errorMsg))
3280 	return 0;
3281 
3282     switch (type) {
3283 	case MiNode:
3284 	    mml_node = new MmlMiNode(this, mml_attr);
3285 	    break;
3286 	case MnNode:
3287 	    mml_node = new MmlMnNode(this, mml_attr);
3288 	    break;
3289 	case MfracNode:
3290 	    mml_node = new MmlMfracNode(this, mml_attr);
3291 	    break;
3292 	case MrowNode:
3293 	    mml_node = new MmlMrowNode(this, mml_attr);
3294 	    break;
3295 	case MsqrtNode:
3296 	    mml_node = new MmlMsqrtNode(this, mml_attr);
3297 	    break;
3298 	case MrootNode:
3299 	    mml_node = new MmlMrootNode(this, mml_attr);
3300 	    break;
3301 	case MsupNode:
3302 	    mml_node = new MmlMsupNode(this, mml_attr);
3303 	    break;
3304 	case MsubNode:
3305 	    mml_node = new MmlMsubNode(this, mml_attr);
3306 	    break;
3307 	case MsubsupNode:
3308 	    mml_node = new MmlMsubsupNode(this, mml_attr);
3309 	    break;
3310 	case MoNode:
3311 	    mml_node = new MmlMoNode(this, mml_attr);
3312 	    break;
3313 	case MstyleNode:
3314 	    mml_node = new MmlMstyleNode(this, mml_attr);
3315 	    break;
3316 	case TextNode:
3317 	    mml_node = new MmlTextNode(mml_value, this);
3318 	    break;
3319 	case MphantomNode:
3320 	    mml_node = new MmlMphantomNode(this, mml_attr);
3321 	    break;
3322 	case MfencedNode:
3323 	    mml_node = new MmlMfencedNode(this, mml_attr);
3324 	    break;
3325 	case MtableNode:
3326 	    mml_node = new MmlMtableNode(this, mml_attr);
3327 	    break;
3328 	case MtrNode:
3329 	    mml_node = new MmlMtrNode(this, mml_attr);
3330 	    break;
3331 	case MtdNode:
3332 	    mml_node = new MmlMtdNode(this, mml_attr);
3333 	    break;
3334 	case MoverNode:
3335 	    mml_node = new MmlMoverNode(this, mml_attr);
3336 	    break;
3337 	case MunderNode:
3338 	    mml_node = new MmlMunderNode(this, mml_attr);
3339 	    break;
3340 	case MunderoverNode:
3341 	    mml_node = new MmlMunderoverNode(this, mml_attr);
3342 	    break;
3343 	case MalignMarkNode:
3344 	    mml_node = new MmlMalignMarkNode(this);
3345 	    break;
3346 	case MerrorNode:
3347 	    mml_node = new MmlMerrorNode(this, mml_attr);
3348 	    break;
3349 	case MtextNode:
3350 	    mml_node = new MmlMtextNode(this, mml_attr);
3351 	    break;
3352 	case MpaddedNode:
3353 	    mml_node = new MmlMpaddedNode(this, mml_attr);
3354 	    break;
3355 	case MspaceNode:
3356 	    mml_node = new MmlMspaceNode(this, mml_attr);
3357 	    break;
3358 	case UnknownNode:
3359 	    mml_node = new MmlUnknownNode(this, mml_attr);
3360 	    break;
3361 	case NoNode:
3362 	    mml_node = 0;
3363 	    break;
3364     }
3365 
3366     return mml_node;
3367 }
3368 
insertOperator(MmlNode * node,const QString & text)3369 void MmlDocument::insertOperator(MmlNode *node, const QString &text)
3370 {
3371     MmlNode *text_node = createNode(TextNode, MmlAttributeMap(), text, 0);
3372     MmlNode *mo_node = createNode(MoNode, MmlAttributeMap(), QString(), 0);
3373 
3374     bool ok = insertChild(node, mo_node, 0);
3375     Q_ASSERT( ok );
3376     ok = insertChild(mo_node, text_node, 0);
3377     Q_ASSERT( ok );
3378 }
3379 
domToMml(const QDomNode & dom_node,bool * ok,QString * errorMsg)3380 MmlNode *MmlDocument::domToMml(const QDomNode &dom_node, bool *ok, QString *errorMsg)
3381 {
3382     // create the node
3383 
3384     Q_ASSERT(ok != 0);
3385 
3386     NodeType mml_type = domToMmlNodeType(dom_node);
3387 
3388     if (mml_type == NoNode) {
3389 	*ok = true;
3390 	return 0;
3391     }
3392 
3393     QDomNamedNodeMap dom_attr = dom_node.attributes();
3394     MmlAttributeMap mml_attr;
3395     for (int i = 0; i < int(dom_attr.length()); ++i) {
3396 	QDomNode attr_node = dom_attr.item(i);
3397 	Q_ASSERT(!attr_node.nodeName().isNull());
3398 	Q_ASSERT(!attr_node.nodeValue().isNull());
3399 	mml_attr[attr_node.nodeName()] = attr_node.nodeValue();
3400     }
3401 
3402     QString mml_value;
3403     if (mml_type == TextNode)
3404 	mml_value = dom_node.nodeValue();
3405     MmlNode *mml_node = createNode(mml_type, mml_attr, mml_value, errorMsg);
3406     if (mml_node == 0) {
3407 	*ok = false;
3408 	return 0;
3409     }
3410 
3411     // create the node's children according to the child_spec
3412 
3413     const NodeSpec *spec = mmlFindNodeSpec(mml_type);
3414     QDomNodeList dom_child_list = dom_node.childNodes();
3415     int child_cnt = dom_child_list.count();
3416     MmlNode *mml_child = 0;
3417 
3418     QString separator_list;
3419     if (mml_type == MfencedNode)
3420 	separator_list = mml_node->explicitAttribute("separators", ",");
3421 
3422     switch (spec->child_spec) {
3423 	case NodeSpec::ChildIgnore:
3424 	    break;
3425 
3426 	case NodeSpec::ImplicitMrow:
3427 
3428 	    if (child_cnt > 0) {
3429 		mml_child = createImplicitMrowNode(dom_node, ok, errorMsg);
3430 		if (!*ok) {
3431 		    delete mml_node;
3432 		    return 0;
3433 		}
3434 
3435 		if (!insertChild(mml_node, mml_child, errorMsg)) {
3436 		    delete mml_node;
3437 		    delete mml_child;
3438 		    *ok = false;
3439 		    return 0;
3440 		}
3441 	    }
3442 
3443 	    break;
3444 
3445 	default:
3446 	    // exact ammount of children specified - check...
3447 	    if (spec->child_spec != child_cnt) {
3448 		if (errorMsg != 0)
3449 		    *errorMsg = QString("element ")
3450 			+ spec->tag
3451 			+ " requires exactly "
3452 			+ QString::number(spec->child_spec)
3453 			+ " arguments, got "
3454 			+ QString::number(child_cnt);
3455 		delete mml_node;
3456 		*ok = false;
3457 		return 0;
3458 	}
3459 
3460 	// ...and continue just as in ChildAny
3461 
3462 	case NodeSpec::ChildAny:
3463 	    if (mml_type == MfencedNode)
3464 		insertOperator(mml_node, mml_node->explicitAttribute("open", "("));
3465 
3466 	    for (int i = 0; i < child_cnt; ++i) {
3467 		QDomNode dom_child = dom_child_list.item(i);
3468 
3469 		MmlNode *mml_child = domToMml(dom_child, ok, errorMsg);
3470 		if (!*ok) {
3471 		    delete mml_node;
3472 		    return 0;
3473 		}
3474 
3475 		if (mml_type == MtableNode && mml_child->nodeType() != MtrNode) {
3476 		    MmlNode *mtr_node = createNode(MtrNode, MmlAttributeMap(), QString(), 0);
3477 		    insertChild(mml_node, mtr_node, 0);
3478 		    if (!insertChild(mtr_node, mml_child, errorMsg)) {
3479 			delete mml_node;
3480 			delete mml_child;
3481 			*ok = false;
3482 			return 0;
3483 		    }
3484 		}
3485 		else if (mml_type == MtrNode && mml_child->nodeType() != MtdNode) {
3486 		    MmlNode *mtd_node = createNode(MtdNode, MmlAttributeMap(), QString(), 0);
3487 		    insertChild(mml_node, mtd_node, 0);
3488 		    if (!insertChild(mtd_node, mml_child, errorMsg)) {
3489 			delete mml_node;
3490 			delete mml_child;
3491 			*ok = false;
3492 			return 0;
3493 		    }
3494 		}
3495 		else {
3496 		    if (!insertChild(mml_node, mml_child, errorMsg)) {
3497 			delete mml_node;
3498 			delete mml_child;
3499 			*ok = false;
3500 			return 0;
3501 		    }
3502 		}
3503 
3504 		if (i < child_cnt - 1 && mml_type == MfencedNode && !separator_list.isEmpty()) {
3505 		    QChar separator;
3506 		    if (i >= (int)separator_list.length())
3507 			separator = separator_list.at(separator_list.length() - 1);
3508 		    else
3509 			separator = separator_list[i];
3510 		    insertOperator(mml_node, QString(separator));
3511 		}
3512 	    }
3513 
3514 	    if (mml_type == MfencedNode)
3515 		insertOperator(mml_node, mml_node->explicitAttribute("close", ")"));
3516 
3517 	    break;
3518     }
3519 
3520     *ok = true;
3521     return mml_node;
3522 }
3523 
createImplicitMrowNode(const QDomNode & dom_node,bool * ok,QString * errorMsg)3524 MmlNode *MmlDocument::createImplicitMrowNode(const QDomNode &dom_node, bool *ok,
3525 						QString *errorMsg)
3526 {
3527     QDomNodeList dom_child_list = dom_node.childNodes();
3528     int child_cnt = dom_child_list.count();
3529 
3530     if (child_cnt == 0) {
3531 	*ok = true;
3532 	return 0;
3533     }
3534 
3535     if (child_cnt == 1)
3536 	return domToMml(dom_child_list.item(0), ok, errorMsg);
3537 
3538     MmlNode *mml_node = createNode(MrowNode, MmlAttributeMap(),
3539 				    QString(), errorMsg);
3540     Q_ASSERT(mml_node != 0); // there is no reason in heaven or hell for this to fail
3541 
3542     for (int i = 0; i < child_cnt; ++i) {
3543 	QDomNode dom_child = dom_child_list.item(i);
3544 
3545 	MmlNode *mml_child = domToMml(dom_child, ok, errorMsg);
3546 	if (!*ok) {
3547 	    delete mml_node;
3548 	    return 0;
3549 	}
3550 
3551 	if (!insertChild(mml_node, mml_child, errorMsg)) {
3552 	    delete mml_node;
3553 	    delete mml_child;
3554 	    *ok = false;
3555 	    return 0;
3556 	}
3557     }
3558 
3559     return mml_node;
3560 }
3561 
paint(QPainter * p,const QPoint & pos) const3562 void MmlDocument::paint(QPainter *p, const QPoint &pos) const
3563 {
3564     if (m_root_node == 0)
3565     	return;
3566 
3567 /*    p->save();
3568     p->setPen(Qt::blue);
3569     p->drawLine(pos.x() - 5, pos.y(), pos.x() + 5, pos.y());
3570     p->drawLine(pos.x(), pos.y() - 5, pos.x(), pos.y() + 5);
3571     p->restore(); */
3572 
3573     QRect mr = m_root_node->myRect();
3574     m_root_node->setRelOrigin(pos - mr.topLeft());
3575     m_root_node->paint(p);
3576 }
3577 
size() const3578 QSize MmlDocument::size() const
3579 {
3580     if (m_root_node == 0)
3581     	return QSize(0, 0);
3582     return m_root_node->deviceRect().size();
3583 }
3584 
3585 
3586 
3587 
3588 // *******************************************************************
3589 // MmlNode
3590 // *******************************************************************
3591 
3592 
MmlNode(NodeType type,MmlDocument * document,const MmlAttributeMap & attribute_map)3593 MmlNode::MmlNode(NodeType type, MmlDocument *document, const MmlAttributeMap &attribute_map)
3594 {
3595     m_parent = 0;
3596     m_first_child = 0;
3597     m_next_sibling = 0;
3598     m_previous_sibling = 0;
3599 
3600     m_node_type = type;
3601     m_document = document;
3602     m_attribute_map = attribute_map;
3603 
3604     m_my_rect = m_parent_rect = QRect(0, 0, 0, 0);
3605     m_rel_origin = QPoint(0, 0);
3606     m_stretched = false;
3607 }
3608 
~MmlNode()3609 MmlNode::~MmlNode()
3610 {
3611     MmlNode *n = firstChild();
3612     while (n != 0) {
3613 	MmlNode *tmp = n->nextSibling();
3614 	delete n;
3615 	n = tmp;
3616     }
3617 }
3618 
rectToStr(const QRect & rect)3619 static QString rectToStr(const QRect &rect)
3620 {
3621     return QString("[(%1, %2), %3x%4]")
3622 		.arg(rect.x())
3623 		.arg(rect.y())
3624 		.arg(rect.width())
3625 		.arg(rect.height());
3626 }
3627 
toStr() const3628 QString MmlNode::toStr() const
3629 {
3630     const NodeSpec *spec = mmlFindNodeSpec(nodeType());
3631     Q_ASSERT(spec != 0);
3632 
3633     return QString("%1 %2 mr=%3 pr=%4 dr=%5 ro=(%7, %8) str=%9")
3634 		.arg(spec->type_str)
3635 		.arg((unsigned long)this, 0, 16)
3636 		.arg(rectToStr(myRect()))
3637 		.arg(rectToStr(parentRect()))
3638 		.arg(rectToStr(deviceRect()))
3639 		.arg(m_rel_origin.x())
3640 		.arg(m_rel_origin.y())
3641 		.arg((int)isStretched());
3642 }
3643 
interpretSpacing(const QString & value,bool * ok) const3644 int MmlNode::interpretSpacing(const QString &value, bool *ok) const
3645 {
3646     return ::interpretSpacing(value, em(), ex(), ok);
3647 }
3648 
basePos() const3649 int MmlNode::basePos() const
3650 {
3651     QFontMetrics fm(font());
3652     return fm.strikeOutPos();
3653 }
3654 
underlinePos() const3655 int MmlNode::underlinePos() const
3656 {
3657     QFontMetrics fm(font());
3658     return basePos() + fm.underlinePos();
3659 }
overlinePos() const3660 int MmlNode::overlinePos() const
3661 {
3662     QFontMetrics fm(font());
3663     return basePos() - fm.overlinePos();
3664 }
3665 
lastSibling() const3666 MmlNode *MmlNode::lastSibling() const
3667 {
3668     const MmlNode *n = this;
3669     while (!n->isLastSibling())
3670 	n = n->nextSibling();
3671     return const_cast<MmlNode*>(n);
3672 }
3673 
firstSibling() const3674 MmlNode *MmlNode::firstSibling() const
3675 {
3676     const MmlNode *n = this;
3677     while (!n->isFirstSibling())
3678 	n = n->previousSibling();
3679     return const_cast<MmlNode*>(n);
3680 }
3681 
em() const3682 int MmlNode::em() const
3683 {
3684     return QFontMetrics(font()).boundingRect('m').width();
3685 }
3686 
ex() const3687 int MmlNode::ex() const
3688 {
3689     return QFontMetrics(font()).boundingRect('x').height();
3690 }
3691 
scriptlevel(const MmlNode *) const3692 int MmlNode::scriptlevel(const MmlNode *) const
3693 {
3694     int parent_sl;
3695     const MmlNode *p = parent();
3696     if (p == 0)
3697 	parent_sl = 0;
3698     else
3699 	parent_sl = p->scriptlevel(this);
3700 
3701     QString expl_sl_str = explicitAttribute("scriptlevel");
3702     if (expl_sl_str.isNull())
3703 	return parent_sl;
3704 
3705     if (expl_sl_str.startsWith("+") || expl_sl_str.startsWith("-")) {
3706 	bool ok;
3707 	int expl_sl = expl_sl_str.toInt(&ok);
3708 	if (ok) {
3709 	    return parent_sl + expl_sl;
3710 	}
3711 	else {
3712 	    qWarning("MmlNode::scriptlevel(): bad value %s", expl_sl_str.toLatin1().data());
3713 	    return parent_sl;
3714 	}
3715     }
3716 
3717     bool ok;
3718     int expl_sl = expl_sl_str.toInt(&ok);
3719     if (ok)
3720 	return expl_sl;
3721 
3722 
3723     if (expl_sl_str == "+")
3724 	return parent_sl + 1;
3725     else if (expl_sl_str == "-")
3726 	return parent_sl - 1;
3727     else {
3728         qWarning("MmlNode::scriptlevel(): could not parse value: \"%s\"", expl_sl_str.toLatin1().data());
3729 	return parent_sl;
3730     }
3731 }
3732 
devicePoint(const QPoint & p) const3733 QPoint MmlNode::devicePoint(const QPoint &p) const
3734 {
3735     QRect mr = myRect();
3736     QRect dr = deviceRect();
3737 
3738     if (isStretched())
3739 	return dr.topLeft() + QPoint((p.x() - mr.left())*dr.width()/mr.width(),
3740 					(p.y() - mr.top())*dr.height()/mr.height());
3741     else
3742 	return dr.topLeft() + p - mr.topLeft();
3743 }
3744 
inheritAttributeFromMrow(const QString & name,const QString & def) const3745 QString MmlNode::inheritAttributeFromMrow(const QString &name,
3746 					    const QString &def) const
3747 {
3748     const MmlNode *p = this;
3749     for (; p != 0; p = p->parent()) {
3750 	if (p == this || p->nodeType() == MstyleNode) {
3751 	    QString value = p->explicitAttribute(name);
3752 	    if (!value.isNull())
3753 		return value;
3754 	}
3755     }
3756 
3757     return def;
3758 }
3759 
color() const3760 QColor MmlNode::color() const
3761 {
3762     // If we are child of <merror> return red
3763     const MmlNode *p = this;
3764     for (; p != 0; p = p->parent()) {
3765 	if (p->nodeType() == MerrorNode)
3766 	    return QColor("red");
3767     }
3768 
3769     QString value_str = inheritAttributeFromMrow("mathcolor");
3770     if (value_str.isNull())
3771 	value_str = inheritAttributeFromMrow("color");
3772     if (value_str.isNull())
3773 	return QColor();
3774 
3775     return QColor(value_str);
3776 }
3777 
background() const3778 QColor MmlNode::background() const
3779 {
3780     QString value_str = inheritAttributeFromMrow("mathbackground");
3781     if (value_str.isNull())
3782 	value_str = inheritAttributeFromMrow("background");
3783     if (value_str.isNull())
3784 	return QColor();
3785 
3786     return QColor(value_str);
3787 }
3788 
updateFontAttr(MmlAttributeMap & font_attr,const MmlNode * n,const QString & name,const QString & preferred_name=QString ())3789 static void updateFontAttr(MmlAttributeMap &font_attr, const MmlNode *n,
3790 				const QString &name, const QString &preferred_name = QString())
3791 {
3792     if (font_attr.contains(preferred_name) || font_attr.contains(name))
3793 	return;
3794     QString value = n->explicitAttribute(name);
3795     if (!value.isNull())
3796 	font_attr[name] = value;
3797 }
3798 
collectFontAttributes(const MmlNode * node)3799 static MmlAttributeMap collectFontAttributes(const MmlNode *node)
3800 {
3801     MmlAttributeMap font_attr;
3802 
3803     for (const MmlNode *n = node; n != 0; n = n->parent()) {
3804 	if (n == node || n->nodeType() == Mml::MstyleNode) {
3805 	    updateFontAttr(font_attr, n, "mathvariant");
3806 	    updateFontAttr(font_attr, n, "mathsize");
3807 
3808 	    // depreciated attributes
3809 	    updateFontAttr(font_attr, n, "fontsize", "mathsize");
3810 	    updateFontAttr(font_attr, n, "fontweight", "mathvariant");
3811 	    updateFontAttr(font_attr, n, "fontstyle", "mathvariant");
3812 	    updateFontAttr(font_attr, n, "fontfamily", "mathvariant");
3813 	}
3814     }
3815 
3816     return font_attr;
3817 }
3818 
font() const3819 QFont MmlNode::font() const
3820 {
3821     QFont fn(document()->fontName(QtMmlWidget::NormalFont),
3822 		document()->baseFontPointSize());
3823 
3824     int ps = fn.pointSize();
3825     int sl = scriptlevel();
3826     if (sl >= 0) {
3827 	for (int i = 0; i < sl; ++i)
3828 	    ps = (int)(ps*g_script_size_multiplier);
3829     }
3830     else {
3831 	for (int i = 0; i > sl; --i)
3832 	    ps = (int)(ps/g_script_size_multiplier);
3833     }
3834     if (ps < g_min_font_point_size)
3835 	ps = g_min_font_point_size;
3836     fn.setPointSize(ps);
3837 
3838     int em = QFontMetrics(fn).boundingRect('m').width();
3839     int ex = QFontMetrics(fn).boundingRect('x').height();
3840 
3841     MmlAttributeMap font_attr = collectFontAttributes(this);
3842 
3843     if (font_attr.contains("mathvariant")) {
3844 	QString value = font_attr["mathvariant"];
3845 
3846 	bool ok;
3847 	uint mv = interpretMathVariant(value, &ok);
3848 
3849 	if (ok) {
3850 	    if (mv & ScriptMV)
3851 		fn.setFamily(document()->fontName(QtMmlWidget::ScriptFont));
3852 
3853 	    if (mv & FrakturMV)
3854 		fn.setFamily(document()->fontName(QtMmlWidget::FrakturFont));
3855 
3856 	    if (mv & SansSerifMV)
3857 		fn.setFamily(document()->fontName(QtMmlWidget::SansSerifFont));
3858 
3859 	    if (mv & MonospaceMV)
3860 		fn.setFamily(document()->fontName(QtMmlWidget::MonospaceFont));
3861 
3862 	    if (mv & DoubleStruckMV)
3863 		fn.setFamily(document()->fontName(QtMmlWidget::DoublestruckFont));
3864 
3865 	    if (mv & BoldMV)
3866 		fn.setBold(true);
3867 
3868 	    if (mv & ItalicMV)
3869 		fn.setItalic(true);
3870 	}
3871     }
3872 
3873     if (font_attr.contains("mathsize")) {
3874 	QString value = font_attr["mathsize"];
3875 	fn = interpretMathSize(value, fn, em, ex, 0);
3876     }
3877 
3878     fn = interpretDepreciatedFontAttr(font_attr, fn, em, ex);
3879 
3880     if (nodeType() == MiNode
3881 	    && !font_attr.contains("mathvariant")
3882 	    && !font_attr.contains("fontstyle")) {
3883 	const MmlMiNode *mi_node = (const MmlMiNode*) this;
3884 	if (mi_node->text().length() == 1)
3885 	    fn.setItalic(true);
3886     }
3887 
3888     if (nodeType() == MoNode) {
3889 	fn.setItalic(false);
3890 	fn.setBold(false);
3891     }
3892 
3893     return fn;
3894 }
3895 
explicitAttribute(const QString & name,const QString & def) const3896 QString MmlNode::explicitAttribute(const QString &name, const QString &def) const
3897 {
3898     MmlAttributeMap::const_iterator it = m_attribute_map.find(name);
3899     if (it != m_attribute_map.end())
3900 	return *it;
3901     return def;
3902 }
3903 
3904 
parentRect() const3905 QRect MmlNode::parentRect() const
3906 {
3907     if (isStretched())
3908 	return m_parent_rect;
3909 
3910     QRect mr = myRect();
3911     QPoint ro = relOrigin();
3912 
3913     return QRect(ro + mr.topLeft(), mr.size());
3914 }
3915 
3916 
stretchTo(const QRect & rect)3917 void MmlNode::stretchTo(const QRect &rect)
3918 {
3919     m_parent_rect = rect;
3920     m_stretched = true;
3921 }
3922 
setRelOrigin(const QPoint & rel_origin)3923 void MmlNode::setRelOrigin(const QPoint &rel_origin)
3924 {
3925     m_rel_origin = rel_origin + QPoint(-myRect().left(), 0);
3926     m_stretched = false;
3927 }
3928 
updateMyRect()3929 void MmlNode::updateMyRect()
3930 {
3931     m_my_rect = symbolRect();
3932     MmlNode *child = firstChild();
3933     for (; child != 0; child = child->nextSibling())
3934 	m_my_rect |= child->parentRect();
3935 }
3936 
layout()3937 void MmlNode::layout()
3938 {
3939     m_parent_rect = QRect(0, 0, 0, 0);
3940     m_stretched = false;
3941     m_rel_origin = QPoint(0, 0);
3942 
3943     MmlNode *child = firstChild();
3944     for (; child != 0; child = child->nextSibling())
3945 	child->layout();
3946 
3947     layoutSymbol();
3948 
3949     updateMyRect();
3950 
3951     if (parent() == 0)
3952 	m_rel_origin = QPoint(0, 0);
3953 }
3954 
3955 
deviceRect() const3956 QRect MmlNode::deviceRect() const
3957 {
3958     if (parent() == 0)
3959 	return QRect(relOrigin() + myRect().topLeft(), myRect().size());
3960 
3961 /*    if (!isStretched()) {
3962 	QRect pdr = parent()->deviceRect();
3963 	QRect pmr = parent()->myRect();
3964 	QRect pr = parentRect();
3965 	QRect mr = myRect();
3966 	return QRect(pdr.left() + pr.left() - pmr.left(),
3967 			pdr.top()  + pr.top() - pmr.top(),
3968 			mr.width(), mr.height());
3969     }
3970 */
3971     QRect pdr = parent()->deviceRect();
3972     QRect pr = parentRect();
3973     QRect pmr = parent()->myRect();
3974 
3975     float scale_w = 0;
3976     if (pmr.width() != 0)
3977 	scale_w = (float)pdr.width()/pmr.width();
3978     float scale_h = 0;
3979     if (pmr.height() != 0)
3980 	scale_h = (float)pdr.height()/pmr.height();
3981 
3982     return QRect(pdr.left() + ROUND((pr.left() - pmr.left())*scale_w),
3983 		     pdr.top()  + ROUND((pr.top() - pmr.top())*scale_h),
3984 		     ROUND((pr.width()*scale_w)),
3985 		     ROUND((pr.height()*scale_h)));
3986 }
3987 
layoutSymbol()3988 void MmlNode::layoutSymbol()
3989 {
3990     // default behaves like an mrow
3991 
3992     // now lay them out in a neat row, aligning their origins to my origin
3993     int w = 0;
3994     MmlNode *child = firstChild();
3995     for (; child != 0; child = child->nextSibling()) {
3996 	child->setRelOrigin(QPoint(w, 0));
3997 	w += child->parentRect().width() + 1;
3998     }
3999 }
4000 
paint(QPainter * p)4001 void MmlNode::paint(QPainter *p)
4002 {
4003     if (!myRect().isValid())
4004         return;
4005     p->save();
4006     p->setViewport(deviceRect());
4007     p->setWindow(myRect());
4008 
4009 
4010     QColor fg = color();
4011     QColor bg = background();
4012     if (bg.isValid())
4013 	p->fillRect(myRect(), bg);
4014     if (fg.isValid())
4015 	p->setPen(color());
4016 
4017     MmlNode *child = firstChild();
4018     for (; child != 0; child = child->nextSibling())
4019 	child->paint(p);
4020 
4021     paintSymbol(p);
4022 
4023     p->restore();
4024 }
4025 
paintSymbol(QPainter * p) const4026 void MmlNode::paintSymbol(QPainter *p) const
4027 {
4028     if (g_draw_frames && myRect().isValid()) {
4029 	p->save();
4030 	p->setPen(Qt::red);
4031 	p->drawRect(m_my_rect);
4032 	QPen pen = p->pen();
4033 	pen.setStyle(Qt::DotLine);
4034 	p->setPen(pen);
4035 	p->drawLine(myRect().left(), 0, myRect().right(), 0);
4036 	p->restore();
4037     }
4038 }
4039 
stretch()4040 void MmlNode::stretch()
4041 {
4042     MmlNode *child = firstChild();
4043     for (; child != 0; child = child->nextSibling())
4044 	child->stretch();
4045 }
4046 
text() const4047 QString MmlTokenNode::text() const
4048 {
4049     QString result;
4050 
4051     const MmlNode *child = firstChild();
4052     for (; child != 0; child = child->nextSibling()) {
4053 	if (child->nodeType() != TextNode) continue;
4054 	if (!result.isEmpty())
4055 	    result += ' ';
4056 	result += ((MmlTextNode*)child)->text();
4057     }
4058 
4059     return result;
4060 }
4061 
numerator() const4062 MmlNode *MmlMfracNode::numerator() const
4063 {
4064     MmlNode *node = firstChild();
4065     Q_ASSERT(node != 0);
4066     return node;
4067 }
4068 
denominator() const4069 MmlNode *MmlMfracNode::denominator() const
4070 {
4071     MmlNode *node = numerator()->nextSibling();
4072     Q_ASSERT(node != 0);
4073     return node;
4074 }
4075 
symbolRect() const4076 QRect MmlMfracNode::symbolRect() const
4077 {
4078     int num_width = numerator()->myRect().width();
4079     int denom_width = denominator()->myRect().width();
4080     int my_width = qMax(num_width, denom_width) + 4;
4081 
4082     return QRect(-my_width/2, 0, my_width, 1);
4083 }
4084 
layoutSymbol()4085 void MmlMfracNode::layoutSymbol()
4086 {
4087     MmlNode *num = numerator();
4088     MmlNode *denom = denominator();
4089 
4090     QRect num_rect = num->myRect();
4091     QRect denom_rect = denom->myRect();
4092 
4093     int spacing = (int)(g_mfrac_spacing*(num_rect.height() + denom_rect.height()));
4094 
4095     num->setRelOrigin(QPoint(-num_rect.width()/2, - spacing - num_rect.bottom()));
4096     denom->setRelOrigin(QPoint(-denom_rect.width()/2, spacing - denom_rect.top()));
4097 }
4098 
zeroLineThickness(const QString & s)4099 static bool zeroLineThickness(const QString &s)
4100 {
4101     if (s.length() == 0 || !s[0].isDigit())
4102 	return false;
4103 
4104     for (int i = 0; i < s.length(); ++i) {
4105 	QChar c = s.at(i);
4106 	if (c.isDigit() && c != '0')
4107 	    return false;
4108     }
4109     return true;
4110 }
4111 
paintSymbol(QPainter * p) const4112 void MmlMfracNode::paintSymbol(QPainter *p) const
4113 {
4114     QString linethickness_str = inheritAttributeFromMrow("linethickness", "1");
4115 
4116     /* InterpretSpacing returns an int, which might be 0 even if the thickness
4117        is > 0, though very very small. That's ok, because the painter then paints
4118        a line of thickness 1. However, we have to run this check if the line
4119        thickness really is zero */
4120     if (!zeroLineThickness(linethickness_str)) {
4121 	bool ok;
4122 	int linethickness = interpretSpacing(linethickness_str, &ok);
4123 	if (!ok)
4124 	    linethickness = 1;
4125 
4126 	p->save();
4127 	QPen pen = p->pen();
4128 	pen.setWidth(linethickness);
4129 	p->setPen(pen);
4130 	QSize s = myRect().size();
4131 	p->drawLine(-s.width()/2, 0, s.width()/2, 0);
4132 	p->restore();
4133     }
4134 }
4135 
base() const4136 MmlNode *MmlRootBaseNode::base() const
4137 {
4138     MmlNode *node = firstChild();
4139 //    Q_ASSERT(node != 0);
4140     return node;
4141 }
4142 
index() const4143 MmlNode *MmlRootBaseNode::index() const
4144 {
4145     MmlNode *b = base();
4146     if (b == 0)
4147 	return 0;
4148     return b->nextSibling();
4149 }
4150 
scriptlevel(const MmlNode * child) const4151 int MmlRootBaseNode::scriptlevel(const MmlNode *child) const
4152 {
4153     int sl = MmlNode::scriptlevel();
4154 
4155     MmlNode *i = index();
4156     if (child != 0 && child == i)
4157 	return sl + 1;
4158     else
4159 	return sl;
4160 }
4161 
4162 
symbolRect() const4163 QRect MmlRootBaseNode::symbolRect() const
4164 {
4165     MmlNode *b = base();
4166     QRect base_rect;
4167     if (b == 0)
4168 	base_rect = QRect(0, 0, 1, 1);
4169     else
4170 	base_rect = base()->myRect();
4171 
4172     int margin = (int)(g_mroot_base_margin*base_rect.height());
4173     int tw = tailWidth();
4174 
4175     return QRect(-tw, base_rect.top() - margin, tw,
4176 		    base_rect.height() + 2*margin);
4177 }
4178 
tailWidth() const4179 int MmlRootBaseNode::tailWidth() const
4180 {
4181     QFontMetrics fm(font());
4182     return fm.boundingRect(g_radical_char).width();
4183 }
4184 
layoutSymbol()4185 void MmlRootBaseNode::layoutSymbol()
4186 {
4187     MmlNode *b = base();
4188     QSize base_size;
4189     if (b != 0) {
4190 	b->setRelOrigin(QPoint(0, 0));
4191 	base_size = base()->myRect().size();
4192     } else
4193 	base_size = QSize(1, 1);
4194 
4195     MmlNode *i = index();
4196     if (i != 0) {
4197 	int tw = tailWidth();
4198 
4199 	QRect i_rect = i->myRect();
4200 	i->setRelOrigin(QPoint(-tw/2 - i_rect.width(),
4201 				-i_rect.bottom() - 4));
4202     }
4203 }
4204 
paintSymbol(QPainter * p) const4205 void MmlRootBaseNode::paintSymbol(QPainter *p) const
4206 {
4207     QFont fn = font();
4208 
4209     p->save();
4210 
4211     QRect sr = symbolRect();
4212 
4213     QRect r = sr;
4214     r.moveTopLeft(devicePoint(sr.topLeft()));
4215     p->setViewport(r);
4216     p->setWindow(QFontMetrics(fn).boundingRect(g_radical_char));
4217     p->setFont(font());
4218     p->drawText(0, 0, QString(g_radical_char));
4219 
4220     p->restore();
4221 
4222     p->drawLine(sr.right(), sr.top(), myRect().right(), sr.top());
4223 }
4224 
MmlTextNode(const QString & text,MmlDocument * document)4225 MmlTextNode::MmlTextNode(const QString &text, MmlDocument *document)
4226     : MmlNode(TextNode, document, MmlAttributeMap())
4227 {
4228     m_text = text;
4229     // Trim whitespace from ends, but keep nbsp and thinsp
4230     m_text.remove(QRegExp("^[^\\S\\x00a0\\x2009]+"));
4231     m_text.remove(QRegExp("[^\\S\\x00a0\\x2009]+$"));
4232 
4233     if (m_text == QString(QChar(0x62, 0x20))	     // &InvisibleTimes;
4234 	    || m_text == QString(QChar(0x63, 0x20))  // &InvisibleComma;
4235 	    || m_text == QString(QChar(0x61, 0x20))) // &ApplyFunction;
4236 	m_text = "";
4237 }
4238 
toStr() const4239 QString MmlTextNode::toStr() const
4240 {
4241     return MmlNode::toStr() + ", text=\"" + m_text + "\"";
4242 }
4243 
paintSymbol(QPainter * p) const4244 void MmlTextNode::paintSymbol(QPainter *p) const
4245 {
4246     MmlNode::paintSymbol(p);
4247 
4248     QFont fn = font();
4249 
4250     QFontInfo fi(fn);
4251 //    qWarning("MmlTextNode::paintSymbol(): requested: %s, used: %s, size=%d, italic=%d, bold=%d, text=\"%s\" sl=%d",
4252 //    	    	fn.family().latin1(), fi.family().latin1(), fi.pointSize(), (int)fi.italic(), (int)fi.bold(), m_text.latin1(), scriptlevel());
4253 
4254     QFontMetrics fm(fn);
4255 
4256     p->save();
4257     p->setFont(fn);
4258 
4259     p->drawText(0, fm.strikeOutPos(), m_text);
4260     p->restore();
4261 }
4262 
symbolRect() const4263 QRect MmlTextNode::symbolRect() const
4264 {
4265     QFontMetrics fm(font());
4266 
4267     QRect br = fm.tightBoundingRect(m_text);
4268     br.translate(0, fm.strikeOutPos());
4269 
4270     return br;
4271 }
4272 
base() const4273 MmlNode *MmlSubsupBaseNode::base() const
4274 {
4275     MmlNode *b = firstChild();
4276     Q_ASSERT(b != 0);
4277     return b;
4278 }
4279 
sscript() const4280 MmlNode *MmlSubsupBaseNode::sscript() const
4281 {
4282     MmlNode *s = base()->nextSibling();
4283     Q_ASSERT(s != 0);
4284     return s;
4285 }
4286 
scriptlevel(const MmlNode * child) const4287 int MmlSubsupBaseNode::scriptlevel(const MmlNode *child) const
4288 {
4289     int sl = MmlNode::scriptlevel();
4290 
4291     MmlNode *s = sscript();
4292     if (child != 0 && child == s)
4293 	return sl + 1;
4294     else
4295 	return sl;
4296 }
4297 
layoutSymbol()4298 void MmlMsupNode::layoutSymbol()
4299 {
4300     MmlNode *b = base();
4301     MmlNode *s = sscript();
4302 
4303     b->setRelOrigin(QPoint(-b->myRect().width(), 0));
4304     s->setRelOrigin(QPoint(0, b->myRect().top()));
4305 }
4306 
layoutSymbol()4307 void MmlMsubNode::layoutSymbol()
4308 {
4309     MmlNode *b = base();
4310     MmlNode *s = sscript();
4311 
4312     b->setRelOrigin(QPoint(-b->myRect().width(), 0));
4313     s->setRelOrigin(QPoint(0, b->myRect().bottom()));
4314 }
4315 
base() const4316 MmlNode *MmlMsubsupNode::base() const
4317 {
4318     MmlNode *b = firstChild();
4319     Q_ASSERT(b != 0);
4320     return b;
4321 }
4322 
subscript() const4323 MmlNode *MmlMsubsupNode::subscript() const
4324 {
4325     MmlNode *sub = base()->nextSibling();
4326     Q_ASSERT(sub != 0);
4327     return sub;
4328 }
4329 
superscript() const4330 MmlNode *MmlMsubsupNode::superscript() const
4331 {
4332     MmlNode *sup = subscript()->nextSibling();
4333     Q_ASSERT(sup != 0);
4334     return sup;
4335 }
4336 
layoutSymbol()4337 void MmlMsubsupNode::layoutSymbol()
4338 {
4339     MmlNode *b = base();
4340     MmlNode *sub = subscript();
4341     MmlNode *sup = superscript();
4342 
4343     b->setRelOrigin(QPoint(-b->myRect().width(), 0));
4344     sub->setRelOrigin(QPoint(0, b->myRect().bottom()));
4345     sup->setRelOrigin(QPoint(0, b->myRect().top()));
4346 }
4347 
scriptlevel(const MmlNode * child) const4348 int MmlMsubsupNode::scriptlevel(const MmlNode *child) const
4349 {
4350     int sl = MmlNode::scriptlevel();
4351 
4352     MmlNode *sub = subscript();
4353     MmlNode *sup = superscript();
4354 
4355     if (child != 0 && (child == sup || child == sub))
4356 	return sl + 1;
4357     else
4358 	return sl;
4359 }
4360 
toStr() const4361 QString MmlMoNode::toStr() const
4362 {
4363     return MmlNode::toStr() + QString(" form=%1").arg((int)form());
4364 }
4365 
layoutSymbol()4366 void MmlMoNode::layoutSymbol()
4367 {
4368     MmlNode *child = firstChild();
4369     if (child == 0)
4370 	return;
4371 
4372     child->setRelOrigin(QPoint(0, 0));
4373 
4374     if (m_oper_spec == 0)
4375 	m_oper_spec = mmlFindOperSpec(text(), form());
4376 }
4377 
MmlMoNode(MmlDocument * document,const MmlAttributeMap & attribute_map)4378 MmlMoNode::MmlMoNode(MmlDocument *document, const MmlAttributeMap &attribute_map)
4379     : MmlTokenNode(MoNode, document, attribute_map)
4380 {
4381     m_oper_spec = 0;
4382 }
4383 
dictionaryAttribute(const QString & name) const4384 QString MmlMoNode::dictionaryAttribute(const QString &name) const
4385 {
4386     const MmlNode *p = this;
4387     for (; p != 0; p = p->parent()) {
4388 	if (p == this || p->nodeType() == MstyleNode) {
4389 	    QString expl_attr = p->explicitAttribute(name);
4390 	    if (!expl_attr.isNull())
4391 		return expl_attr;
4392 	}
4393     }
4394 
4395     return mmlDictAttribute(name, m_oper_spec);
4396 }
4397 
form() const4398 Mml::FormType MmlMoNode::form() const
4399 {
4400     QString value_str = inheritAttributeFromMrow("form");
4401     if (!value_str.isNull()) {
4402 	bool ok;
4403 	FormType value = interpretForm(value_str, &ok);
4404 	if (ok)
4405 	    return value;
4406 	else
4407 	    qWarning("Could not convert %s to form", value_str.toLatin1().data());
4408 
4409     }
4410 
4411     // Default heuristic.
4412     if (firstSibling() == (MmlNode*)this && lastSibling() != (MmlNode*)this)
4413 	return PrefixForm;
4414     else if (lastSibling() == (MmlNode*)this && firstSibling() != (MmlNode*)this)
4415 	return PostfixForm;
4416     else return InfixForm;
4417 
4418 }
4419 
stretch()4420 void MmlMoNode::stretch()
4421 {
4422     if (parent() == 0)
4423 	return;
4424 
4425     if (m_oper_spec == 0)
4426 	return;
4427 
4428     if (m_oper_spec->stretch_dir == OperSpec::HStretch
4429     	    && parent()->nodeType() == MrowNode
4430 	    && (nextSibling() != 0 || previousSibling() != 0))
4431 	return;
4432 
4433     QRect pmr = parent()->myRect();
4434     QRect pr = parentRect();
4435 
4436     switch (m_oper_spec->stretch_dir) {
4437 	case OperSpec::VStretch:
4438 	    stretchTo(QRect(pr.left(), pmr.top(), pr.width(), pmr.height()));
4439 	    break;
4440 	case OperSpec::HStretch:
4441 	    stretchTo(QRect(pmr.left(), pr.top(), pmr.width(), pr.height()));
4442 	    break;
4443 	case OperSpec::HVStretch:
4444 	    stretchTo(pmr);
4445 	    break;
4446 	case OperSpec::NoStretch:
4447 	    break;
4448     }
4449 }
4450 
lspace() const4451 int MmlMoNode::lspace() const
4452 {
4453     Q_ASSERT(m_oper_spec != 0);
4454     if (parent() == 0
4455 	    || (parent()->nodeType() != MrowNode
4456 	    	    && parent()->nodeType() != MfencedNode
4457 		    && parent()->nodeType() != UnknownNode)
4458 	    || (previousSibling() == 0 && nextSibling() == 0))
4459 	return 0;
4460     else
4461 	return interpretSpacing(dictionaryAttribute("lspace"), 0);
4462 }
4463 
rspace() const4464 int MmlMoNode::rspace() const
4465 {
4466     Q_ASSERT(m_oper_spec != 0);
4467     if (parent() == 0
4468 	    || (parent()->nodeType() != MrowNode
4469 	    	    && parent()->nodeType() != MfencedNode
4470 		    && parent()->nodeType() != UnknownNode)
4471 	    || (previousSibling() == 0 && nextSibling() == 0))
4472 	return 0;
4473     else
4474 	return interpretSpacing(dictionaryAttribute("rspace"), 0);
4475 }
4476 
symbolRect() const4477 QRect MmlMoNode::symbolRect() const
4478 {
4479     const MmlNode *child = firstChild();
4480 
4481     if (child == 0)
4482 	return QRect(0, 0, 0, 0);
4483 
4484     QRect cmr = child->myRect();
4485 
4486     return QRect(-lspace(), cmr.top(),
4487 		   cmr.width() + lspace() + rspace(), cmr.height());
4488 }
4489 
rowspacing() const4490 int MmlMtableNode::rowspacing() const
4491 {
4492     QString value = explicitAttribute("rowspacing");
4493     if (value.isNull())
4494 	return ex();
4495     bool ok;
4496     int r = interpretSpacing(value, &ok);
4497 
4498     if (ok)
4499 	return r;
4500     else
4501 	return ex();
4502 }
4503 
columnspacing() const4504 int MmlMtableNode::columnspacing() const
4505 {
4506     QString value = explicitAttribute("columnspacing");
4507     if (value.isNull())
4508 	return (int)(0.8*em());
4509     bool ok;
4510     int r = interpretSpacing(value, &ok);
4511 
4512     if (ok)
4513 	return r;
4514     else
4515 	return (int)(0.8*em());
4516 }
4517 
colWidthSum() const4518 uint MmlMtableNode::CellSizeData::colWidthSum() const
4519 {
4520     uint w = 0;
4521     for (int i = 0; i < col_widths.count(); ++i)
4522 	w += col_widths[i];
4523     return w;
4524 }
4525 
rowHeightSum() const4526 uint MmlMtableNode::CellSizeData::rowHeightSum() const
4527 {
4528     uint h = 0;
4529     for (int i = 0; i < row_heights.count(); ++i)
4530 	h += row_heights[i];
4531     return h;
4532 }
4533 
init(const MmlNode * first_row)4534 void MmlMtableNode::CellSizeData::init(const MmlNode *first_row)
4535 {
4536     col_widths.clear();
4537     row_heights.clear();
4538 
4539     const MmlNode *mtr = first_row;
4540     for (; mtr != 0; mtr = mtr->nextSibling()) {
4541 
4542 	Q_ASSERT(mtr->nodeType() == MtrNode);
4543 
4544 	int col_cnt = 0;
4545 	const MmlNode *mtd = mtr->firstChild();
4546 	for (; mtd != 0; mtd = mtd->nextSibling(), ++col_cnt) {
4547 
4548 	    Q_ASSERT(mtd->nodeType() == MtdNode);
4549 
4550 	    QRect mtdmr = mtd->myRect();
4551 
4552 	    if (col_cnt == col_widths.count())
4553 		col_widths.append(mtdmr.width());
4554 	    else
4555 		col_widths[col_cnt] = qMax(col_widths[col_cnt], mtdmr.width());
4556 	}
4557 
4558 	row_heights.append(mtr->myRect().height());
4559     }
4560 }
4561 
layoutSymbol()4562 void MmlMtableNode::layoutSymbol()
4563 {
4564     // Obtain natural widths of columns
4565     m_cell_size_data.init(firstChild());
4566 
4567     int col_spc = columnspacing();
4568     int row_spc = rowspacing();
4569     int frame_spc_hor = framespacing_hor();
4570     QString columnwidth_attr = explicitAttribute("columnwidth", "auto");
4571 
4572     // Is table width set by user? If so, set col_width_sum and never ever change it.
4573     int col_width_sum = m_cell_size_data.colWidthSum();
4574     bool width_set_by_user = false;
4575     QString width_str = explicitAttribute("width", "auto");
4576     if (width_str != "auto") {
4577 	bool ok;
4578 
4579 	int w = interpretSpacing(width_str, &ok);
4580 	if (ok) {
4581 	    col_width_sum = w
4582 			    - col_spc*(m_cell_size_data.numCols() - 1)
4583 			    - frame_spc_hor*2;
4584 	    width_set_by_user = true;
4585 	}
4586     }
4587 
4588     // Find out what kind of columns we are dealing with and set the widths of
4589     // statically sized columns.
4590     int fixed_width_sum = 0;	      // sum of widths of statically sized set columns
4591     int auto_width_sum = 0; 	      // sum of natural widths of auto sized columns
4592     int relative_width_sum = 0;       // sum of natural widths of relatively sized columns
4593     double relative_fraction_sum = 0; // total fraction of width taken by relatively
4594 				      // sized columns
4595     int i;
4596     for (i = 0; i < m_cell_size_data.numCols(); ++i) {
4597 	QString value = interpretListAttr(columnwidth_attr, i, "auto");
4598 
4599 	// Is it an auto sized column?
4600 	if (value == "auto" || value == "fit") {
4601 	    auto_width_sum += m_cell_size_data.col_widths[i];
4602 	    continue;
4603 	}
4604 
4605 	// Is it a statically sized column?
4606 	bool ok;
4607 	int w = interpretSpacing(value, &ok);
4608 	if (ok) {
4609 	    // Yup, sets its width to the user specified value
4610 	    m_cell_size_data.col_widths[i] = w;
4611 	    fixed_width_sum += w;
4612 	    continue;
4613 	}
4614 
4615 	// Is it a relatively sized column?
4616 	if (value.endsWith("%")) {
4617 	    value.truncate(value.length() - 1);
4618 	    double factor = value.toFloat(&ok);
4619 	    if (ok && !value.isEmpty()) {
4620 		factor /= 100.0;
4621 		relative_width_sum += m_cell_size_data.col_widths[i];
4622 		relative_fraction_sum += factor;
4623 		if (!width_set_by_user) {
4624 		    // If the table width was not set by the user, we are free to increase
4625 		    // it so that the width of this column will be >= than its natural width
4626 		    int min_col_width_sum = ROUND(m_cell_size_data.col_widths[i]/factor);
4627 		    if (min_col_width_sum > col_width_sum)
4628 			col_width_sum = min_col_width_sum;
4629 		}
4630 		continue;
4631 	    }
4632 	    else
4633 		qWarning("MmlMtableNode::layoutSymbol(): could not parse value %s%%", value.toLatin1().data());
4634 	}
4635 
4636 	// Relatively sized column, but we failed to parse the factor. Treat is like an auto
4637 	// column.
4638 	auto_width_sum += m_cell_size_data.col_widths[i];
4639     }
4640 
4641     // Work out how much space remains for the auto olumns, after allocating
4642     // the statically sized and the relatively sized columns.
4643     int required_auto_width_sum = col_width_sum
4644 				    - ROUND(relative_fraction_sum*col_width_sum)
4645 				    - fixed_width_sum;
4646 
4647     if (!width_set_by_user && required_auto_width_sum < auto_width_sum) {
4648 	if (relative_fraction_sum < 1)
4649 	    col_width_sum = ROUND((fixed_width_sum + auto_width_sum)/(1 - relative_fraction_sum));
4650 	else
4651 	    col_width_sum = fixed_width_sum + auto_width_sum + relative_width_sum;
4652 	required_auto_width_sum = auto_width_sum;
4653     }
4654 
4655     // Ratio by which we have to shring/grow all auto sized columns to make it all fit
4656     double auto_width_scale = 1;
4657     if (auto_width_sum > 0)
4658 	auto_width_scale = (float)required_auto_width_sum/auto_width_sum;
4659 
4660     // Set correct sizes for the auto sized and the relatively sized columns.
4661     for (i = 0; i < m_cell_size_data.numCols(); ++i) {
4662 	QString value = interpretListAttr(columnwidth_attr, i, "auto");
4663 
4664 	// Is it a relatively sized column?
4665 	if (value.endsWith("%")) {
4666 	    bool ok;
4667 	    int w = interpretPercentSpacing(value, col_width_sum, &ok);
4668 	    if (ok)
4669 		m_cell_size_data.col_widths[i] = w;
4670 	    else
4671 		// We're treating parsing errors here as auto sized columns
4672 		m_cell_size_data.col_widths[i]
4673 			= ROUND(auto_width_scale*m_cell_size_data.col_widths[i]);
4674 	}
4675 	// Is it an auto sized column?
4676 	else if (value == "auto") {
4677 	    m_cell_size_data.col_widths[i]
4678 		    = ROUND(auto_width_scale*m_cell_size_data.col_widths[i]);
4679 	}
4680     }
4681 
4682     QString s;
4683     QList<int> &col_widths = m_cell_size_data.col_widths;
4684     for (i = 0; i < col_widths.count(); ++i) {
4685 	s += QString("[w=%1 %2%%]")
4686 		.arg(col_widths[i])
4687 		.arg(100*col_widths[i]/m_cell_size_data.colWidthSum());
4688     }
4689 //    qWarning(s);
4690 
4691     m_content_width = m_cell_size_data.colWidthSum()
4692 		    + col_spc*(m_cell_size_data.numCols() - 1);
4693     m_content_height = m_cell_size_data.rowHeightSum()
4694 		    + row_spc*(m_cell_size_data.numRows() - 1);
4695 
4696     int bottom = -m_content_height/2;
4697     MmlNode *child = firstChild();
4698     for (; child != 0; child = child->nextSibling()) {
4699 	Q_ASSERT(child->nodeType() == MtrNode);
4700 	MmlMtrNode *row = (MmlMtrNode*) child;
4701 
4702 	row->layoutCells(m_cell_size_data.col_widths, col_spc);
4703 	QRect rmr = row->myRect();
4704 	row->setRelOrigin(QPoint(0, bottom - rmr.top()));
4705 	bottom += rmr.height() + row_spc;
4706     }
4707 }
4708 
symbolRect() const4709 QRect MmlMtableNode::symbolRect() const
4710 {
4711     int frame_spc_hor = framespacing_hor();
4712     int frame_spc_ver = framespacing_ver();
4713 
4714     return QRect(-frame_spc_hor,
4715 		    -m_content_height/2 - frame_spc_ver,
4716 		    m_content_width + 2*frame_spc_hor,
4717 		    m_content_height + 2*frame_spc_ver);
4718 }
4719 
frame() const4720 Mml::FrameType MmlMtableNode::frame() const
4721 {
4722     QString value = explicitAttribute("frame", "none");
4723     return interpretFrameType(value, 0, 0);
4724 }
4725 
columnlines(int idx) const4726 Mml::FrameType MmlMtableNode::columnlines(int idx) const
4727 {
4728     QString value = explicitAttribute("columnlines", "none");
4729     return interpretFrameType(value, idx, 0);
4730 }
4731 
rowlines(int idx) const4732 Mml::FrameType MmlMtableNode::rowlines(int idx) const
4733 {
4734     QString value = explicitAttribute("rowlines", "none");
4735     return interpretFrameType(value, idx, 0);
4736 }
4737 
paintSymbol(QPainter * p) const4738 void MmlMtableNode::paintSymbol(QPainter *p) const
4739 {
4740     FrameType f = frame();
4741     if (f != FrameNone) {
4742 	p->save();
4743 
4744 	QPen pen = p->pen();
4745 	if (f == FrameDashed)
4746 	    pen.setStyle(Qt::DashLine);
4747 	else
4748 	    pen.setStyle(Qt::SolidLine);
4749 	p->setPen(pen);
4750 	p->drawRect(myRect());
4751 
4752 	p->restore();
4753     }
4754 
4755     p->save();
4756 
4757     int col_spc = columnspacing();
4758     int row_spc = rowspacing();
4759 
4760     QPen pen = p->pen();
4761     int col_offset = 0;
4762     int i;
4763     for (i = 0; i < m_cell_size_data.numCols() - 1; ++i) {
4764 	FrameType f = columnlines(i);
4765 	col_offset += m_cell_size_data.col_widths[i];
4766 
4767 	if (f != FrameNone) {
4768 	    if (f == FrameDashed)
4769 		pen.setStyle(Qt::DashLine);
4770 	    else if (f == FrameSolid)
4771 		pen.setStyle(Qt::SolidLine);
4772 
4773 	    p->setPen(pen);
4774 	    int x = col_offset + col_spc/2;
4775 	    p->drawLine(x, -m_content_height/2, x, m_content_height/2 );
4776 	}
4777 	col_offset += col_spc;
4778     }
4779 
4780     int row_offset = 0;
4781     for (i = 0; i < m_cell_size_data.numRows() - 1; ++i) {
4782 	FrameType f = rowlines(i);
4783 	row_offset += m_cell_size_data.row_heights[i];
4784 
4785 	if (f != FrameNone) {
4786 	    if (f == FrameDashed)
4787 		pen.setStyle(Qt::DashLine);
4788 	    else if (f == FrameSolid)
4789 		pen.setStyle(Qt::SolidLine);
4790 
4791 	    p->setPen(pen);
4792 	    int y = row_offset + row_spc/2 - m_content_height/2;
4793 	    p->drawLine(0, y, m_content_width, y);
4794 	}
4795 	row_offset += row_spc;
4796     }
4797 
4798     p->restore();
4799 }
4800 
framespacing_ver() const4801 int MmlMtableNode::framespacing_ver() const
4802 {
4803     if (frame() == FrameNone)
4804 	return (int)(0.2*em());
4805 
4806     QString value = explicitAttribute("framespacing", "0.4em 0.5ex");
4807 
4808     bool ok;
4809     FrameSpacing fs = interpretFrameSpacing(value, em(), ex(), &ok);
4810     if (ok)
4811 	return fs.m_ver;
4812     else
4813 	return (int)(0.5*ex());
4814 }
4815 
framespacing_hor() const4816 int MmlMtableNode::framespacing_hor() const
4817 {
4818     if (frame() == FrameNone)
4819 	return (int)(0.2*em());
4820 
4821     QString value = explicitAttribute("framespacing", "0.4em 0.5ex");
4822 
4823     bool ok;
4824     FrameSpacing fs = interpretFrameSpacing(value, em(), ex(), &ok);
4825     if (ok)
4826 	return fs.m_hor;
4827     else
4828 	return (int)(0.4*em());
4829 }
4830 
layoutCells(const QList<int> & col_widths,int col_spc)4831 void MmlMtrNode::layoutCells(const QList<int> &col_widths,
4832 				int col_spc)
4833 {
4834     QRect mr = myRect();
4835 
4836     MmlNode *child = firstChild();
4837     int col_offset = 0;
4838     uint colnum = 0;
4839     for (; child != 0; child = child->nextSibling(), ++colnum) {
4840 	Q_ASSERT(child->nodeType() == MtdNode);
4841 	MmlMtdNode *mtd = (MmlMtdNode*) child;
4842 
4843 	QRect r = QRect(0, mr.top(), col_widths[colnum], mr.height());
4844 	mtd->setMyRect(r);
4845 	mtd->setRelOrigin(QPoint(col_offset, 0));
4846 	col_offset += col_widths[colnum] + col_spc;
4847     }
4848 
4849     updateMyRect();
4850 }
4851 
scriptlevel(const MmlNode * child) const4852 int MmlMtdNode::scriptlevel(const MmlNode *child) const
4853 {
4854     int sl = MmlNode::scriptlevel();
4855     if (child != 0 && child == firstChild())
4856 	return sl + m_scriptlevel_adjust;
4857     else
4858 	return sl;
4859 }
4860 
setMyRect(const QRect & rect)4861 void MmlMtdNode::setMyRect(const QRect &rect)
4862 {
4863     MmlNode::setMyRect(rect);
4864     MmlNode *child = firstChild();
4865     if (child == 0)
4866 	return;
4867 
4868     if (rect.width() < child->myRect().width()) {
4869 	while (rect.width() < child->myRect().width()
4870 		    && child->font().pointSize() > g_min_font_point_size) {
4871 
4872 //    	    qWarning("MmlMtdNode::setMyRect(): rect.width()=%d, child()->myRect().width=%d sl=%d",
4873 //	    		rect.width(), child->myRect().width(), m_scriptlevel_adjust);
4874 
4875 	    ++m_scriptlevel_adjust;
4876 	    child->layout();
4877 	}
4878 
4879 //    	qWarning("MmlMtdNode::setMyRect(): rect.width()=%d, child()->myRect().width=%d sl=%d",
4880 //	    	    rect.width(), child->myRect().width(), m_scriptlevel_adjust);
4881     }
4882 
4883     QRect mr = myRect();
4884     QRect cmr = child->myRect();
4885 
4886     QPoint child_rel_origin;
4887 
4888     switch (columnalign()) {
4889 	case ColAlignLeft:
4890 	    child_rel_origin.setX(0);
4891 	    break;
4892 	case ColAlignCenter:
4893 	    child_rel_origin.setX(mr.left() + (mr.width() - cmr.width())/2);
4894 	    break;
4895 	case ColAlignRight:
4896 	    child_rel_origin.setX(mr.right() - cmr.width());
4897 	    break;
4898     }
4899 
4900     switch (rowalign()) {
4901 	case RowAlignTop:
4902 	    child_rel_origin.setY(mr.top() - cmr.top());
4903 	    break;
4904 	case RowAlignCenter:
4905 	case RowAlignBaseline:
4906 	    child_rel_origin.setY(mr.top() -cmr.top() + (mr.height() - cmr.height())/2);
4907 	    break;
4908 	case RowAlignBottom:
4909 	    child_rel_origin.setY(mr.bottom() - cmr.bottom());
4910 	    break;
4911 	case RowAlignAxis:
4912 	    child_rel_origin.setY(0);
4913 	    break;
4914     }
4915 
4916     child->setRelOrigin(child_rel_origin);
4917 }
4918 
colNum()4919 uint MmlMtdNode::colNum()
4920 {
4921     MmlNode *syb = previousSibling();
4922 
4923     uint i = 0;
4924     for (; syb != 0; syb = syb->previousSibling())
4925 	++i;
4926 
4927     return i;
4928 }
4929 
rowNum()4930 uint MmlMtdNode::rowNum()
4931 {
4932     MmlNode *row = parent()->previousSibling();
4933 
4934     uint i = 0;
4935     for (; row != 0; row = row->previousSibling())
4936 	++i;
4937 
4938     return i;
4939 }
4940 
columnalign()4941 MmlMtdNode::ColAlign MmlMtdNode::columnalign()
4942 {
4943     QString val = explicitAttribute("columnalign");
4944     if (!val.isNull())
4945 	return interpretColAlign(val, 0, 0);
4946 
4947     MmlNode *node = parent(); // <mtr>
4948     if (node == 0)
4949 	return ColAlignCenter;
4950 
4951     uint colnum = colNum();
4952     val = node->explicitAttribute("columnalign");
4953     if (!val.isNull())
4954 	return interpretColAlign(val, colnum, 0);
4955 
4956     node = node->parent(); // <mtable>
4957     if (node == 0)
4958 	return ColAlignCenter;
4959 
4960     val = node->explicitAttribute("columnalign");
4961     if (!val.isNull())
4962 	return interpretColAlign(val, colnum, 0);
4963 
4964     return ColAlignCenter;
4965 }
4966 
rowalign()4967 MmlMtdNode::RowAlign MmlMtdNode::rowalign()
4968 {
4969     QString val = explicitAttribute("rowalign");
4970     if (!val.isNull())
4971 	return interpretRowAlign(val, 0, 0);
4972 
4973     MmlNode *node = parent(); // <mtr>
4974     if (node == 0)
4975 	return RowAlignAxis;
4976 
4977     uint rownum = rowNum();
4978     val = node->explicitAttribute("rowalign");
4979     if (!val.isNull())
4980 	return interpretRowAlign(val, rownum, 0);
4981 
4982     node = node->parent(); // <mtable>
4983     if (node == 0)
4984 	return RowAlignAxis;
4985 
4986     val = node->explicitAttribute("rowalign");
4987     if (!val.isNull())
4988 	return interpretRowAlign(val, rownum, 0);
4989 
4990     return RowAlignAxis;
4991 }
4992 
layoutSymbol()4993 void MmlMoverNode::layoutSymbol()
4994 {
4995     MmlNode *base = firstChild();
4996     Q_ASSERT(base != 0);
4997     MmlNode *over = base->nextSibling();
4998     Q_ASSERT(over != 0);
4999 
5000     QRect base_rect = base->myRect();
5001     QRect over_rect = over->myRect();
5002 
5003     int spacing = (int)(g_mfrac_spacing*(over_rect.height()
5004                                          + base_rect.height()));
5005 
5006     base->setRelOrigin(QPoint(-base_rect.width()/2, 0));
5007     over->setRelOrigin(QPoint(-over_rect.width()/2,
5008                               base_rect.top() - spacing - over_rect.bottom()));
5009 }
5010 
scriptlevel(const MmlNode * node) const5011 int MmlMoverNode::scriptlevel(const MmlNode *node) const
5012 {
5013     MmlNode *base = firstChild();
5014     Q_ASSERT(base != 0);
5015     MmlNode *over = base->nextSibling();
5016     Q_ASSERT(over != 0);
5017 
5018     int sl = MmlNode::scriptlevel();
5019     if (node != 0 && node == over)
5020 	return sl + 1;
5021     else
5022 	return sl;
5023 }
5024 
layoutSymbol()5025 void MmlMunderNode::layoutSymbol()
5026 {
5027     MmlNode *base = firstChild();
5028     Q_ASSERT(base != 0);
5029     MmlNode *under = base->nextSibling();
5030     Q_ASSERT(under != 0);
5031 
5032     QRect base_rect = base->myRect();
5033     QRect under_rect = under->myRect();
5034 
5035     int spacing = (int)(g_mfrac_spacing*(under_rect.height() + base_rect.height()));
5036 
5037     base->setRelOrigin(QPoint(-base_rect.width()/2, 0));
5038     under->setRelOrigin(QPoint(-under_rect.width()/2, base_rect.bottom() + spacing - under_rect.top()));
5039 }
5040 
scriptlevel(const MmlNode * node) const5041 int MmlMunderNode::scriptlevel(const MmlNode *node) const
5042 {
5043     MmlNode *base = firstChild();
5044     Q_ASSERT(base != 0);
5045     MmlNode *under = base->nextSibling();
5046     Q_ASSERT(under != 0);
5047 
5048     int sl = MmlNode::scriptlevel();
5049     if (node != 0 && node == under)
5050 	return sl + 1;
5051     else
5052 	return sl;
5053 }
5054 
layoutSymbol()5055 void MmlMunderoverNode::layoutSymbol()
5056 {
5057     MmlNode *base = firstChild();
5058     Q_ASSERT(base != 0);
5059     MmlNode *under = base->nextSibling();
5060     Q_ASSERT(under != 0);
5061     MmlNode *over = under->nextSibling();
5062     Q_ASSERT(over != 0);
5063 
5064     QRect base_rect = base->myRect();
5065     QRect under_rect = under->myRect();
5066     QRect over_rect = over->myRect();
5067 
5068     int spacing = (int)(g_mfrac_spacing*(   base_rect.height()
5069 						+ under_rect.height()
5070 						+ over_rect.height())	);
5071 
5072     base->setRelOrigin(QPoint(-base_rect.width()/2, 0));
5073     under->setRelOrigin(QPoint(-under_rect.width()/2, base_rect.bottom() + spacing - under_rect.top()));
5074     over->setRelOrigin(QPoint(-over_rect.width()/2, base_rect.top() - spacing - under_rect.bottom()));
5075 }
5076 
scriptlevel(const MmlNode * node) const5077 int MmlMunderoverNode::scriptlevel(const MmlNode *node) const
5078 {
5079     MmlNode *base = firstChild();
5080     Q_ASSERT(base != 0);
5081     MmlNode *under = base->nextSibling();
5082     Q_ASSERT(under != 0);
5083     MmlNode *over = under->nextSibling();
5084     Q_ASSERT(over != 0);
5085 
5086     int sl = MmlNode::scriptlevel();
5087     if (node != 0 && (node == under || node == over))
5088 	return sl + 1;
5089     else
5090 	return sl;
5091 }
5092 
interpretSpacing(QString value,int base_value,bool * ok) const5093 int MmlMpaddedNode::interpretSpacing(QString value, int base_value, bool *ok) const
5094 {
5095     if (ok != 0)
5096 	*ok = false;
5097 
5098     value.replace(' ', "");
5099 
5100     QString sign, factor_str, pseudo_unit;
5101     bool percent = false;
5102 
5103     // extract the sign
5104     int idx = 0;
5105     if (idx < value.length() && (value.at(idx) == '+' || value.at(idx) == '-'))
5106 	sign = value.at(idx++);
5107 
5108     // extract the factor
5109     while (idx < value.length() && (value.at(idx).isDigit() || value.at(idx) == '.'))
5110 	factor_str.append(value.at(idx++));
5111 
5112     // extract the % sign
5113     if (idx < value.length() && value.at(idx) == '%') {
5114 	percent = true;
5115 	++idx;
5116     }
5117 
5118     // extract the pseudo-unit
5119     pseudo_unit = value.mid(idx);
5120 
5121     bool float_ok;
5122     double factor = factor_str.toFloat(&float_ok);
5123     if (!float_ok || factor < 0) {
5124 	qWarning("MmlMpaddedNode::interpretSpacing(): could not parse \"%s\"", value.toLatin1().data());
5125 	return 0;
5126     }
5127 
5128     if (percent)
5129 	factor /= 100.0;
5130 
5131     QRect cr;
5132     if (firstChild() == 0)
5133 	cr = QRect(0, 0, 0, 0);
5134     else
5135 	cr = firstChild()->myRect();
5136 
5137     int unit_size;
5138 
5139     if (pseudo_unit.isEmpty())
5140 	unit_size = base_value;
5141     else if (pseudo_unit == "width")
5142 	unit_size = cr.width();
5143     else if (pseudo_unit == "height")
5144 	unit_size = -cr.top();
5145     else if (pseudo_unit == "depth")
5146 	unit_size = cr.bottom();
5147     else {
5148 	bool unit_ok;
5149 	unit_size = MmlNode::interpretSpacing("1" + pseudo_unit, &unit_ok);
5150 	if (!unit_ok) {
5151 	    qWarning("MmlMpaddedNode::interpretSpacing(): could not parse \"%s\"", value.toLatin1().data());
5152 	    return 0;
5153 	}
5154     }
5155 
5156     if (ok != 0)
5157 	*ok = true;
5158 
5159     if (sign.isNull())
5160 	return (int)(factor*unit_size);
5161     else if (sign == "+")
5162 	return base_value + (int)(factor*unit_size);
5163     else // sign == "-"
5164 	return base_value - (int)(factor*unit_size);
5165 }
5166 
lspace() const5167 int MmlMpaddedNode::lspace() const
5168 {
5169     QString value = explicitAttribute("lspace");
5170 
5171     if (value.isNull())
5172 	return 0;
5173 
5174     bool ok;
5175     int lspace = interpretSpacing(value, 0, &ok);
5176 
5177     if (ok)
5178 	return lspace;
5179 
5180     return 0;
5181 }
5182 
width() const5183 int MmlMpaddedNode::width() const
5184 {
5185     int child_width = 0;
5186     if (firstChild() != 0)
5187 	child_width = firstChild()->myRect().width();
5188 
5189     QString value = explicitAttribute("width");
5190     if (value.isNull())
5191 	return child_width;
5192 
5193     bool ok;
5194     int w = interpretSpacing(value, child_width, &ok);
5195     if (ok)
5196 	return w;
5197 
5198     return child_width;
5199 }
5200 
height() const5201 int MmlMpaddedNode::height() const
5202 {
5203     QRect cr;
5204     if (firstChild() == 0)
5205 	cr = QRect(0, 0, 0, 0);
5206     else
5207 	cr = firstChild()->myRect();
5208 
5209     QString value = explicitAttribute("height");
5210     if (value.isNull())
5211 	return -cr.top();
5212 
5213     bool ok;
5214     int h = interpretSpacing(value, -cr.top(), &ok);
5215     if (ok)
5216 	return h;
5217 
5218     return -cr.top();
5219 }
5220 
depth() const5221 int MmlMpaddedNode::depth() const
5222 {
5223     QRect cr;
5224     if (firstChild() == 0)
5225 	cr = QRect(0, 0, 0, 0);
5226     else
5227 	cr = firstChild()->myRect();
5228 
5229     QString value = explicitAttribute("depth");
5230     if (value.isNull())
5231 	return cr.bottom();
5232 
5233     bool ok;
5234     int h = interpretSpacing(value, cr.bottom(), &ok);
5235     if (ok)
5236 	return h;
5237 
5238     return cr.bottom();
5239 }
5240 
layoutSymbol()5241 void MmlMpaddedNode::layoutSymbol()
5242 {
5243     MmlNode *child = firstChild();
5244     if (child == 0)
5245 	return;
5246 
5247     child->setRelOrigin(QPoint(0, 0));
5248 }
5249 
5250 
symbolRect() const5251 QRect MmlMpaddedNode::symbolRect() const
5252 {
5253     return QRect(-lspace(), -height(), lspace() + width(), height() + depth());
5254 }
5255 
5256 // *******************************************************************
5257 // QtMmlWidget
5258 // *******************************************************************
5259 
5260 /*!
5261     \class QtMmlWidget
5262 
5263     \brief The QtMmlWidget class renders mathematical formulas written in MathML 2.0.
5264 
5265     QtMmlWidget implements the Presentation Markup subset of the
5266     MathML 2.0 specification, with a few \link overview.html exceptions\endlink.
5267 
5268     \code
5269     QtMmlWidget *mmlWidget = new QtMmlWidget(this);
5270     QString errorMsg;
5271     int errorLine;
5272     int errorColumn;
5273     bool ok = mmlWidget->setContent(mmlText, &errorMsg, &errorLine, &errorColumn);
5274     if (!ok) {
5275 	qWarning("MathML error: %s, Line: %d, Column: %d",
5276 		 errorMsg.latin1(), errorLine, errorColumn);
5277     }
5278     \endcode
5279 
5280 */
5281 
5282 
5283 /*!
5284     \enum QtMmlWidget::MmlFont
5285 
5286     This ennumerated type is used in fontName() and setFontName() to
5287     specify a font type.
5288 
5289     \value NormalFont	The default font type, used to render
5290     expressions for which no mathvariant or fontfamily is specified,
5291     or for which the "normal" mathvariant is specified.
5292 
5293     \value FrakturFont	The font type used to render expressions for
5294     which the "fraktur" mathvariant is specified.
5295 
5296     \value SansSerifFont    The font type used to render expressions
5297     for which the "sans-serif" mathvariant is specified.
5298 
5299     \value ScriptFont	    The font type used to render expressions
5300     for which the "script" mathvariant is specified.
5301 
5302     \value MonospaceFont    The font type used to render expressions
5303     for which the "monospace" mathvariant is specified.
5304 
5305     \value DoublestruckFont The font type used to render expressions
5306     for which the "doublestruck" mathvariant is specified.
5307 
5308     \sa setFontName() fontName() setBaseFontPointSize() baseFontPointSize()
5309 */
5310 
5311 /*!
5312     Constructs a QtMmlWidget object. The \a parent
5313     parameter is passed to QFrame's constructor.
5314 */
5315 
QtMmlWidget(QWidget * parent)5316 QtMmlWidget::QtMmlWidget(QWidget *parent)
5317     : QFrame(parent)
5318 {
5319     m_doc = new MmlDocument;
5320 }
5321 
5322 /*!
5323     Destructs a QtMmlWidget object.
5324 */
5325 
~QtMmlWidget()5326 QtMmlWidget::~QtMmlWidget()
5327 {
5328     delete m_doc;
5329 }
5330 
5331 /*!
5332     Returns the name of the font used to render the font \a type.
5333 
5334     \sa setFontName()  setBaseFontPointSize() baseFontPointSize() QtMmlWidget::MmlFont
5335 */
5336 
fontName(MmlFont type) const5337 QString QtMmlWidget::fontName(MmlFont type) const
5338 {
5339     return m_doc->fontName(type);
5340 }
5341 
5342 /*!
5343     Sets the name of the font used to render the font \a type to \a name.
5344 
5345     \sa fontName() setBaseFontPointSize() baseFontPointSize() QtMmlWidget::MmlFont
5346 */
5347 
setFontName(MmlFont type,const QString & name)5348 void QtMmlWidget::setFontName(MmlFont type, const QString &name)
5349 {
5350     m_doc->setFontName(type, name);
5351     m_doc->layout();
5352     update();
5353 }
5354 
5355 /*!
5356     If \a b is true, draws a red bounding rectangle around each
5357     expression; if \a b is false, no such rectangle is drawn.
5358     This is mostly useful for debugging MathML expressions.
5359 
5360     \sa drawFrames()
5361 */
5362 
setDrawFrames(bool b)5363 void QtMmlWidget::setDrawFrames(bool b)
5364 {
5365     g_draw_frames = b;
5366     update();
5367 }
5368 
5369 /*!
5370     Returns true if each expression should be drawn with a red
5371     bounding rectangle; otherwise returns false.
5372     This is mostly useful for debugging MathML expressions.
5373 
5374     \sa setDrawFrames()
5375 */
5376 
drawFrames() const5377 bool QtMmlWidget::drawFrames() const
5378 {
5379     return g_draw_frames;
5380 }
5381 
5382 /*!
5383     Clears the contents of this widget.
5384 */
clear()5385 void QtMmlWidget::clear()
5386 {
5387     m_doc->clear();
5388 }
5389 
5390 /*!
5391     Returns the point size of the font used to render expressions
5392     whose scriptlevel is 0.
5393 
5394     \sa setBaseFontPointSize() fontName() setFontName()
5395 */
5396 
baseFontPointSize() const5397 int QtMmlWidget::baseFontPointSize() const
5398 {
5399     return m_doc->baseFontPointSize();
5400 }
5401 
5402 /*!
5403     Sets the point \a size of the font used to render expressions
5404     whose scriptlevel is 0.
5405 
5406     \sa baseFontPointSize() fontName() setFontName()
5407 */
5408 
setBaseFontPointSize(int size)5409 void QtMmlWidget::setBaseFontPointSize(int size)
5410 {
5411     if (size < g_min_font_point_size)
5412 	return;
5413 
5414     m_doc->setBaseFontPointSize(size);
5415     m_doc->layout();
5416     update();
5417 }
5418 
5419 /*!
5420     Returns the size of the formula in pixels.
5421 */
5422 
sizeHint() const5423 QSize QtMmlWidget::sizeHint() const
5424 {
5425     QSize size = m_doc->size();
5426     if (size == QSize(0, 0))
5427     	return QSize(100, 50);
5428     return m_doc->size();
5429 }
5430 
5431 /*!
5432     Sets the MathML expression to be rendered. The expression is given
5433     in the string \a text. If the expression is successfully parsed,
5434     this method returns true; otherwise it returns false. If an error
5435     occured \a errorMsg is set to a diagnostic message, while \a
5436     errorLine and \a errorColumn contain the location of the error.
5437     Any of \a errorMsg, \a errorLine and \a errorColumn may be 0,
5438     in which case they are not set.
5439 
5440     \a text should contain MathML 2.0 presentation markup elements enclosed
5441     in a <math> element.
5442 */
5443 
setContent(const QString & text,QString * errorMsg,int * errorLine,int * errorColumn)5444 bool QtMmlWidget::setContent(const QString &text, QString *errorMsg,
5445 				int *errorLine, int *errorColumn)
5446 {
5447     bool result = m_doc->setContent(text, errorMsg, errorLine, errorColumn);
5448     if (result)
5449 	update();
5450     return result;
5451 }
5452 
5453 /*! \internal */
5454 
paintEvent(QPaintEvent * e)5455 void QtMmlWidget::paintEvent(QPaintEvent *e)
5456 {
5457     QFrame::paintEvent(e);
5458     QPainter p(this);
5459     if (e->rect().intersects(contentsRect()))
5460         p.setClipRegion(e->region().intersected(contentsRect()));
5461 
5462     QSize s = m_doc->size();
5463     int x = (width() - s.width())/2;
5464     int y = (height() - s.height())/2;
5465     m_doc->paint(&p, QPoint(x, y));
5466 }
5467 
5468 /*! \internal */
5469 
dump() const5470 void QtMmlWidget::dump() const
5471 {
5472     m_doc->dump();
5473 }
5474 
5475 // *******************************************************************
5476 // Static helper functions
5477 // *******************************************************************
5478 
entityDeclarations()5479 static QString entityDeclarations()
5480 {
5481     QString result = "<!DOCTYPE math [\n";
5482 
5483     const EntitySpec *ent = g_xml_entity_data;
5484     for (; ent->name != 0; ++ent) {
5485 	result += "\t<!ENTITY " + QString(ent->name) + " \"" + ent->value + "\">\n";
5486     }
5487 
5488     result += "]>\n";
5489 
5490     return result;
5491 }
5492 
interpretSpacing(QString value,int em,int ex,bool * ok)5493 static int interpretSpacing(QString value, int em, int ex, bool *ok)
5494 {
5495     if (ok != 0)
5496 	*ok = true;
5497 
5498     if (value == "thin")
5499 	return 1;
5500 
5501     if (value == "medium")
5502 	return 2;
5503 
5504     if (value == "thick")
5505 	return 3;
5506 
5507     struct HSpacingValue {
5508 	const char *name;
5509 	float factor;
5510     };
5511 
5512     static const HSpacingValue g_h_spacing_data[] =
5513     {
5514 	{ "veryverythinmathspace",	(float) 0.0555556   },
5515 	{ "verythinmathspace",  	(float) 0.111111    },
5516 	{ "thinmathspace",          	(float) 0.166667    },
5517 	{ "mediummathspace",    	(float) 0.222222    },
5518 	{ "thickmathspace",     	(float) 0.277778    },
5519 	{ "verythickmathspace", 	(float) 0.333333    },
5520 	{ "veryverythickmathspace", 	(float) 0.388889    },
5521 	{ 0,    	    	    	(float) 0   	    }
5522     };
5523 
5524     const HSpacingValue *v = g_h_spacing_data;
5525     for (; v->name != 0; ++v) {
5526 	if (value == v->name)
5527 	    return (int)(em*v->factor);
5528     }
5529 
5530     if (value.endsWith("em")) {
5531 	value.truncate(value.length() - 2);
5532 	bool float_ok;
5533 	float factor = value.toFloat(&float_ok);
5534 	if (float_ok && factor >= 0)
5535 	    return (int)(em*factor);
5536 	else {
5537 	    qWarning("interpretSpacing(): could not parse \"%sem\"", value.toLatin1().data());
5538 	    if (ok != 0)
5539 		*ok = false;
5540 	    return 0;
5541 	}
5542     }
5543 
5544     if (value.endsWith("ex")) {
5545 	value.truncate(value.length() - 2);
5546 	bool float_ok;
5547 	float factor = value.toFloat(&float_ok);
5548 	if (float_ok && factor >= 0)
5549 	    return (int)(ex*factor);
5550 	else {
5551 	    qWarning("interpretSpacing(): could not parse \"%sex\"", value.toLatin1().data());
5552 	    if (ok != 0)
5553 		*ok = false;
5554 	    return 0;
5555 	}
5556     }
5557 
5558    if (value.endsWith("cm")) {
5559 	value.truncate(value.length() - 2);
5560 	bool float_ok;
5561 	float factor = value.toFloat(&float_ok);
5562 	if (float_ok && factor >= 0) {
5563 	    Q_ASSERT(qApp->desktop() != 0);
5564 	    QDesktopWidget *dw = qApp->desktop();
5565 	    Q_ASSERT(dw->width() != 0);
5566 	    Q_ASSERT(dw->widthMM() != 0);
5567 	    return (int)(factor*10*dw->width()/dw->widthMM());
5568 	}
5569 	else {
5570 	    qWarning("interpretSpacing(): could not parse \"%scm\"", value.toLatin1().data());
5571 	    if (ok != 0)
5572 		*ok = false;
5573 	    return 0;
5574 	}
5575     }
5576 
5577     if (value.endsWith("mm")) {
5578 	value.truncate(value.length() - 2);
5579 	bool float_ok;
5580 	float factor = value.toFloat(&float_ok);
5581 	if (float_ok && factor >= 0) {
5582 	    Q_ASSERT(qApp->desktop() != 0);
5583 	    QDesktopWidget *dw = qApp->desktop();
5584 	    Q_ASSERT(dw->width() != 0);
5585 	    Q_ASSERT(dw->widthMM() != 0);
5586 	    return (int)(factor*dw->width()/dw->widthMM());
5587 	}
5588 	else {
5589 	    qWarning("interpretSpacing(): could not parse \"%smm\"", value.toLatin1().data());
5590 	    if (ok != 0)
5591 		*ok = false;
5592 	    return 0;
5593 	}
5594     }
5595 
5596     if (value.endsWith("in")) {
5597 	value.truncate(value.length() - 2);
5598 	bool float_ok;
5599 	float factor = value.toFloat(&float_ok);
5600 	if (float_ok && factor >= 0) {
5601 	    Q_ASSERT(qApp->desktop() != 0);
5602 	    QDesktopWidget *dw = qApp->desktop();
5603 	    Q_ASSERT(dw->width() != 0);
5604 	    Q_ASSERT(dw->widthMM() != 0);
5605 	    return (int)(factor*10*dw->width()/(2.54*dw->widthMM()));
5606 	}
5607 	else {
5608 	    qWarning("interpretSpacing(): could not parse \"%sin\"", value.toLatin1().data());
5609 	    if (ok != 0)
5610 		*ok = false;
5611 	    return 0;
5612 	}
5613     }
5614 
5615     if (value.endsWith("px")) {
5616 	value.truncate(value.length() - 2);
5617 	bool float_ok;
5618 	int i = (int) value.toFloat(&float_ok);
5619 	if (float_ok && i >= 0)
5620 	    return i;
5621 	else {
5622 	    qWarning("interpretSpacing(): could not parse \"%spx\"", value.toLatin1().data());
5623 	    if (ok != 0)
5624 		*ok = false;
5625 	    return 0;
5626 	}
5627     }
5628 
5629     bool float_ok;
5630     int i = (int)value.toFloat(&float_ok);
5631     if (float_ok && i >= 0)
5632 	return i;
5633 
5634     qWarning("interpretSpacing(): could not parse \"%s\"", value.toLatin1().data());
5635     if (ok != 0)
5636 	*ok = false;
5637     return 0;
5638 }
5639 
interpretPercentSpacing(QString value,int base,bool * ok)5640 static int interpretPercentSpacing(QString value, int base, bool *ok)
5641 {
5642     if (!value.endsWith("%")) {
5643 	if (ok != 0)
5644 	    *ok = false;
5645 	return 0;
5646     }
5647 
5648     value.truncate(value.length() - 1);
5649     bool float_ok;
5650     float factor = value.toFloat(&float_ok);
5651     if (float_ok && factor >= 0) {
5652 	if (ok != 0)
5653 	    *ok = true;
5654 	return (int)(base*factor/100.0);
5655     }
5656 
5657     qWarning("interpretPercentSpacing(): could not parse \"%s%%\"", value.toLatin1().data());
5658     if (ok != 0)
5659 	*ok = false;
5660     return 0;
5661 }
5662 
interpretPointSize(QString value,bool * ok)5663 static int interpretPointSize(QString value, bool *ok)
5664 {
5665     if (!value.endsWith("pt")) {
5666 	if (ok != 0)
5667 	    *ok = false;
5668 	return 0;
5669     }
5670 
5671     value.truncate(value.length() - 2);
5672     bool float_ok;
5673     int pt_size = (int) value.toFloat(&float_ok);
5674     if (float_ok && pt_size > 0) {
5675 	if (ok != 0)
5676 	    *ok = true;
5677 	return pt_size;
5678     }
5679 
5680     qWarning("interpretPointSize(): could not parse \"%spt\"", value.toLatin1().data());
5681     if (ok != 0)
5682 	*ok = false;
5683     return 0;
5684 }
5685 
mmlFindNodeSpec(Mml::NodeType type)5686 static const NodeSpec *mmlFindNodeSpec(Mml::NodeType type)
5687 {
5688     const NodeSpec *spec = g_node_spec_data;
5689     for (; spec->type != Mml::NoNode; ++spec) {
5690 	if (type == spec->type) return spec;
5691     }
5692     return 0;
5693 }
5694 
mmlFindNodeSpec(const QString & tag)5695 static const NodeSpec *mmlFindNodeSpec(const QString &tag)
5696 {
5697     const NodeSpec *spec = g_node_spec_data;
5698     for (; spec->type != Mml::NoNode; ++spec) {
5699 	if (tag == spec->tag) return spec;
5700     }
5701     return 0;
5702 }
5703 
mmlCheckChildType(Mml::NodeType parent_type,Mml::NodeType child_type,QString * error_str)5704 static bool mmlCheckChildType(Mml::NodeType parent_type, Mml::NodeType child_type,
5705 			    QString *error_str)
5706 {
5707     if (parent_type == Mml::UnknownNode || child_type == Mml::UnknownNode)
5708 	return true;
5709 
5710     const NodeSpec *child_spec = mmlFindNodeSpec(child_type);
5711     const NodeSpec *parent_spec = mmlFindNodeSpec(parent_type);
5712 
5713     Q_ASSERT(parent_spec != 0);
5714     Q_ASSERT(child_spec != 0);
5715 
5716     QString allowed_child_types(parent_spec->child_types);
5717     // null list means any child type is valid
5718     if (allowed_child_types.isNull())
5719 	return true;
5720 
5721     QString child_type_str = QString(" ") + child_spec->type_str + " ";
5722     if (!allowed_child_types.contains(child_type_str)) {
5723 	if (error_str != 0)
5724 	    *error_str = QString("illegal child ")
5725 			  + child_spec->type_str
5726 			  + " for parent "
5727 			  + parent_spec->type_str;
5728 	return false;
5729     }
5730 
5731     return true;
5732 }
5733 
mmlCheckAttributes(Mml::NodeType child_type,const MmlAttributeMap & attr,QString * error_str)5734 static bool mmlCheckAttributes(Mml::NodeType child_type, const MmlAttributeMap &attr,
5735 			    QString *error_str)
5736 {
5737     const NodeSpec *spec = mmlFindNodeSpec(child_type);
5738     Q_ASSERT(spec != 0);
5739 
5740     QString allowed_attr(spec->attributes);
5741     // empty list means any attr is valid
5742     if (allowed_attr.isEmpty())
5743 	return true;
5744 
5745     MmlAttributeMap::const_iterator it = attr.begin(), end = attr.end();
5746     for (; it != end; ++it) {
5747 	QString name = it.key();
5748 
5749 	if (name.indexOf(':') != -1)
5750 	    continue;
5751 
5752 	QString padded_name = " " + name + " ";
5753 	if (!allowed_attr.contains(padded_name)) {
5754 	    if (error_str != 0)
5755 		*error_str = QString("illegal attribute ")
5756 				 + name
5757 				 + " in "
5758 				 + spec->type_str;
5759 	    return false;
5760 	}
5761     }
5762 
5763     return true;
5764 }
5765 
attributeIndex(const QString & name)5766 static int attributeIndex(const QString &name)
5767 {
5768     for (unsigned i = 0; i < g_oper_spec_rows; ++i) {
5769 	if (name == g_oper_spec_names[i])
5770 	    return i;
5771     }
5772     return -1;
5773 }
5774 
decodeEntityValue(QString literal)5775 static QString decodeEntityValue(QString literal)
5776 {
5777     QString result;
5778 
5779     while (!literal.isEmpty()) {
5780 
5781 	if (!literal.startsWith("&#")) {
5782 	    qWarning("decodeEntityValue(): bad entity literal: \"%s\"", literal.toLatin1().data());
5783 	    return QString();
5784 	}
5785 
5786 	literal = literal.right(literal.length() - 2);
5787 
5788 	int i = literal.indexOf(';');
5789 	if (i == -1) {
5790 	    qWarning("decodeEntityValue(): bad entity literal: \"%s\"", literal.toLatin1().data());
5791 	    return QString();
5792 	}
5793 
5794 	QString char_code = literal.left(i);
5795 	literal = literal.right(literal.length() - i - 1);
5796 
5797 	if (char_code.isEmpty()) {
5798 	    qWarning("decodeEntityValue(): bad entity literal: \"%s\"", literal.toLatin1().data());
5799 	    return QString();
5800 	}
5801 
5802 	if (char_code.at(0) == 'x') {
5803 	    char_code = char_code.right(char_code.length() - 1);
5804 	    bool ok;
5805 	    unsigned c = char_code.toUInt(&ok, 16);
5806 	    if (!ok) {
5807 	        qWarning("decodeEntityValue(): bad entity literal: \"%s\"", literal.toLatin1().data());
5808 		return QString();
5809 	    }
5810 	    result += QChar(c);
5811 	}
5812 	else {
5813 	    bool ok;
5814 	    unsigned c = char_code.toUInt(&ok, 10);
5815 	    if (!ok) {
5816 	        qWarning("decodeEntityValue(): bad entity literal: \"%s\"", literal.toLatin1().data());
5817 		return QString();
5818 	    }
5819 	    result += QChar(c);
5820 	}
5821     }
5822 
5823     return result;
5824 }
5825 
searchEntitySpecData(const QString & value,const EntitySpec * from=0)5826 static const EntitySpec *searchEntitySpecData(const QString &value, const EntitySpec *from = 0)
5827 {
5828     const EntitySpec *ent = from;
5829     if (ent == 0)
5830 	ent = g_xml_entity_data;
5831     for (; ent->name != 0; ++ent) {
5832 	QString ent_value = decodeEntityValue(ent->value);
5833 	if (value == ent_value)
5834 	    return ent;
5835     }
5836     return 0;
5837 }
5838 
5839 struct OperSpecSearchResult
5840 {
OperSpecSearchResultOperSpecSearchResult5841     OperSpecSearchResult() { prefix_form = infix_form = postfix_form = 0; }
5842 
5843     const OperSpec *prefix_form,
5844 		   *infix_form,
5845 		   *postfix_form;
5846 
5847     const OperSpec *&getForm(Mml::FormType f);
haveFormOperSpecSearchResult5848     bool haveForm(Mml::FormType f)
5849 	{ return getForm(f) != 0; }
addFormOperSpecSearchResult5850     void addForm(const OperSpec *spec)
5851 	{ getForm(spec->form) = spec; }
5852 };
5853 
getForm(Mml::FormType f)5854 const OperSpec *&OperSpecSearchResult::getForm(Mml::FormType f)
5855 {
5856     switch (f) {
5857 	case Mml::PrefixForm:
5858 	    return prefix_form;
5859 	case Mml::InfixForm:
5860 	    return infix_form;
5861 	case Mml::PostfixForm:
5862 	    return postfix_form;
5863     }
5864     return postfix_form; // just to avoid warning
5865 }
5866 
5867 /*
5868     Searches g_oper_spec_data and returns any instance of operator name. There may
5869     be more instances, but since the list is sorted, they will be next to each other.
5870 */
searchOperSpecData(const QString & name)5871 static const OperSpec *searchOperSpecData(const QString &name)
5872 {
5873     const char *name_latin1 = name.toLatin1().data();
5874 
5875     // binary search
5876     // establish invariant g_oper_spec_data[begin].name < name < g_oper_spec_data[end].name
5877 
5878     int cmp = qstrcmp(name_latin1, g_oper_spec_data[0].name);
5879     if (cmp < 0)
5880     	return 0;
5881 
5882     if (cmp == 0)
5883     	return g_oper_spec_data;
5884 
5885     uint begin = 0;
5886     uint end = g_oper_spec_count;
5887 
5888     // invariant holds
5889     while (end - begin > 1) {
5890     	uint mid = (begin + end)/2;
5891 
5892     	const OperSpec *spec = g_oper_spec_data + mid;
5893 	int cmp = qstrcmp(name_latin1, spec->name);
5894     	if (cmp < 0)
5895 	    end = mid;
5896 	else if (cmp > 0)
5897 	    begin = mid;
5898 	else
5899 	    return spec;
5900     }
5901 
5902     return 0;
5903 }
5904 
5905 /*
5906     This searches g_oper_spec_data until at least one name in name_list is found with FormType form,
5907     or until name_list is exhausted. The idea here is that if we don't find the operator in the
5908     specified form, we still want to use some other available form of that operator.
5909 */
_mmlFindOperSpec(const QStringList & name_list,Mml::FormType form)5910 static OperSpecSearchResult _mmlFindOperSpec(const QStringList &name_list, Mml::FormType form)
5911 {
5912     OperSpecSearchResult result;
5913 
5914     QStringList::const_iterator it = name_list.begin();
5915     for (; it != name_list.end(); ++it) {
5916     	const QString &name = *it;
5917 
5918     	const OperSpec *spec = searchOperSpecData(name);
5919 
5920 	if (spec == 0)
5921 	    continue;
5922 
5923     	const char *name_latin1 = name.toLatin1().data();
5924 
5925     	// backtrack to the first instance of name
5926 	while (spec > g_oper_spec_data && qstrcmp((spec - 1)->name, name_latin1) == 0)
5927     	    --spec;
5928 
5929     	// iterate over instances of name until the instances are exhausted or until we
5930 	// find an instance in the specified form.
5931 	do {
5932 	    result.addForm(spec++);
5933 	    if (result.haveForm(form))
5934 	    	break;
5935 	} while (qstrcmp(spec->name, name_latin1) == 0);
5936 
5937 	if (result.haveForm(form))
5938 	    break;
5939     }
5940 
5941     return result;
5942 }
5943 
5944 /*
5945     text is a string between <mo> and </mo>. It can be a character ('+'), an
5946     entity reference ("&infin;") or a character reference ("&#x0221E"). Our
5947     job is to find an operator spec in the operator dictionary (g_oper_spec_data)
5948     that matches text. Things are further complicated by the fact, that many
5949     operators come in several forms (prefix, infix, postfix).
5950 
5951     If available, this function returns an operator spec matching text in the specified
5952     form. If such operator is not available, returns an operator spec that matches
5953     text, but of some other form in the preference order specified by the MathML spec.
5954     If that's not available either, returns the default operator spec.
5955 */
mmlFindOperSpec(const QString & text,Mml::FormType form)5956 static const OperSpec *mmlFindOperSpec(const QString &text, Mml::FormType form)
5957 {
5958     QStringList name_list;
5959     name_list.append(text);
5960 
5961     // First, just try to find text in the operator dictionary.
5962     OperSpecSearchResult result = _mmlFindOperSpec(name_list, form);
5963 
5964     if (!result.haveForm(form)) {
5965     	// Try to find other names for the operator represented by text.
5966 
5967 	const EntitySpec *ent = 0;
5968 	for (;;) {
5969 	    ent = searchEntitySpecData(text, ent);
5970 	    if (ent == 0)
5971 		break;
5972 	    name_list.append('&' + QString(ent->name) + ';');
5973 	    ++ent;
5974 	}
5975 
5976 	result = _mmlFindOperSpec(name_list, form);
5977     }
5978 
5979     const OperSpec *spec = result.getForm(form);
5980     if (spec != 0)
5981 	return spec;
5982 
5983     spec = result.getForm(Mml::InfixForm);
5984     if (spec != 0)
5985 	return spec;
5986 
5987     spec = result.getForm(Mml::PostfixForm);
5988     if (spec != 0)
5989 	return spec;
5990 
5991     spec = result.getForm(Mml::PrefixForm);
5992     if (spec != 0)
5993 	return spec;
5994 
5995     return &g_oper_spec_defaults;
5996 }
5997 
mmlDictAttribute(const QString & name,const OperSpec * spec)5998 static QString mmlDictAttribute(const QString &name, const OperSpec *spec)
5999 {
6000     int i = attributeIndex(name);
6001     if (i == -1)
6002 	return QString();
6003     else
6004 	return spec->attributes[i];
6005 }
6006 
interpretMathVariant(const QString & value,bool * ok)6007 static uint interpretMathVariant(const QString &value, bool *ok)
6008 {
6009     struct MathVariantValue {
6010 	const char *value;
6011 	uint mv;
6012     };
6013 
6014     static const MathVariantValue g_mv_data[] =
6015     {
6016 	{ "normal",     	    	    Mml::NormalMV },
6017 	{ "bold",   	    	    	    Mml::BoldMV },
6018 	{ "italic",   	    	    	    Mml::ItalicMV },
6019 	{ "bold-italic",   	    	    Mml::BoldMV | Mml::ItalicMV },
6020 	{ "double-struck",   	    	    Mml::DoubleStruckMV },
6021 	{ "bold-fraktur",   	    	    Mml::BoldMV | Mml::FrakturMV },
6022 	{ "script",   	    	    	    Mml::ScriptMV },
6023 	{ "bold-script",	    	    Mml::BoldMV | Mml::ScriptMV },
6024 	{ "fraktur",   	    	    	    Mml::FrakturMV },
6025 	{ "sans-serif",   	    	    Mml::SansSerifMV },
6026 	{ "bold-sans-serif",   	    	    Mml::BoldMV | Mml::SansSerifMV },
6027 	{ "sans-serif-italic",   	    Mml::SansSerifMV | Mml::ItalicMV },
6028 	{ "sans-serif-bold-italic",         Mml::SansSerifMV | Mml::ItalicMV | Mml::BoldMV },
6029 	{ "monospace",   	    	    Mml::MonospaceMV },
6030 	{ 0,    	    	    	    0 }
6031     };
6032 
6033     const MathVariantValue *v = g_mv_data;
6034     for (; v->value != 0; ++v) {
6035 	if (value == v->value) {
6036 	    if (ok != 0)
6037 		*ok = true;
6038 	    return v->mv;
6039 	}
6040     }
6041 
6042     if (ok != 0)
6043 	*ok = false;
6044 
6045    qWarning("interpretMathVariant(): could not parse value: \"%s\"", value.toLatin1().data());
6046 
6047     return Mml::NormalMV;
6048 }
6049 
interpretForm(const QString & value,bool * ok)6050 static Mml::FormType interpretForm(const QString &value, bool *ok)
6051 {
6052     if (ok != 0)
6053 	*ok = true;
6054 
6055     if (value == "prefix")
6056 	return Mml::PrefixForm;
6057     if (value == "infix")
6058 	return Mml::InfixForm;
6059     if (value == "postfix")
6060 	return Mml::PostfixForm;
6061 
6062     if (ok != 0)
6063 	*ok = false;
6064 
6065     qWarning("interpretForm(): could not parse value \"%s\"", value.toLatin1().data());
6066     return Mml::InfixForm;
6067 }
6068 
interpretColAlign(const QString & value_list,uint colnum,bool * ok)6069 static Mml::ColAlign interpretColAlign(const QString &value_list, uint colnum, bool *ok)
6070 {
6071     QString value = interpretListAttr(value_list, colnum, "center");
6072 
6073     if (ok != 0)
6074 	*ok = true;
6075 
6076     if (value == "left")
6077 	return Mml::ColAlignLeft;
6078     if (value == "right")
6079 	return Mml::ColAlignRight;
6080     if (value == "center")
6081 	return Mml::ColAlignCenter;
6082 
6083     if (ok != 0)
6084 	*ok = false;
6085 
6086     qWarning("interpretColAlign(): could not parse value \"%s\"", value.toLatin1().data());
6087     return Mml::ColAlignCenter;
6088 }
6089 
interpretRowAlign(const QString & value_list,uint rownum,bool * ok)6090 static Mml::RowAlign interpretRowAlign(const QString &value_list, uint rownum, bool *ok)
6091 {
6092     QString value = interpretListAttr(value_list, rownum, "axis");
6093 
6094     if (ok != 0)
6095 	*ok = true;
6096 
6097     if (value == "top")
6098 	return Mml::RowAlignTop;
6099     if (value == "center")
6100 	return Mml::RowAlignCenter;
6101     if (value == "bottom")
6102 	return Mml::RowAlignBottom;
6103     if (value == "baseline")
6104 	return Mml::RowAlignBaseline;
6105     if (value == "axis")
6106 	return Mml::RowAlignAxis;
6107 
6108     if (ok != 0)
6109 	*ok = false;
6110 
6111     qWarning("interpretRowAlign(): could not parse value \"%s\"", value.toLatin1().data());
6112     return Mml::RowAlignAxis;
6113 }
6114 
interpretListAttr(const QString & value_list,int idx,const QString & def)6115 static QString interpretListAttr(const QString &value_list, int idx, const QString &def)
6116 {
6117     QStringList l = value_list.split(' ');
6118 
6119     if (l.count() == 0)
6120 	return def;
6121 
6122     if (l.count() <= idx)
6123 	return l[l.count() - 1];
6124     else
6125 	return l[idx];
6126 }
6127 
interpretFrameType(const QString & value_list,uint idx,bool * ok)6128 static Mml::FrameType interpretFrameType(const QString &value_list, uint idx, bool *ok)
6129 {
6130     if (ok != 0)
6131 	*ok = true;
6132 
6133     QString value = interpretListAttr(value_list, idx, "none");
6134 
6135     if (value == "none")
6136 	return Mml::FrameNone;
6137     if (value == "solid")
6138 	return Mml::FrameSolid;
6139     if (value == "dashed")
6140 	return Mml::FrameDashed;
6141 
6142     if (ok != 0)
6143 	*ok = false;
6144 
6145     qWarning("interpretFrameType(): could not parse value \"%s\"", value.toLatin1().data());
6146     return Mml::FrameNone;
6147 }
6148 
6149 
interpretFrameSpacing(const QString & value_list,int em,int ex,bool * ok)6150 static Mml::FrameSpacing interpretFrameSpacing(const QString &value_list, int em, int ex, bool *ok)
6151 {
6152     Mml::FrameSpacing fs;
6153 
6154     QStringList l = value_list.split(' ');
6155     if (l.count() != 2) {
6156 	qWarning("interpretFrameSpacing: could not parse value \"%s\"", value_list.toLatin1().data());
6157 	if (ok != 0)
6158 	    *ok = false;
6159 	return Mml::FrameSpacing((int)(0.4*em), (int)(0.5*ex));
6160     }
6161 
6162     bool hor_ok, ver_ok;
6163     fs.m_hor = interpretSpacing(l[0], em, ex, &hor_ok);
6164     fs.m_ver = interpretSpacing(l[1], em, ex, &ver_ok);
6165 
6166     if (ok != 0)
6167 	*ok = hor_ok && ver_ok;
6168 
6169     return fs;
6170 }
6171 
interpretDepreciatedFontAttr(const MmlAttributeMap & font_attr,QFont & fn,int em,int ex)6172 static QFont interpretDepreciatedFontAttr(const MmlAttributeMap &font_attr, QFont &fn, int em, int ex)
6173 {
6174     if (font_attr.contains("fontsize")) {
6175 	QString value = font_attr["fontsize"];
6176 
6177 	for (;;) {
6178 
6179 	    bool ok;
6180 	    int ptsize = interpretPointSize(value, &ok);
6181 	    if (ok) {
6182 		fn.setPointSize(ptsize);
6183 		break;
6184 	    }
6185 
6186 	    ptsize = interpretPercentSpacing(value, fn.pointSize(), &ok);
6187 	    if (ok) {
6188 		fn.setPointSize(ptsize);
6189 		break;
6190 	    }
6191 
6192 	    int size = interpretSpacing(value, em, ex, &ok);
6193 	    if (ok) {
6194 		fn.setPixelSize(size);
6195 		break;
6196 	    }
6197 
6198 	    break;
6199 	}
6200     }
6201 
6202     if (font_attr.contains("fontweight")) {
6203 	QString value = font_attr["fontweight"];
6204 	if (value == "normal")
6205 	    fn.setBold(false);
6206 	else if (value == "bold")
6207 	    fn.setBold(true);
6208 	else
6209 	    qWarning("interpretDepreciatedFontAttr(): could not parse fontweight \"%s\"", value.toLatin1().data());
6210     }
6211 
6212     if (font_attr.contains("fontstyle")) {
6213 	QString value = font_attr["fontstyle"];
6214 	if (value == "normal")
6215 	    fn.setItalic(false);
6216 	else if (value == "italic")
6217 	    fn.setItalic(true);
6218 	else
6219 	    qWarning("interpretDepreciatedFontAttr(): could not parse fontstyle \"%s\"", value.toLatin1().data());
6220     }
6221 
6222     if (font_attr.contains("fontfamily")) {
6223 	QString value = font_attr["fontfamily"];
6224 	fn.setFamily(value);
6225     }
6226 
6227     return fn;
6228 }
6229 
interpretMathSize(QString value,QFont & fn,int em,int ex,bool * ok)6230 static QFont interpretMathSize(QString value, QFont &fn, int em, int ex, bool *ok)
6231 {
6232     if (ok != 0)
6233 	*ok = true;
6234 
6235     if (value == "small") {
6236 	fn.setPointSize((int)(fn.pointSize()*0.7));
6237 	return fn;
6238     }
6239 
6240     if (value == "normal")
6241 	return fn;
6242 
6243     if (value == "big") {
6244 	fn.setPointSize((int)(fn.pointSize()*1.5));
6245 	return fn;
6246     }
6247 
6248     bool size_ok;
6249 
6250     int ptsize = interpretPointSize(value, &size_ok);
6251     if (size_ok) {
6252 	fn.setPointSize(ptsize);
6253 	return fn;
6254     }
6255 
6256     int size = interpretSpacing(value, em, ex, &size_ok);
6257     if (size_ok) {
6258 	fn.setPixelSize(size);
6259 	return fn;
6260     }
6261 
6262     if (ok != 0)
6263 	*ok = false;
6264     qWarning("interpretMathSize(): could not parse mathsize \"%s\"", value.toLatin1().data());
6265     return fn;
6266 }
6267 
6268 /*!
6269     \class QtMmlDocument
6270 
6271     \brief The QtMmlDocument class renders mathematical formulas written in MathML 2.0.
6272 
6273     This class provides a direct API to the rendering engine used by
6274     QtMmlWidget. It can be used to paint MathML inside other widgets.
6275 
6276     All methods work the same as the corresponding methods in QtMmlWidget.
6277 */
6278 
6279 /*!
6280   Constructs an empty MML document.
6281 */
QtMmlDocument()6282 QtMmlDocument::QtMmlDocument()
6283 {
6284     m_doc = new MmlDocument;
6285 }
6286 
6287 /*!
6288   Destroys the MML document.
6289 */
~QtMmlDocument()6290 QtMmlDocument::~QtMmlDocument()
6291 {
6292     delete m_doc;
6293 }
6294 
6295 /*!
6296     Clears the contents of this MML document.
6297 */
clear()6298 void QtMmlDocument::clear()
6299 {
6300     m_doc->clear();
6301 }
6302 
6303 /*!
6304     Sets the MathML expression to be rendered. The expression is given
6305     in the string \a text. If the expression is successfully parsed,
6306     this method returns true; otherwise it returns false. If an error
6307     occured \a errorMsg is set to a diagnostic message, while \a
6308     errorLine and \a errorColumn contain the location of the error.
6309     Any of \a errorMsg, \a errorLine and \a errorColumn may be 0,
6310     in which case they are not set.
6311 
6312     \a text should contain MathML 2.0 presentation markup elements enclosed
6313     in a <math> element.
6314 */
setContent(QString text,QString * errorMsg,int * errorLine,int * errorColumn)6315 bool QtMmlDocument::setContent(QString text, QString *errorMsg,
6316                                int *errorLine, int *errorColumn)
6317 {
6318     return m_doc->setContent(text, errorMsg, errorLine, errorColumn);
6319 }
6320 
6321 /*!
6322   Renders this MML document with the painter \a p at position \a pos.
6323 */
paint(QPainter * p,const QPoint & pos) const6324 void QtMmlDocument::paint(QPainter *p, const QPoint &pos) const
6325 {
6326     m_doc->paint(p, pos);
6327 }
6328 
6329 /*!
6330     Returns the size of this MML document, as rendered, in pixels.
6331 */
size() const6332 QSize QtMmlDocument::size() const
6333 {
6334     return m_doc->size();
6335 }
6336 
6337 /*!
6338     Returns the name of the font used to render the font \a type.
6339 
6340     \sa setFontName()  setBaseFontPointSize() baseFontPointSize() QtMmlWidget::MmlFont
6341 */
fontName(QtMmlWidget::MmlFont type) const6342 QString QtMmlDocument::fontName(QtMmlWidget::MmlFont type) const
6343 {
6344     return m_doc->fontName(type);
6345 }
6346 
6347 /*!
6348     Sets the name of the font used to render the font \a type to \a name.
6349 
6350     \sa fontName() setBaseFontPointSize() baseFontPointSize() QtMmlWidget::MmlFont
6351 */
setFontName(QtMmlWidget::MmlFont type,const QString & name)6352 void QtMmlDocument::setFontName(QtMmlWidget::MmlFont type, const QString &name)
6353 {
6354     m_doc->setFontName(type, name);
6355     m_doc->layout();
6356 }
6357 
6358 /*!
6359     Returns the point size of the font used to render expressions
6360     whose scriptlevel is 0.
6361 
6362     \sa setBaseFontPointSize() fontName() setFontName()
6363 */
baseFontPointSize() const6364 int QtMmlDocument::baseFontPointSize() const
6365 {
6366     return m_doc->baseFontPointSize();
6367 }
6368 
6369 /*!
6370     Sets the point \a size of the font used to render expressions
6371     whose scriptlevel is 0.
6372 
6373     \sa baseFontPointSize() fontName() setFontName()
6374 */
setBaseFontPointSize(int size)6375 void QtMmlDocument::setBaseFontPointSize(int size)
6376 {
6377     m_doc->setBaseFontPointSize(size);
6378     m_doc->layout();
6379 }
6380