xref: /AOO41X/main/starmath/source/mathtype.cxx (revision d107581f588b53ce11339a8a18091c0f86ec8bb4)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_starmath.hxx"
26 
27 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
28 #include <mathtype.hxx>
29 
30 #ifndef _TOOLS_DEBUG_H
31 #include <tools/debug.hxx>
32 #endif
33 
34 #include <sfx2/docfile.hxx>
35 
36 #define APPEND(str,ascii) str.AppendAscii(RTL_CONSTASCII_STRINGPARAM(ascii))
37 
38 #if 0
39 String aEmbelList[21] =
40 {
41     " ",
42     " ",
43     "single dot",
44     "double dot",
45     "triple dot",
46     "single prime",
47     "double prime",
48     "backwards prime (left of character)",
49     "tilde",
50     "hat (circumflex)",
51     "diagonal slash through character",
52     "right arrow",
53     "left arrow",
54     "double-headed arrow",
55     "right single-barbed arrow",
56     "left single-barbed arrow",
57     "mid-height horizontal bar",
58     "over-bar",
59     "triple prime",
60     "over-arc, concave downward",
61     "over-arc, concave upward"
62 };
63 
64 String aSelectorList[49] =
65 {
66     "angle brackets",
67     "parentheses",
68     "braces (curly brackets)",
69     "square brackets",
70     "vertical bars",
71     "double vertical bars",
72     "floor brackets",
73     "ceiling brackets",
74     "left brace, left brace",
75     "right brace, right brace",
76     "right brace, left brace",
77     "left brace, right parenthesis",
78     "left parenthesis, right brace",
79     "radical",
80     "fractions",
81     "subscript/superscript",
82     "underbar",
83     "overbar",
84     "left-pointing arrow",
85     "right-pointing arrow",
86     "left- and right-pointing arrow",
87     "single integral",
88     "double integral",
89     "triple integral",
90     "single summation-style integral",
91     "double summation-style integral",
92     "triple summation-style integral",
93     "upper horizontal brace",
94     "lower horizontal brace",
95     "summation",
96     "summation (integral-style limits)",
97     "product",
98     "product (integral-style limits)",
99     "coproduct",
100     "coproduct (integral-style limits)",
101     "union",
102     "union (integral-style limits)",
103     "intersection",
104     "intersection (integral-style limits)",
105     "limit",
106     "long division",
107     "slash fractions",
108     "big integral-style operators",
109     "big summation-style operators",
110     "leading sub- and superscripts",
111     "Dirac delta",
112     "under arrow",
113     "over arrow",
114     "over arc"
115 };
116 
117 String aIntegralOpt[2] =
118 {
119     "fixed-size integral",
120     "integral expands vertically to fit its contents"
121 };
122 
123 String aFenceOpt[3] =
124 {
125     "center fence on math axis",
126     "center fence on contents, place math axis of contents on math axis of containing line",
127     "center fence on contents, center contents on math axis of containing line"
128 };
129 
130 String aTypeFaces[12] =
131 {
132     "",
133     "fnTEXT",
134     "fnFUNCTION",
135     "fnVARIABLE",
136     "fnLCGREEK",
137     "fnUCGREEK",
138     "fnSYMBOL",
139     "fnVECTOR",
140     "fnNUMBER",
141     "fnUSER1",
142     "fnUSER2",
143     "fnMTEXTRA"
144 };
145 
146 String aSizes[7] =
147 {
148     "full",
149     "subscript",
150     "sub-subscript",
151     "symbol",
152     "sub-symbol",
153     "user 1",
154     "user 2"
155 };
156 #endif
157 
Convert(sal_Unicode nIn)158 static sal_Unicode Convert(sal_Unicode nIn)
159 {
160     //Find the best match in accepted unicode for our private area symbols
161     static sal_Unicode aStarMathPrivateToUnicode[] =
162     {
163         0x2030, 0xF613, 0xF612, 0x002B, 0x003C, 0x003E, 0xE425, 0xE421, 0xE088, 0x2208,
164         0x0192, 0x2026, 0x2192, 0x221A, 0x221A, 0x221A, 0xE090, 0x005E, 0x02C7, 0x02D8,
165         0x00B4, 0x0060, 0x02DC, 0x00AF, 0x0362, 0xE099, 0xE09A, 0x20DB, 0xE09C, 0xE09D,
166         0x0028, 0x0029, 0x2220, 0x22AF, 0xE0A2, 0xE0A3, 0xE0A4, 0xE0A5, 0xE0A6, 0xE0A7,
167         0x002F, 0x005C, 0x274F, 0xE0AB, 0x0393, 0x0394, 0x0398, 0x039b, 0x039e, 0x03A0,
168         0x03a3, 0x03a5, 0x03a6, 0x03a8, 0x03A9, 0x03B1, 0x03B2, 0x03b3, 0x03b4, 0x03b5,
169         0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
170         0x03c0, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03b5,
171         0x03d1, 0x03d6, 0xE0D2, 0x03db, 0x2118, 0x2202, 0x2129, 0xE0D7, 0xE0D8, 0x22A4,
172         0xE0DA, 0x2190, 0x2191, 0x2193
173     };
174     if ((nIn >= 0xE080) && (nIn <= 0xE0DD))
175         nIn = aStarMathPrivateToUnicode[nIn-0xE080];
176 
177     //For whatever unicode glyph that equation editor doesn't ship with that
178     //we have a possible match we can munge it to.
179     switch (nIn)
180     {
181         case 0x2223:
182             nIn = '|';
183             break;
184         default:
185             break;
186     }
187 
188     return nIn;
189 }
190 
Init()191 void MathType::Init()
192 {
193     //These are the default MathType sizes
194     aSizeTable[0]=12;
195     aSizeTable[1]=8;
196     aSizeTable[2]=6;
197     aSizeTable[3]=24;
198     aSizeTable[4]=10;
199     aSizeTable[5]=12;
200     aSizeTable[6]=12;
201 
202     /*
203     These are the default MathType italic/bold settings If mathtype is changed
204     from its defaults, there is nothing we can do, as this information is not
205     stored in the document
206     */
207     MathTypeFont aFont;
208     for(sal_uInt8 i=1;i<=11;i++)
209     {
210         aFont.nTface = i+128;
211         switch (i)
212         {
213             default:
214                 aFont.nStyle=0;
215                 break;
216             case 3:
217             case 4:
218                 aFont.nStyle=1;
219                 break;
220             case 7:
221                 aFont.nStyle=2;
222                 break;
223         }
224         aUserStyles.insert(aFont);
225     }
226 }
227 
228 
229 /*ToDo replace with table rather than switch, returns
230  sal_True in the case that the char is just a char, and
231  sal_False if the character is an operator which must not be
232  placed inside the quote sequence designed to protect
233  against being parsed as a keyword
234 
235  General solution required to force starmath to handle
236  unicode math chars the way it handles its own math
237  chars rathar than handle them as text as it will do
238  for the default case below, i.e. incorrect spacing
239  between math symbols and ordinary text e.g. 1=2 rather
240  than 1 = 2
241  */
LookupChar(sal_Unicode nChar,String & rRet,sal_uInt8 nVersion,sal_uInt8 nTypeFace)242 sal_Bool MathType::LookupChar(sal_Unicode nChar,String &rRet,sal_uInt8 nVersion,
243     sal_uInt8 nTypeFace)
244 {
245     sal_Bool bRet=sal_False;
246     const char *pC = NULL;
247     switch(nChar)
248     {
249         case 0x0000:
250             pC = " none ";
251             break;
252         case 0x00ac:
253             pC = " neg ";
254             break;
255         case 0x00b1:
256             pC = " +- ";
257             break;
258         case '(':
259             pC = " \\( ";
260             break;
261         case ')':
262             pC = " \\) ";
263             break;
264         case '[':
265             pC = " \\[ ";
266             break;
267         case ']':
268             pC = " \\] ";
269             break;
270         case '.':
271             pC = " \".\" ";
272             break;
273         case 0xae:
274             if ((nVersion < 3) && (nTypeFace == 0x86))
275                 pC = " rightarrow ";
276             else
277             {
278                 rRet.Append(nChar);
279                 bRet=sal_True;
280             }
281             break;
282         case 0x00fb:
283             if ((nVersion < 3) && (nTypeFace == 0x81))
284                 nChar = 0xDF;
285             rRet.Append(nChar);
286             bRet=sal_True;
287             break;
288         case 'a':
289             if ((nVersion < 3) && (nTypeFace == 0x84))
290                 nChar = 0x3b1;
291             rRet.Append(nChar);
292             bRet=sal_True;
293             break;
294         case 'b':
295             if ((nVersion < 3) && (nTypeFace == 0x84))
296                 nChar = 0x3b2;
297             rRet.Append(nChar);
298             bRet=sal_True;
299             break;
300         case 'l':
301             if ((nVersion < 3) && (nTypeFace == 0x84))
302                 nChar = 0x3bb;
303             rRet.Append(nChar);
304             bRet=sal_True;
305             break;
306         case 'n':
307             if ((nVersion < 3) && (nTypeFace == 0x84))
308                 nChar = 0x3bd;
309             rRet.Append(nChar);
310             bRet=sal_True;
311             break;
312         case 'r':
313             if ((nVersion < 3) && (nTypeFace == 0x84))
314                 nChar = 0x3c1;
315             rRet.Append(nChar);
316             bRet=sal_True;
317             break;
318         case 'D':
319             if ((nVersion < 3) && (nTypeFace == 0x84))
320                 nChar = 0x394;
321             rRet.Append(nChar);
322             bRet=sal_True;
323             break;
324         case 0xa9:
325             if ((nVersion < 3) && (nTypeFace == 0x82))
326                 nChar = '\'';
327             rRet.Append(nChar);
328             bRet=sal_True;
329             break;
330         case 0x00f1:
331             if ((nVersion < 3) && (nTypeFace == 0x86))
332                 pC = " \\rangle ";
333             else
334             {
335                 rRet.Append(nChar);
336                 bRet=sal_True;
337             }
338             break;
339         case 0x00a3:
340             if ((nVersion < 3) && (nTypeFace == 0x86))
341                 pC = " <= ";
342             else
343             {
344                 rRet.Append(nChar);
345                 bRet=sal_True;
346             }
347             break;
348         case 0x00de:
349             if ((nVersion < 3) && (nTypeFace == 0x86))
350                 pC = " drarrow ";
351             else
352             {
353                 rRet.Append(nChar);
354                 bRet=sal_True;
355             }
356             break;
357         case 0x0057:
358             if ((nVersion < 3) && (nTypeFace == 0x85))
359                 pC = " %OMEGA ";
360             else
361             {
362                 rRet.Append(nChar);
363                 bRet=sal_True;
364             }
365             break;
366         case 0x007b:
367             pC = " lbrace ";
368             break;
369         case 0x007c:
370             pC = " \\lline ";
371             break;
372         case 0x007d:
373             pC = " rbrace ";
374             break;
375         case 0x007e:
376             pC = " \"~\" ";
377             break;
378         case 0x2224:
379             pC = " ndivides ";
380             break;
381         case 0x2225:
382             pC = " parallel ";
383             break;
384         case 0x00d7:
385             if (nVersion < 3)
386                 pC = " cdot ";
387             else
388                 pC = " times ";
389             break;
390         case 0x00f7:
391             pC = " div ";
392             break;
393         case 0x019b:
394             pC = " lambdabar ";
395             break;
396         case 0x2026:
397             pC = " dotslow ";
398             break;
399         case 0x2022:
400             pC = " cdot ";
401             break;
402         case 0x2102:
403             pC = " setC ";
404             break;
405         case 0x210f:
406             pC = " hbar ";
407             break;
408         case 0x2111:
409             pC = " Im ";
410             break;
411         case 0x2115:
412             pC = " setN ";
413             break;
414         case 0x2118:
415             pC = " wp ";
416             break;
417         case 0x211a:
418             pC = " setQ ";
419             break;
420         case 0x211c:
421             pC = " Re ";
422             break;
423         case 0x211d:
424             pC = " setR ";
425             break;
426         case 0x2124:
427             pC = " setZ ";
428             break;
429         case 0x2135:
430             pC = " aleph ";
431             break;
432         case 0x2190:
433             pC = " leftarrow ";
434             break;
435         case 0x2191:
436             pC = " uparrow ";
437             break;
438         case 0x2192:
439             pC = " rightarrow ";
440             break;
441         case 0x0362:
442             pC = " widevec ";
443             break;
444         case 0x2193:
445             pC = " downarrow ";
446             break;
447         case 0x21d0:
448             pC = " dlarrow ";
449             break;
450         case 0x21d2:
451             pC = " drarrow ";
452             break;
453         case 0x21d4:
454             pC = " dlrarrow ";
455             break;
456         case 0x2200:
457             pC = " forall ";
458             break;
459         case 0x2202:
460             pC = " partial ";
461             break;
462         case 0x2203:
463             pC = " exists ";
464             break;
465         case 0x2205:
466             pC = " emptyset ";
467             break;
468         case 0x2207:
469             pC = " nabla ";
470             break;
471         case 0x2208:
472             pC = " in ";
473             break;
474         case 0x2209:
475             pC = " notin ";
476             break;
477         case 0x220d:
478             pC = " owns ";
479             break;
480         case 0x220f:
481             pC = " prod ";
482             break;
483         case 0x2210:
484             pC = " coprod ";
485             break;
486         case 0x2211:
487             pC = " sum ";
488             break;
489         case 0x2212:
490             pC = " - ";
491             break;
492         case 0x2213:
493             pC = " -+ ";
494             break;
495         case 0x2217:
496             pC = " * ";
497             break;
498         case 0x2218:
499             pC = " circ ";
500             break;
501         case 0x221d:
502             pC = " prop ";
503             break;
504         case 0x221e:
505             pC = " infinity ";
506             break;
507         case 0x2227:
508             pC = " and ";
509             break;
510         case 0x2228:
511             pC = " or ";
512             break;
513         case 0x2229:
514             pC = " intersection ";
515             break;
516         case 0x222a:
517             pC = " union ";
518             break;
519         case 0x222b:
520             pC = " int ";
521             break;
522         case 0x222c:
523             pC = " iint ";
524             break;
525         case 0x222d:
526             pC = " iiint ";
527             break;
528         case 0x222e:
529             pC = " lint ";
530             break;
531         case 0x222f:
532             pC = " llint ";
533             break;
534         case 0x2230:
535             pC = " lllint ";
536             break;
537         case 0x2245:
538             pC = " simeq ";
539             break;
540         case 0x2248:
541             pC = " approx ";
542             break;
543         case 0x2260:
544             pC = " <> ";
545             break;
546         case 0x2261:
547             pC = " equiv ";
548             break;
549         case 0x2264:
550             pC = " <= ";
551             break;
552         case 0x2265:
553             pC = " >= ";
554             break;
555         case 0x2282:
556             pC = " subset ";
557             break;
558         case 0x2283:
559             pC = " supset ";
560             break;
561         case 0x2284:
562             pC = " nsubset ";
563             break;
564         case 0x2285:
565             pC = " nsupset ";
566             break;
567         case 0x2286:
568             pC = " subseteq ";
569             break;
570         case 0x2287:
571             pC = " supseteq ";
572             break;
573         case 0x2288:
574             pC = " nsubseteq ";
575             break;
576         case 0x2289:
577             pC = " nsupseteq ";
578             break;
579         case 0x227a:
580         case 0x227b:
581         case 0x22b2:
582         case 0x22b3:
583             rRet += ' ';
584             rRet.Append(nChar);
585             rRet += ' ';
586             break;
587         case 0x22a5:
588             pC = " ortho ";
589             break;
590         case 0x22c5:
591             pC = " cdot ";
592             break;
593         case 0x22ee:
594             pC = " dotsvert ";
595             break;
596         case 0x22ef:
597             pC = " dotsaxis ";
598             break;
599         case 0x22f0:
600             pC = " dotsup ";
601             break;
602         case 0x22f1:
603             pC = " dotsdown ";
604             break;
605         case 0x2329:
606             pC = " langle ";
607             break;
608         case 0x232a:
609             pC = " rangle ";
610             break;
611         case 0x301a:
612             pC = " ldbracket ";
613             break;
614         case 0x301b:
615             pC = " rdbracket ";
616             break;
617         case 0xe083:
618             rRet.Append('+');
619             bRet=sal_True;
620             break;
621         case '^':
622         case 0xe091:
623             pC = " widehat ";
624             break;
625         case 0xe096:
626             pC = " widetilde ";
627             break;
628         case 0xe098:
629             pC = " widevec ";
630             break;
631         case 0xE421:
632             pC = " geslant ";
633             break;
634         case 0xE425:
635             pC = " leslant ";
636             break;
637         case 0xeb01:    //no space
638         case 0xeb08:    //normal space
639             bRet=sal_True;
640             break;
641         case 0xef04:    //tiny space
642         case 0xef05:    //tiny space
643         case 0xeb02:    //small space
644         case 0xeb04:    //medium space
645             rRet.Append('`');
646             break;
647         case 0xeb05:    //large space
648             rRet.Append('~');
649             break;
650         case 0x3a9:
651             pC = " %OMEGA ";
652             break;
653         default:
654             rRet.Append(nChar);
655             bRet=sal_True;
656             break;
657     }
658     if (pC)
659         rRet.AppendAscii(pC);
660     return bRet;
661 }
662 
AppendStyleToText(String & rRet)663 void MathTypeFont::AppendStyleToText(String &rRet)
664 {
665     const char *pC = NULL;
666     switch (nStyle)
667     {
668         default:
669         case 0:
670             break;
671         case 1:
672             pC = " ital ";
673             break;
674         case 2:
675             pC = " bold ";
676             break;
677         case 3:
678             pC = " bold italic";
679             break;
680     }
681     if (pC)
682         rRet.AppendAscii(pC);
683 }
684 
TypeFaceToString(String & rTxt,sal_uInt8 nFace)685 void MathType::TypeFaceToString(String &rTxt,sal_uInt8 nFace)
686 {
687     MathTypeFont aFont(nFace);
688     MathTypeFontSet::iterator aItr = aUserStyles.find(aFont);
689     if (aItr != aUserStyles.end())
690         aFont.nStyle = aItr->nStyle;
691     aFont.AppendStyleToText(rTxt);
692 }
693 
Parse(SotStorage * pStor)694 int MathType::Parse(SotStorage *pStor)
695 {
696     SvStorageStreamRef xSrc = pStor->OpenSotStream(
697         String::CreateFromAscii("Equation Native"),
698         STREAM_STD_READ | STREAM_NOCREATE);
699     if ( (!xSrc.Is()) || (SVSTREAM_OK != xSrc->GetError()))
700         return 0;
701     pS = &xSrc;
702     pS->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
703 
704     EQNOLEFILEHDR aHdr;
705     aHdr.Read(pS);
706     *pS >> nVersion;
707     *pS >> nPlatform;
708     *pS >> nProduct;
709     *pS >> nProdVersion;
710     *pS >> nProdSubVersion;
711 
712     if (nVersion > 3)   // allow only supported versions of MathType to be parsed
713         return 0;
714 
715 #ifdef STANDALONE
716     *pOut << "Format Version is " << int(nVersion) << endl;
717     *pOut << "Generating Platform is " << (nPlatform ? "Windows"
718         : "Mac") << endl;
719     *pOut << "Generating Product is " << (nPlatform ? "Equation Editor"
720         : "Equation Editor") << endl;
721     *pOut << "Prod Version is " << int(nProdVersion) << "." <<
722         int(nProdSubVersion) << endl << endl;
723 #endif
724 
725     int nRet = HandleRecords();
726     //little crude hack to close ocassionally open expressions
727     //a sophisticated system to determine what expressions are
728     //opened is required, but this is as much work as rewriting
729     //starmaths internals.
730     APPEND(rRet,"{}");
731 
732 #if OSL_DEBUG_LEVEL > 1
733 #   ifdef CAOLAN
734     //sanity check
735 
736     //sigh, theres no point! MathType (in some bizarre subvarient) pads
737     //the end of the formula with ENDs (0)'s
738     sal_uLong nEnd = pS->Tell();
739     DBG_ASSERT(nEnd == pS->Seek(STREAM_SEEK_TO_END),
740         "Possibly unfully parsed formula");
741 #   endif
742 #endif
743     return nRet;
744 }
745 
lcl_PrependDummyTerm(String & rRet,xub_StrLen & rTextStart)746 static void lcl_PrependDummyTerm(String &rRet, xub_StrLen &rTextStart)
747 {
748     if ((rRet.GetChar(rTextStart) == '=') &&
749         ((rTextStart == 0) ||
750         (rRet.GetChar(rTextStart-1) == '{'))
751        )
752     {
753         rRet.InsertAscii(" {}",rTextStart);
754         rTextStart+=3;
755     }
756 }
757 
lcl_AppendDummyTerm(String & rRet)758 static void lcl_AppendDummyTerm(String &rRet)
759 {
760     sal_Bool bOk=sal_False;
761     for(int nI=rRet.Len()-1;nI >= 0; nI--)
762     {
763         xub_StrLen nIdx = sal::static_int_cast< xub_StrLen >(nI);
764         sal_Unicode nChar = rRet.GetChar(nIdx);
765         if (nChar == ' ')
766             continue;
767         if (rRet.GetChar(nIdx) != '{')
768             bOk=sal_True;
769         break;
770     }
771     if (!bOk)   //No term, use dummy
772         APPEND(rRet," {}");
773 }
774 
HandleNudge()775 void MathType::HandleNudge()
776 {
777     sal_uInt8 nXNudge;
778     *pS >> nXNudge;
779     sal_uInt8 nYNudge;
780     *pS >> nYNudge;
781     if (nXNudge == 128 && nYNudge == 128)
782     {
783         sal_uInt16 nXLongNudge;
784         sal_uInt16 nYLongNudge;
785         *pS >> nXLongNudge;
786         *pS >> nYLongNudge;
787     }
788 }
789 /*Fabously complicated as many tokens have to be reordered and generally
790  *moved around from mathtypes paradigm to starmaths.*/
HandleRecords(int nLevel,sal_uInt8 nSelector,sal_uInt8 nVariation,int nMatrixRows,int nMatrixCols)791 int MathType::HandleRecords(int nLevel,sal_uInt8 nSelector,
792     sal_uInt8 nVariation, int nMatrixRows,int nMatrixCols)
793 {
794     sal_uInt8 nTag,nRecord;
795     sal_uInt8 nTabType,nTabStops;
796     sal_uInt16 nTabOffset;
797     sal_Char nChar8;
798     String sFontName;
799     int i,nRet=1,newline=0;
800     sal_Bool bSilent=sal_False;
801     int nPart=0;
802     String sPush,sMainTerm;
803     int nSetSize=0,nSetAlign=0;
804     int nCurRow=0,nCurCol=0;
805     sal_Bool bOpenString=sal_False;
806     xub_StrLen nTextStart = 0;
807     xub_StrLen nSubSupStartPos = 0;
808     xub_StrLen nLastTemplateBracket=STRING_NOTFOUND;
809 
810     do
811     {
812         *pS >> nTag;
813         nRecord = nTag&0x0F;
814 
815         /*MathType strings can of course include words which
816          *are StarMath keywords, the simplest solution is
817          to escape strings of greater than len 1 with double
818          quotes to avoid scanning the TokenTable for matches
819 
820          Unfortunately it may turn out that the string gets
821          split during the handling of a character emblishment
822          so this special case must be handled in the
823          character handler case 2:
824          */
825         if ((nRecord == CHAR) && (!bIsSilent) && (!bOpenString))
826         {
827             bOpenString=sal_True;
828             nTextStart = rRet.Len();
829         }
830         else if ((nRecord != CHAR) && (bOpenString))
831         {
832             bOpenString=sal_False;
833             if ((rRet.Len() - nTextStart) > 1)
834             {
835                 String aStr;
836                 TypeFaceToString(aStr,nTypeFace);
837                 aStr += '\"';
838                 rRet.Insert(aStr,nTextStart);
839                 rRet += '\"';
840             }
841             else
842             {
843                 if (nRecord == END)
844                 {
845                     sal_Unicode cChar = 0;
846                     xub_StrLen nI = rRet.Len()-1;
847                     while (nI && ((cChar = rRet.GetChar(nI)) == ' '))
848                         --nI;
849                     if ((cChar == '=') || (cChar == '+') || (cChar == '-'))
850                         APPEND(rRet,"{}");
851                 }
852             }
853         }
854 
855         switch(nRecord)
856         {
857             case LINE:
858                 {
859                     if (xfLMOVE(nTag))
860                         HandleNudge();
861                     //if (xfLSPACE(nTag))
862                     //if (xfRULER(nTag))
863 
864                     if (newline>0)
865                         APPEND(rRet,"\nnewline\n");
866                     if (!(xfNULL(nTag)))
867                     {
868                         switch (nSelector)
869                         {
870                         case 0x0:
871                             if (nVariation==0)
872                                 APPEND(rRet," langle ");
873                             else if (nVariation==1)
874                                 APPEND(rRet," \\langle ");
875                             break;
876                         case 0x1:
877                             if (nVariation==0)
878                                 APPEND(rRet," left (");
879                             else if (nVariation==1)
880                                 APPEND(rRet,"\\(");
881                             break;
882                         case 0x2:
883                             if ((nVariation==0) || (nVariation==1))
884                                 APPEND(rRet," left lbrace ");
885                             else
886                                 APPEND(rRet," left none ");
887                             break;
888                         case 0x3:
889                             if (nVariation==0)
890                                 APPEND(rRet," left [");
891                             else if (nVariation==1)
892                                 APPEND(rRet,"\\[");
893                             break;
894                         case 0x8:
895                         case 0xb:
896                             APPEND(rRet," \\[");
897                             break;
898                         case 0x4:
899                             if (nVariation==0)
900                                 APPEND(rRet," lline ");
901                             else if (nVariation==1)
902                                 APPEND(rRet," \\lline ");
903                             break;
904                         case 0x5:
905                             if (nVariation==0)
906                                 APPEND(rRet," ldline ");
907                             else if (nVariation==1)
908                                 APPEND(rRet," \\ldline ");
909                             break;
910                         case 0x6:
911                             if (nVariation == 0 || nVariation == 1)
912                                 APPEND(rRet," left lfloor ");
913                             else if (nVariation==1)
914                                 APPEND(rRet," left none ");
915                             break;
916                         case 0x7:
917                             if (nVariation==0)
918                                 APPEND(rRet," lceil ");
919                             else if (nVariation==1)
920                                 APPEND(rRet," \\lceil ");
921                             break;
922                         case 0x9:
923                         case 0xa:
924                             APPEND(rRet," \\]");
925                             break;
926                         case 0xc:
927                             APPEND(rRet," \\(");
928                             break;
929                         case 0xd:
930                             if (nPart == 0)
931                             {
932                                 if (nVariation == 0)
933                                     APPEND(rRet," sqrt");
934                                 else
935                                 {
936                                     APPEND(rRet," nroot");
937                                     sPush = rRet;
938                                     rRet.Erase();
939                                 }
940                             }
941                             APPEND(rRet," {");
942                             break;
943                         case 0xe:
944                             if (nPart == 0)
945                                 APPEND(rRet," { ");
946 
947 
948                             if (nPart == 1)
949                                 APPEND(rRet," over ");
950                             APPEND(rRet," {");
951                             break;
952                         case 0xf:
953                             nSubSupStartPos = rRet.Len();
954                             if ((nVariation == 0) ||
955                                     ((nVariation == 2) && (nPart==1)))
956                             {
957                                 lcl_AppendDummyTerm(rRet);
958                                 APPEND(rRet," rSup");
959                             }
960                             else if ((nVariation == 1) ||
961                                     ((nVariation == 2) && (nPart==0)))
962                             {
963                                 lcl_AppendDummyTerm(rRet);
964                                 APPEND(rRet," rSub");
965                             }
966                             APPEND(rRet," {");
967                             break;
968                         case 0x10:
969                             if (nVariation == 0)
970                                 APPEND(rRet," {underline ");
971                             else if (nVariation == 1)
972                                 APPEND(rRet," {underline underline ");
973                             APPEND(rRet," {");
974                             break;
975                         case 0x11:
976                             if (nVariation == 0)
977                                 APPEND(rRet," {overline ");
978                             else if (nVariation == 1)
979                                 APPEND(rRet," {overline overline ");
980                             APPEND(rRet," {");
981                             break;
982                         case 0x12:
983                             if (nPart == 0)
984                             {
985                                 if (nVariation == 0)
986                                     APPEND(rRet," widevec ");//left arrow above
987                                 else if (nVariation == 1)
988                                     APPEND(rRet," widevec ");//left arrow below
989                                 APPEND(rRet," {");
990                             }
991                             break;
992                         case 0x13:
993                             if (nPart == 0)
994                             {
995                                 if (nVariation == 0)
996                                     APPEND(rRet," widevec ");//right arrow above
997                                 else if (nVariation == 1)
998                                     APPEND(rRet," widevec ");//right arrow below
999                                 APPEND(rRet," {");
1000                             }
1001                             break;
1002                         case 0x14:
1003                             if (nPart == 0)
1004                             {
1005                                 if (nVariation == 0)
1006                                     APPEND(rRet," widevec ");//double arrow above
1007                                 else if (nVariation == 1)
1008                                     APPEND(rRet," widevec ");//double arrow below
1009                                 APPEND(rRet," {");
1010                             }
1011                             break;
1012                         case 0x15:
1013                             if (nPart == 0)
1014                             {
1015                                 if ((nVariation == 3) || (nVariation == 4))
1016                                     APPEND(rRet," lInt");
1017                                 else
1018                                     APPEND(rRet," Int");
1019                                 if ( (nVariation != 0) && (nVariation != 3))
1020                                 {
1021                                     sPush = rRet;
1022                                     rRet.Erase();
1023                                 }
1024                             }
1025                             if (((nVariation == 1) ||
1026                                     (nVariation == 4)) && (nPart==1))
1027                                 APPEND(rRet," rSub");
1028                             else if ((nVariation == 2) && (nPart==2))
1029                                 APPEND(rRet," rSup");
1030                             else if ((nVariation == 2) && (nPart==1))
1031                                 APPEND(rRet," rSub");
1032                             APPEND(rRet," {");
1033                             break;
1034                         case 0x16:
1035                             if (nPart == 0)
1036                             {
1037                                 if ((nVariation == 2) || (nVariation == 3))
1038                                     APPEND(rRet," llInt");
1039                                 else
1040                                     APPEND(rRet," iInt");
1041                                 if ( (nVariation != 0) && (nVariation != 2))
1042                                 {
1043                                     sPush = rRet;
1044                                     rRet.Erase();
1045                                 }
1046                             }
1047                             if (((nVariation == 1) ||
1048                                     (nVariation == 3)) && (nPart==1))
1049                                 APPEND(rRet," rSub");
1050                             APPEND(rRet," {");
1051                             break;
1052                         case 0x17:
1053                             if (nPart == 0)
1054                             {
1055                                 if ((nVariation == 2) || (nVariation == 3))
1056                                     APPEND(rRet," lllInt");
1057                                 else
1058                                     APPEND(rRet," iiInt");
1059                                 if ( (nVariation != 0) && (nVariation != 2))
1060                                 {
1061                                     sPush = rRet;
1062                                     rRet.Erase();
1063                                 }
1064                             }
1065                             if (((nVariation == 1) ||
1066                                     (nVariation == 3)) && (nPart==1))
1067                                 APPEND(rRet," rSub");
1068                             APPEND(rRet," {");
1069                             break;
1070                         case 0x18:
1071                             if (nPart == 0)
1072                             {
1073                                 if (nVariation == 2)
1074                                     APPEND(rRet," lInt");
1075                                 else
1076                                     APPEND(rRet," Int");
1077                                 sPush = rRet;
1078                                 rRet.Erase();
1079                             }
1080                             if (((nVariation == 1) ||
1081                                     (nVariation == 2)) && (nPart==1))
1082                                 APPEND(rRet," cSub");
1083                             else if ((nVariation == 0) && (nPart==2))
1084                                 APPEND(rRet," cSup");
1085                             else if ((nVariation == 0) && (nPart==1))
1086                                 APPEND(rRet," cSub");
1087                             APPEND(rRet," {");
1088                             break;
1089                         case 0x19:
1090                             if (nPart == 0)
1091                             {
1092                                 if (nVariation == 0)
1093                                     APPEND(rRet," llInt");
1094                                 else
1095                                     APPEND(rRet," iInt");
1096                                 sPush = rRet;
1097                                 rRet.Erase();
1098                             }
1099                             if (nPart==1)
1100                                 APPEND(rRet," cSub");
1101                             APPEND(rRet," {");
1102                             break;
1103                         case 0x1a:
1104                             if (nPart == 0)
1105                             {
1106                                 if (nVariation == 0)
1107                                     APPEND(rRet," lllInt");
1108                                 else
1109                                     APPEND(rRet," iiInt");
1110                                 sPush = rRet;
1111                                 rRet.Erase();
1112                             }
1113                             if (nPart==1)
1114                                 APPEND(rRet," cSub");
1115                             APPEND(rRet," {");
1116                             break;
1117                         case 0x1b:
1118                         case 0x1c:
1119                             APPEND(rRet," {");
1120                             break;
1121                         case 0x1d:
1122                             if (nPart == 0)
1123                             {
1124                                 APPEND(rRet," Sum");
1125                                 if (nVariation != 2)
1126                                 {
1127                                     sPush = rRet;
1128                                     rRet.Erase();
1129                                 }
1130                             }
1131                             if ((nVariation == 0) && (nPart==1))
1132                                 APPEND(rRet," cSub");
1133                             else if ((nVariation == 1) && (nPart==2))
1134                                 APPEND(rRet," cSup");
1135                             else if ((nVariation == 1) && (nPart==1))
1136                                 APPEND(rRet," cSub");
1137                             APPEND(rRet," {");
1138                             break;
1139                         case 0x1e:
1140                             if (nPart == 0)
1141                             {
1142                                 APPEND(rRet," Sum");
1143                                 sPush = rRet;
1144                                 rRet.Erase();
1145                             }
1146                             if ((nVariation == 0) && (nPart==1))
1147                                 APPEND(rRet," rSub");
1148                             else if ((nVariation == 1) && (nPart==2))
1149                                 APPEND(rRet," rSup");
1150                             else if ((nVariation == 1) && (nPart==1))
1151                                 APPEND(rRet," rSub");
1152                             APPEND(rRet," {");
1153                             break;
1154                         case 0x1f:
1155                             if (nPart == 0)
1156                             {
1157                                 APPEND(rRet," Prod");
1158                                 if (nVariation != 2)
1159                                 {
1160                                     sPush = rRet;
1161                                     rRet.Erase();
1162                                 }
1163                             }
1164                             if ((nVariation == 0) && (nPart==1))
1165                                 APPEND(rRet," cSub");
1166                             else if ((nVariation == 1) && (nPart==2))
1167                                 APPEND(rRet," cSup");
1168                             else if ((nVariation == 1) && (nPart==1))
1169                                 APPEND(rRet," cSub");
1170                             APPEND(rRet," {");
1171                             break;
1172                         case 0x20:
1173                             if (nPart == 0)
1174                             {
1175                                 APPEND(rRet," Prod");
1176                                 sPush = rRet;
1177                                 rRet.Erase();
1178                             }
1179                             if ((nVariation == 0) && (nPart==1))
1180                                 APPEND(rRet," rSub");
1181                             else if ((nVariation == 1) && (nPart==2))
1182                                 APPEND(rRet," rSup");
1183                             else if ((nVariation == 1) && (nPart==1))
1184                                 APPEND(rRet," rSub");
1185                             APPEND(rRet," {");
1186                             break;
1187                         case 0x21:
1188                             if (nPart == 0)
1189                             {
1190                                 APPEND(rRet," coProd");
1191                                 if (nVariation != 2)
1192                                 {
1193                                     sPush = rRet;
1194                                     rRet.Erase();
1195                                 }
1196                             }
1197                             if ((nVariation == 0) && (nPart==1))
1198                                 APPEND(rRet," cSub");
1199                             else if ((nVariation == 1) && (nPart==2))
1200                                 APPEND(rRet," cSup");
1201                             else if ((nVariation == 1) && (nPart==1))
1202                                 APPEND(rRet," cSub");
1203                             APPEND(rRet," {");
1204                             break;
1205                         case 0x22:
1206                             if (nPart == 0)
1207                             {
1208                                 APPEND(rRet," coProd");
1209                                 sPush = rRet;
1210                                 rRet.Erase();
1211                             }
1212                             if ((nVariation == 0) && (nPart==1))
1213                                 APPEND(rRet," rSub");
1214                             else if ((nVariation == 1) && (nPart==2))
1215                                 APPEND(rRet," rSup");
1216                             else if ((nVariation == 1) && (nPart==1))
1217                                 APPEND(rRet," rSub");
1218                             APPEND(rRet," {");
1219                             break;
1220                         case 0x23:
1221                             if (nPart == 0)
1222                             {
1223                                 APPEND(rRet," union"); //union
1224                                 if (nVariation != 2)
1225                                 {
1226                                     sPush = rRet;
1227                                     rRet.Erase();
1228                                 }
1229                             }
1230                             if ((nVariation == 0) && (nPart==1))
1231                                 APPEND(rRet," cSub");
1232                             else if ((nVariation == 1) && (nPart==2))
1233                                 APPEND(rRet," cSup");
1234                             else if ((nVariation == 1) && (nPart==1))
1235                                 APPEND(rRet," cSub");
1236                             APPEND(rRet," {");
1237                             break;
1238                         case 0x24:
1239                             if (nPart == 0)
1240                             {
1241                                 APPEND(rRet," union"); //union
1242                                 sPush = rRet;
1243                                 rRet.Erase();
1244                             }
1245                             if ((nVariation == 0) && (nPart==1))
1246                                 APPEND(rRet," rSub");
1247                             else if ((nVariation == 1) && (nPart==2))
1248                                 APPEND(rRet," rSup");
1249                             else if ((nVariation == 1) && (nPart==1))
1250                                 APPEND(rRet," rSub");
1251                             APPEND(rRet," {");
1252                             break;
1253                         case 0x25:
1254                             if (nPart == 0)
1255                             {
1256                                 APPEND(rRet," intersect"); //intersect
1257                                 if (nVariation != 2)
1258                                 {
1259                                     sPush = rRet;
1260                                     rRet.Erase();
1261                                 }
1262                             }
1263                             if ((nVariation == 0) && (nPart==1))
1264                                 APPEND(rRet," cSub");
1265                             else if ((nVariation == 1) && (nPart==2))
1266                                 APPEND(rRet," cSup");
1267                             else if ((nVariation == 1) && (nPart==1))
1268                                 APPEND(rRet," cSub");
1269                             APPEND(rRet," {");
1270                             break;
1271                         case 0x26:
1272                             if (nPart == 0)
1273                             {
1274                                 APPEND(rRet," intersect"); //intersect
1275                                 sPush = rRet;
1276                                 rRet.Erase();
1277                             }
1278                             if ((nVariation == 0) && (nPart==1))
1279                                 APPEND(rRet," rSub");
1280                             else if ((nVariation == 1) && (nPart==2))
1281                                 APPEND(rRet," rSup");
1282                             else if ((nVariation == 1) && (nPart==1))
1283                                 APPEND(rRet," rSub");
1284                             APPEND(rRet," {");
1285                             break;
1286                         case 0x27:
1287                             if ((nVariation == 0) && (nPart==1))
1288                                 APPEND(rRet," cSup");
1289                             else if ((nVariation == 1) && (nPart==1))
1290                                 APPEND(rRet," cSub");
1291                             else if ((nVariation == 2) && (nPart==1))
1292                                 APPEND(rRet," cSub");
1293                             else if ((nVariation == 2) && (nPart==2))
1294                                 APPEND(rRet," cSup");
1295                             APPEND(rRet," {");
1296                             break;
1297                         case 0x28:
1298                             if (nVariation == 0)
1299                             {
1300                                 if (nPart == 0)
1301                                 {
1302                                     sPush = rRet;
1303                                     rRet.Erase();
1304                                 }
1305                             }
1306                             APPEND(rRet," {");
1307                             if (nVariation == 0)
1308                             {
1309                                 if (nPart == 1)
1310                                     APPEND(rRet,"alignr ");
1311                             }
1312                             if (nPart == 0)
1313                                 APPEND(rRet,"\\lline ");
1314                             if (nVariation == 1)
1315                                 APPEND(rRet,"overline ");
1316                             break;
1317                         case 0x29:
1318                             APPEND(rRet," {");
1319                             break;
1320                         case 0x2a:
1321                             if (nPart == 0)
1322                             {
1323                                 sPush = rRet;
1324                                 rRet.Erase();
1325                             }
1326                             if ((nVariation == 0) && (nPart==0))
1327                                 APPEND(rRet," rSup");
1328                             else if ((nVariation == 2) && (nPart==1))
1329                                 APPEND(rRet," rSup");
1330                             else if ((nVariation == 1) && (nPart==0))
1331                                 APPEND(rRet," rSub");
1332                             else if ((nVariation == 2) && (nPart==0))
1333                                 APPEND(rRet," rSub");
1334                             APPEND(rRet," {");
1335                             break;
1336                         case 0x2b:
1337                             if (nPart == 0)
1338                             {
1339                                 sPush = rRet;
1340                                 rRet.Erase();
1341                             }
1342                             if ((nVariation == 0) && (nPart==0))
1343                                 APPEND(rRet," cSup");
1344                             else if ((nVariation == 2) && (nPart==1))
1345                                 APPEND(rRet," cSup");
1346                             else if ((nVariation == 1) && (nPart==0))
1347                                 APPEND(rRet," cSub");
1348                             else if ((nVariation == 2) && (nPart==0))
1349                                 APPEND(rRet," cSub");
1350                             APPEND(rRet," {");
1351                             break;
1352                         case 0x2c:
1353                             if (nPart == 0)
1354                                 APPEND(rRet,"\"\"");
1355                             if ((nVariation == 0)
1356                                     || ((nVariation == 2) && (nPart==1)))
1357                                 APPEND(rRet," lSup");
1358                             else if ((nVariation == 1)
1359                                     || ((nVariation == 2) && (nPart==0)))
1360                                 APPEND(rRet," lSub");
1361                             APPEND(rRet," {");
1362                             break;
1363                         case 0x2d:
1364                             if (nVariation==0)
1365                             {
1366                                 if (nPart == 0)
1367                                     APPEND(rRet," langle ");
1368                             }
1369                             else if (nVariation==1)
1370                             {
1371                                 APPEND(rRet," \\langle ");
1372                                 newline--;
1373                             }
1374                             else if (nVariation==2)
1375                             {
1376                                 APPEND(rRet," \\lline ");
1377                                 newline--;
1378                             }
1379                             break;
1380                         case 0x2e:
1381                             if (nVariation == 0)
1382                                 APPEND(rRet," widevec ");//left below
1383                             else if (nVariation == 1)
1384                                 APPEND(rRet," widevec ");//right below
1385                             else if (nVariation == 2)
1386                                 APPEND(rRet," widevec ");//double headed below
1387                             APPEND(rRet," {");
1388                             break;
1389                         case 0x2f:
1390                             if (nVariation == 0)
1391                                 APPEND(rRet," widevec ");//left above
1392                             else if (nVariation == 1)
1393                                 APPEND(rRet," widevec ");//right above
1394                             else if (nVariation == 2)
1395                                 APPEND(rRet," widevec ");//double headed above
1396                             APPEND(rRet," {");
1397                             break;
1398                         default:
1399                             break;
1400                         }
1401                         sal_Int16 nOldCurSize=nCurSize;
1402                         xub_StrLen nSizeStartPos = rRet.Len();
1403                         HandleSize(nLSize,nDSize,nSetSize);
1404                         nRet = HandleRecords(nLevel+1);
1405                         while (nSetSize)
1406                         {
1407                             sal_Bool bOk=sal_False;
1408                             xub_StrLen nI = rRet.SearchBackward('{');
1409                             if (nI != STRING_NOTFOUND)
1410                             {
1411                                 for(nI=nI+1;nI<rRet.Len();nI++)
1412                                     if (rRet.GetChar(nI) != ' ')
1413                                     {
1414                                         bOk=sal_True;
1415                                         break;
1416                                     }
1417                             }
1418                             else
1419                                 bOk=sal_True;
1420 
1421                             if (bOk)
1422                                 APPEND(rRet,"} ");
1423                             else
1424                                 rRet.Erase(nSizeStartPos);
1425                             nSetSize--;
1426                             nCurSize=nOldCurSize;
1427                         }
1428 
1429 
1430                         HandleMatrixSeperator(nMatrixRows,nMatrixCols,
1431                             nCurCol,nCurRow);
1432 
1433                         switch (nSelector)
1434                         {
1435                         case 0x0:
1436                             if (nVariation==0)
1437                                 APPEND(rRet," rangle ");
1438                             else if (nVariation==2)
1439                                 APPEND(rRet," \\rangle ");
1440                             break;
1441                         case 0x1:
1442                             if (nVariation==0)
1443                                 APPEND(rRet," right )");
1444                             else if (nVariation==2)
1445                                 APPEND(rRet,"\\)");
1446                             break;
1447                         case 0x2:
1448                             if ((nVariation==0) || (nVariation==2))
1449                                 APPEND(rRet," right rbrace ");
1450                             else
1451                                 APPEND(rRet," right none ");
1452                             break;
1453                         case 0x3:
1454                             if (nVariation==0)
1455                                 APPEND(rRet," right ]");
1456                             else if (nVariation==2)
1457                                 APPEND(rRet,"\\]");
1458                             break;
1459                         case 0x4:
1460                             if (nVariation==0)
1461                                 APPEND(rRet," rline ");
1462                             else if (nVariation==2)
1463                                 APPEND(rRet," \\rline ");
1464                             break;
1465                         case 0x5:
1466                             if (nVariation==0)
1467                                 APPEND(rRet," rdline ");
1468                             else if (nVariation==2)
1469                                 APPEND(rRet," \\rdline ");
1470                             break;
1471                         case 0x6:
1472                             if (nVariation == 0 || nVariation == 2)
1473                                 APPEND(rRet," right rfloor ");
1474                             else if (nVariation==2)
1475                                 APPEND(rRet," right none ");
1476                             break;
1477                         case 0x7:
1478                             if (nVariation==0)
1479                                 APPEND(rRet," rceil ");
1480                             else if (nVariation==2)
1481                                 APPEND(rRet," \\rceil ");
1482                             break;
1483                         case 0x8:
1484                         case 0xa:
1485                             APPEND(rRet,"\\[");
1486                             break;
1487                         case 0x9:
1488                         case 0xc:
1489                             APPEND(rRet,"\\]");
1490                             break;
1491                         case 0xd:
1492                             APPEND(rRet,"} ");
1493                             if (nVariation == 1)
1494                             {
1495                                 if (nPart == 0)
1496                                 {
1497                                     newline--;
1498                                     sMainTerm = rRet;
1499                                     rRet.Erase();
1500                                 }
1501                                 else
1502                                 {
1503                                     sPush += rRet;
1504                                     rRet = sPush;
1505                                     rRet += sMainTerm;
1506                                 }
1507                             }
1508                             else
1509                             {
1510                                 if (nPart == 0)
1511                                     newline--;
1512                             }
1513                             nPart++;
1514                             break;
1515                         case 0xb:
1516                             APPEND(rRet,"\\)");
1517                             break;
1518                         case 0xe:
1519                             APPEND(rRet,"} ");
1520                             if (nPart == 0)
1521                                 newline--;
1522                             else
1523                                 APPEND(rRet,"} ");
1524                             nPart++;
1525                             break;
1526                         case 0xf:
1527                             {
1528                             if ((nPart == 0) &&
1529                                     ((nVariation == 2) || (nVariation == 1)))
1530                                 newline--;
1531 
1532                             sal_Bool bOk=sal_False;
1533                             xub_StrLen nI = rRet.SearchBackward('{');
1534                             if (nI != STRING_NOTFOUND)
1535                             {
1536                                 for(nI=nI+1;nI<rRet.Len();nI++)
1537                                     if (rRet.GetChar(nI) != ' ')
1538                                     {
1539                                         bOk=sal_True;
1540                                         break;
1541                                     }
1542                             }
1543                             else
1544                                 bOk=sal_True;
1545 
1546                             if (bOk)
1547                                 APPEND(rRet,"} ");
1548                             else
1549                                 rRet.Erase(nSubSupStartPos);
1550                             nPart++;
1551                             }
1552                             break;
1553                         case 0x2c:
1554                             if ((nPart == 0) &&
1555                                     ((nVariation == 2) || (nVariation == 1)))
1556                                 newline--;
1557                             APPEND(rRet,"} ");
1558                             nPart++;
1559                             break;
1560                         case 0x2e:
1561                         case 0x2f:
1562                             APPEND(rRet,"} ");
1563                             break;
1564                         case 0x10:
1565                         case 0x11:
1566                             APPEND(rRet,"}} ");
1567                             break;
1568                         case 0x12:
1569                         case 0x13:
1570                         case 0x14:
1571                             if (nPart == 0)
1572                             {
1573                                 newline--;
1574                                 APPEND(rRet,"} ");
1575                             }
1576                             nPart++;
1577                             break;
1578                         case 0x1b:
1579                             APPEND(rRet,"} ");
1580                             if (nPart == 0)
1581                             {
1582                                 newline--;
1583                                 APPEND(rRet,"overbrace");
1584                             }
1585                             nPart++;
1586                             break;
1587                         case 0x1c:
1588                             APPEND(rRet,"} ");
1589                             if (nPart == 0)
1590                             {
1591                                 newline--;
1592                                 APPEND(rRet,"underbrace");
1593                             }
1594                             nPart++;
1595                             break;
1596                         case 0x27:
1597                             if (nPart==0)
1598                                 newline--;
1599                             else if ((nPart==1) &&
1600                                     ((nVariation == 2) || (nVariation == 1)))
1601                                 newline--;
1602                             APPEND(rRet,"} ");
1603                             nPart++;
1604                             break;
1605                         case 0x28:
1606                             APPEND(rRet,"} ");
1607                             if (nVariation == 0)
1608                             {
1609                                 if (nPart == 0)
1610                                 {
1611                                     sMainTerm = rRet;
1612                                     rRet.Erase();
1613                                 }
1614                                 else
1615                                 {
1616                                     sPush += rRet;
1617                                     rRet = sPush;
1618                                     APPEND(rRet," over ");
1619                                     rRet += sMainTerm;
1620                                 }
1621                             }
1622                             if (nPart == 0)
1623                                 newline--;
1624                             nPart++;
1625                             break;
1626                         case 0x29:
1627                             APPEND(rRet,"} ");
1628                             if (nPart == 0)
1629                             {
1630                                 newline--;
1631                                 switch (nVariation)
1632                                 {
1633                                 case 1:
1634                                     APPEND(rRet,"slash");
1635                                     break;
1636                                 default:
1637                                     APPEND(rRet,"wideslash");
1638                                     break;
1639                                 }
1640                             }
1641                             nPart++;
1642                             break;
1643                         case 0x1d:
1644                         case 0x1e:
1645                         case 0x1f:
1646                         case 0x20:
1647                         case 0x21:
1648                         case 0x22:
1649                         case 0x23:
1650                         case 0x24:
1651                         case 0x25:
1652                         case 0x26:
1653                             APPEND(rRet,"} ");
1654                             if (nPart == 0)
1655                             {
1656                                 if (nVariation != 2)
1657                                 {
1658                                     sMainTerm = rRet;
1659                                     rRet.Erase();
1660                                 }
1661                                 newline--;
1662                             }
1663                             else if ((nPart == 1) && (nVariation == 0))
1664                             {
1665                                 sPush += rRet;
1666                                 rRet = sPush;
1667                                 rRet += sMainTerm;
1668                                 newline--;
1669                             }
1670                             else if ((nPart == 1) && (nVariation == 1))
1671                                 newline--;
1672                             else if ((nPart == 2) && (nVariation == 1))
1673                             {
1674                                 sPush += rRet;
1675                                 rRet = sPush;
1676                                 rRet += sMainTerm;
1677                                 newline--;
1678                             }
1679                             nPart++;
1680                             break;
1681                         case 0x15:
1682                             APPEND(rRet,"} ");
1683                             if (nPart == 0)
1684                             {
1685                                 if ((nVariation != 0) && (nVariation != 3))
1686                                 {
1687                                     sMainTerm = rRet;
1688                                     rRet.Erase();
1689                                 }
1690                                 newline--;
1691                             }
1692                             else if ((nPart == 1) &&
1693                                     ((nVariation == 1) || (nVariation==4)))
1694                             {
1695                                 sPush += rRet;
1696                                 rRet = sPush;
1697                                 rRet += sMainTerm;
1698                                 newline--;
1699                             }
1700                             else if ((nPart == 1) && (nVariation == 2))
1701                                 newline--;
1702                             else if ((nPart == 2) && (nVariation == 2))
1703                             {
1704                                 sPush += rRet;
1705                                 rRet = sPush;
1706                                 rRet += sMainTerm;
1707                                 newline--;
1708                             }
1709                             nPart++;
1710                             break;
1711                         case 0x16:
1712                         case 0x17:
1713                             APPEND(rRet,"} ");
1714                             if (nPart == 0)
1715                             {
1716                                 if ((nVariation != 0) && (nVariation != 2))
1717                                 {
1718                                     sMainTerm = rRet;
1719                                     rRet.Erase();
1720                                 }
1721                                 newline--;
1722                             }
1723                             else if ((nPart == 1) &&
1724                                     ((nVariation == 1) || (nVariation==3)))
1725                             {
1726                                 sPush += rRet;
1727                                 rRet = sPush;
1728                                 rRet += sMainTerm;
1729                                 newline--;
1730                             }
1731                             nPart++;
1732                             break;
1733                         case 0x18:
1734                             APPEND(rRet,"} ");
1735                             if (nPart == 0)
1736                             {
1737                                 sMainTerm = rRet;
1738                                 rRet.Erase();
1739                                 newline--;
1740                             }
1741                             else if ((nPart == 1) &&
1742                                     ((nVariation == 1) || (nVariation==2)))
1743                             {
1744                                 sPush += rRet;
1745                                 rRet = sPush;
1746                                 rRet += sMainTerm;
1747                                 newline--;
1748                             }
1749                             else if ((nPart == 1) && (nVariation == 0))
1750                                 newline--;
1751                             else if ((nPart == 2) && (nVariation == 0))
1752                             {
1753                                 sPush += rRet;
1754                                 rRet = sPush;
1755                                 rRet += sMainTerm;
1756                                 newline--;
1757                             }
1758                             nPart++;
1759                             break;
1760                         case 0x19:
1761                         case 0x1a:
1762                             APPEND(rRet,"} ");
1763                             if (nPart == 0)
1764                             {
1765                                 sMainTerm = rRet;
1766                                 rRet.Erase();
1767                                 newline--;
1768                             }
1769                             else if (nPart == 1)
1770                             {
1771                                 sPush += rRet;
1772                                 rRet = sPush;
1773                                 rRet += sMainTerm;
1774                                 newline--;
1775                             }
1776                             nPart++;
1777                             break;
1778                         case 0x2a:
1779                         case 0x2b:
1780                             APPEND(rRet,"} ");
1781 
1782                             if ((nPart == 0) &&
1783                                     ((nVariation == 0) || (nVariation == 1)))
1784                             {
1785                                 sMainTerm = rRet;
1786                                 rRet.Erase();
1787                                 newline--;
1788                             }
1789                             else if ((nPart == 0) && (nVariation == 2))
1790                                 newline--;
1791                             else if ((nPart == 1) && (nVariation == 2))
1792                             {
1793                                 sMainTerm = rRet;
1794                                 rRet.Erase();
1795                                 newline--;
1796                             }
1797                             else if ((nPart == 2) || ((((nPart == 1) &&
1798                                     (nVariation == 0)) || (nVariation == 1))))
1799                             {
1800                                 sPush+=rRet;
1801                                 rRet = sPush;
1802                                 rRet += sMainTerm;
1803                             }
1804                             nPart++;
1805                             break;
1806                         case 0x2d:
1807                             if (nVariation==0)
1808                             {
1809                                 if (nPart == 0)
1810                                 {
1811                                     newline--; //there is another term to arrive
1812                                     APPEND(rRet," mline ");
1813                                 }
1814                                 else
1815                                     APPEND(rRet," rangle ");
1816                             }
1817                             else if (nVariation==1)
1818                                 APPEND(rRet," \\lline ");
1819                             else if (nVariation==2)
1820                                 APPEND(rRet," \\rangle ");
1821                             nPart++;
1822                             break;
1823                         default:
1824                             break;
1825                         }
1826                         bSilent = sal_True; //Skip the optional brackets and/or
1827                                         //symbols that follow some of these
1828                                         //records. Foo Data.
1829 
1830                         /*In matrices and piles we cannot seperate equation
1831                          *lines with the newline keyword*/
1832                         if (nMatrixCols==0)
1833                             newline++;
1834                     }
1835                 }
1836                 break;
1837             case CHAR:
1838                 if (xfLMOVE(nTag))
1839                     HandleNudge();
1840                 nRet = HandleChar(nTextStart,nSetSize,nLevel,nTag,nSelector,
1841                     nVariation,bSilent);
1842                 break;
1843             case TMPL:
1844                 if (xfLMOVE(nTag))
1845                     HandleNudge();
1846                 nRet = HandleTemplate(nLevel,nSelector,nVariation,
1847                     nLastTemplateBracket);
1848                 break;
1849             case PILE:
1850                 if (xfLMOVE(nTag))
1851                     HandleNudge();
1852                 nRet = HandlePile(nSetAlign,nLevel,nSelector,nVariation);
1853                 HandleMatrixSeperator(nMatrixRows,nMatrixCols,nCurCol,nCurRow);
1854                 break;
1855             case MATRIX:
1856                 if (xfLMOVE(nTag))
1857                     HandleNudge();
1858                 nRet = HandleMatrix(nLevel,nSelector,nVariation);
1859                 HandleMatrixSeperator(nMatrixRows,nMatrixCols,nCurCol,nCurRow);
1860                 break;
1861             case EMBEL:
1862                 if (xfLMOVE(nTag))
1863                     HandleNudge();
1864                 HandleEmblishments();
1865                 break;
1866             case RULER:
1867                 *pS >> nTabStops;
1868                 for (i=0;i<nTabStops;i++)
1869                 {
1870                     *pS >> nTabType;
1871                     *pS >> nTabOffset;
1872                 }
1873                 DBG_ASSERT(sal_False,"Not seen in the wild Equation Ruler Field");
1874                 break;
1875             case FONT:
1876                 {
1877                     MathTypeFont aFont;
1878                     *pS >> aFont.nTface;
1879                     /*
1880                     The typeface number is the negative (which makes it
1881                     positive) of the typeface value (unbiased) that appears in
1882                     CHAR records that might follow a given FONT record
1883                     */
1884                     aFont.nTface = 128-aFont.nTface;
1885                     *pS >> aFont.nStyle;
1886                     aUserStyles.insert(aFont);
1887                     sFontName.Erase();
1888                     do
1889                     {
1890                         *pS >> nChar8;
1891                         sFontName.Append(ByteString::ConvertToUnicode(
1892                             nChar8,RTL_TEXTENCODING_MS_1252));
1893                     }
1894                     while(nChar8);
1895                 }
1896                 break;
1897             case SIZE:
1898                 HandleSetSize();
1899                 break;
1900             case 10:
1901             case 11:
1902             case 12:
1903             case 13:
1904             case 14:
1905                 nLSize=nRecord-10;
1906                 break;
1907             case END:
1908             default:
1909                 break;
1910         }
1911     }
1912     while (nRecord != END && !pS->IsEof());
1913     while (nSetSize)
1914     {
1915         rRet += '}';
1916         nSetSize--;
1917     }
1918     return nRet;
1919 }
1920 
1921 /*Simply determine if we are at the end of a record or the end of a line,
1922  *with fiddley logic to see if we are in a matrix or a pile or neither
1923 
1924  Note we cannot tell until after the event that this is the last entry
1925  of a pile, so we must strip the last seperator of a pile after this
1926  is detected in the PILE handler
1927  */
HandleMatrixSeperator(int nMatrixRows,int nMatrixCols,int & rCurCol,int & rCurRow)1928 void MathType::HandleMatrixSeperator(int nMatrixRows,int nMatrixCols,
1929     int &rCurCol,int &rCurRow)
1930 {
1931     if (nMatrixRows!=0)
1932     {
1933         if (rCurCol == nMatrixCols-1)
1934         {
1935             if (rCurRow != nMatrixRows-1)
1936                 APPEND(rRet," {} ##\n");
1937             if (nMatrixRows!=-1)
1938             {
1939                 rCurCol=0;
1940                 rCurRow++;
1941             }
1942         }
1943         else
1944         {
1945             APPEND(rRet," {} # ");
1946             if (nMatrixRows!=-1)
1947                 rCurCol++;
1948             else
1949                 rRet += '\n';
1950         }
1951     }
1952 }
1953 
1954 /* set the alignment of the following term, but starmath currently
1955  * cannot handle vertical alignment */
HandleAlign(sal_uInt8 nHorAlign,sal_uInt8,int & rSetAlign)1956 void MathType::HandleAlign(sal_uInt8 nHorAlign, sal_uInt8 /*nVAlign*/, int &rSetAlign)
1957 {
1958     switch(nHorAlign)
1959     {
1960     case 1:
1961     default:
1962         APPEND(rRet,"alignl {");
1963         break;
1964     case 2:
1965         APPEND(rRet,"alignc {");
1966         break;
1967     case 3:
1968         APPEND(rRet,"alignr {");
1969         break;
1970     }
1971 #if 0
1972     switch(nVAlign)
1973     {
1974     }
1975     rSetAlign+=2;
1976 #endif
1977     rSetAlign++;
1978 }
1979 
1980 /* set size of text, complexity due to overuse of signedness as a flag
1981  * indicator by mathtype file format*/
HandleSize(sal_Int16 nLstSize,sal_Int16 nDefSize,int & rSetSize)1982 sal_Bool MathType::HandleSize(sal_Int16 nLstSize,sal_Int16 nDefSize, int &rSetSize)
1983 {
1984     sal_Bool bRet=sal_False;
1985     if (nLstSize < 0)
1986     {
1987         if ((-nLstSize/32 != nDefaultSize) && (-nLstSize/32 != nCurSize))
1988         {
1989             if (rSetSize)
1990             {
1991                 rSetSize--;
1992                 rRet += '}';
1993                 bRet=sal_True;
1994             }
1995             if (-nLstSize/32 != nLastSize)
1996             {
1997                 nLastSize = nCurSize;
1998                 APPEND(rRet," size ");
1999                 rRet += String::CreateFromInt32(-nLstSize/32);
2000                 rRet += '{';
2001                 bRet=sal_True;
2002                 rSetSize++;
2003             }
2004             nCurSize = -nLstSize/32;
2005         }
2006     }
2007     else
2008     {
2009         /*sizetable should theoreticaly be filled with the default sizes
2010          *of the various font groupings matching starmaths equivalents
2011          in aTypeFaces, and a test would be done to see if the new font
2012          size would be the same as what starmath would have chosen for
2013          itself anyway in which case the size setting could be ignored*/
2014         nLstSize = aSizeTable[nLstSize];
2015         nLstSize = nLstSize + nDefSize;
2016         //if (nLstSize != nDefaultSize)
2017         if (nLstSize != nCurSize)
2018         {
2019             if (rSetSize)
2020             {
2021                 rSetSize--;
2022                 rRet += '}';
2023                 bRet=sal_True;
2024             }
2025             if (nLstSize != nLastSize)
2026             {
2027                 nLastSize = nCurSize;
2028                 APPEND(rRet," size ");
2029                 rRet += String::CreateFromInt32(nLstSize);
2030                 rRet += '{';
2031                 bRet=sal_True;
2032                 rSetSize++;
2033             }
2034             nCurSize = nLstSize;
2035         }
2036     }
2037     return bRet;
2038 }
2039 
ConvertFromStarMath(SfxMedium & rMedium)2040 int MathType::ConvertFromStarMath( SfxMedium& rMedium )
2041 {
2042     if (!pTree)
2043         return 0;
2044 
2045     SvStream *pStream = rMedium.GetOutStream();
2046     if ( pStream )
2047     {
2048         SvStorageRef pStor = new SotStorage( pStream, sal_False );
2049 
2050         SvGlobalName aGName(0x0002ce02L, 0x0000, 0x0000,0xc0,0x00,
2051             0x00,0x00,0x00,0x00,0x00,0x46 );
2052         pStor->SetClass( aGName, 0, C2S("Microsoft Equation 3.0"));
2053 
2054         static sal_uInt8 __READONLY_DATA aCompObj[] = {
2055             0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
2056             0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0xCE, 0x02, 0x00,
2057             0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
2058             0x00, 0x00, 0x00, 0x46, 0x17, 0x00, 0x00, 0x00,
2059             0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
2060             0x74, 0x20, 0x45, 0x71, 0x75, 0x61, 0x74, 0x69,
2061             0x6F, 0x6E, 0x20, 0x33, 0x2E, 0x30, 0x00, 0x0C,
2062             0x00, 0x00, 0x00, 0x44, 0x53, 0x20, 0x45, 0x71,
2063             0x75, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x0B,
2064             0x00, 0x00, 0x00, 0x45, 0x71, 0x75, 0x61, 0x74,
2065             0x69, 0x6F, 0x6E, 0x2E, 0x33, 0x00, 0xF4, 0x39,
2066             0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2067             0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2068         };
2069         SvStorageStreamRef xStor( pStor->OpenSotStream( C2S("\1CompObj")));
2070         xStor->Write(aCompObj,sizeof(aCompObj));
2071 
2072         static sal_uInt8 __READONLY_DATA aOle[] = {
2073             0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
2074             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2075             0x00, 0x00, 0x00, 0x00
2076             };
2077         SvStorageStreamRef xStor2( pStor->OpenSotStream( C2S("\1Ole")));
2078         xStor2->Write(aOle,sizeof(aOle));
2079         xStor.Clear();
2080         xStor2.Clear();
2081 
2082         SvStorageStreamRef xSrc = pStor->OpenSotStream(C2S("Equation Native"));
2083         if ( (!xSrc.Is()) || (SVSTREAM_OK != xSrc->GetError()))
2084             return 0;
2085 
2086         pS = &xSrc;
2087         pS->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
2088 
2089         pS->SeekRel(EQNOLEFILEHDR_SIZE); //Skip 28byte Header and fill it in later
2090         *pS << sal_uInt8(0x03);
2091         *pS << sal_uInt8(0x01);
2092         *pS << sal_uInt8(0x01);
2093         *pS << sal_uInt8(0x03);
2094         *pS << sal_uInt8(0x00);
2095         sal_uInt32 nSize = pS->Tell();
2096         nPendingAttributes=0;
2097 
2098         HandleNodes(pTree);
2099         *pS << sal_uInt8(END);
2100 
2101         nSize = pS->Tell()-nSize;
2102         pS->Seek(0);
2103         EQNOLEFILEHDR aHdr(nSize+4+1);
2104         aHdr.Write(pS);
2105 
2106         pStor->Commit();
2107     }
2108 
2109     return 1;
2110 }
2111 
2112 
HandleNodes(SmNode * pNode,int nLevel)2113 sal_uInt8 MathType::HandleNodes(SmNode *pNode,int nLevel)
2114 {
2115     sal_Bool bRet=sal_False;
2116     switch(pNode->GetType())
2117     {
2118         case NATTRIBUT:
2119             HandleAttributes(pNode,nLevel);
2120             break;
2121         case NTEXT:
2122             HandleText(pNode,nLevel);
2123             break;
2124         case NVERTICAL_BRACE:
2125             HandleVerticalBrace(pNode,nLevel);
2126             break;
2127         case NBRACE:
2128             HandleBrace(pNode,nLevel);
2129             break;
2130         case NOPER:
2131             HandleOperator(pNode,nLevel);
2132             break;
2133         case NBINVER:
2134             HandleFractions(pNode,nLevel);
2135             break;
2136         case NROOT:
2137             HandleRoot(pNode,nLevel);
2138             break;
2139         case NSPECIAL:
2140             {
2141             SmTextNode *pText=(SmTextNode *)pNode;
2142             //if the token str and the result text are the same then this
2143             //is to be seen as text, else assume its a mathchar
2144             if (pText->GetText() == pText->GetToken().aText)
2145                 HandleText(pText,nLevel);
2146             else
2147                 HandleMath(pText,nLevel);
2148             }
2149             break;
2150         case NMATH:
2151             HandleMath(pNode,nLevel);
2152             break;
2153         case NSUBSUP:
2154             HandleSubSupScript(pNode,nLevel);
2155             break;
2156         case NEXPRESSION:
2157             {
2158             sal_uInt16  nSize = pNode->GetNumSubNodes();
2159             for (sal_uInt16 i = 0; i < nSize; i++)
2160                 if (SmNode *pTemp = pNode->GetSubNode(i))
2161                     HandleNodes(pTemp,nLevel+1);
2162             }
2163             break;
2164         case NTABLE:
2165             //Root Node, PILE equivalent, i.e. vertical stack
2166             HandleTable(pNode,nLevel);
2167             break;
2168         case NMATRIX:
2169             HandleSmMatrix((SmMatrixNode *)pNode,nLevel);
2170             break;
2171         case NLINE:
2172             {
2173             *pS << sal_uInt8(0x0a);
2174             *pS << sal_uInt8(LINE);
2175             sal_uInt16  nSize = pNode->GetNumSubNodes();
2176             for (sal_uInt16 i = 0; i < nSize; i++)
2177                 if (SmNode *pTemp = pNode->GetSubNode(i))
2178                     HandleNodes(pTemp,nLevel+1);
2179             *pS << sal_uInt8(END);
2180             }
2181             break;
2182         case NALIGN:
2183             HandleMAlign(pNode,nLevel);
2184             break;
2185         case NBLANK:
2186             *pS << sal_uInt8(CHAR);
2187             *pS << sal_uInt8(0x98);
2188             if (pNode->GetToken().eType == TSBLANK)
2189                 *pS << sal_uInt16(0xEB04);
2190             else
2191                 *pS << sal_uInt16(0xEB05);
2192             break;
2193         default:
2194             {
2195             sal_uInt16  nSize = pNode->GetNumSubNodes();
2196             for (sal_uInt16 i = 0; i < nSize; i++)
2197                 if (SmNode *pTemp = pNode->GetSubNode(i))
2198                     HandleNodes(pTemp,nLevel+1);
2199             }
2200             break;
2201     }
2202     return bRet;
2203 }
2204 
2205 
StartTemplate(sal_uInt16 nSelector,sal_uInt16 nVariation)2206 int MathType::StartTemplate(sal_uInt16 nSelector,sal_uInt16 nVariation)
2207 {
2208     int nOldPending=nPendingAttributes;
2209     *pS << sal_uInt8(TMPL); //Template
2210     *pS << sal_uInt8(nSelector); //selector
2211     *pS << sal_uInt8(nVariation); //variation
2212     *pS << sal_uInt8(0x00); //options
2213     *pS << sal_uInt8(LINE);
2214     //theres just no way we can now handle any character
2215     //attributes (from mathtypes perspective) centered
2216     //over an expression but above template attribute
2217     //such as widevec and similiar constructs
2218     //we have to drop them
2219     nPendingAttributes=0;
2220     return nOldPending;
2221 }
2222 
EndTemplate(int nOldPendingAttributes)2223 void MathType::EndTemplate(int nOldPendingAttributes)
2224 {
2225     *pS << sal_uInt8(END); //end line
2226     *pS << sal_uInt8(END); //end template
2227     nPendingAttributes=nOldPendingAttributes;
2228 }
2229 
2230 
HandleSmMatrix(SmMatrixNode * pMatrix,int nLevel)2231 void MathType::HandleSmMatrix(SmMatrixNode *pMatrix,int nLevel)
2232 {
2233     *pS << sal_uInt8(MATRIX);
2234     *pS << sal_uInt8(0x00); //vAlign ?
2235     *pS << sal_uInt8(0x00); //h_just
2236     *pS << sal_uInt8(0x00); //v_just
2237     *pS << sal_uInt8(pMatrix->GetNumRows()); //v_just
2238     *pS << sal_uInt8(pMatrix->GetNumCols()); //v_just
2239     int nBytes=(pMatrix->GetNumRows()+1)*2/8;
2240     if (((pMatrix->GetNumRows()+1)*2)%8)
2241         nBytes++;
2242     for (sal_uInt16 j = 0; j < nBytes; j++)
2243         *pS << sal_uInt8(0x00); //row_parts
2244     nBytes=(pMatrix->GetNumCols()+1)*2/8;
2245     if (((pMatrix->GetNumCols()+1)*2)%8)
2246         nBytes++;
2247     for (sal_uInt16 k = 0; k < nBytes; k++)
2248         *pS << sal_uInt8(0x00); //col_parts
2249     sal_uInt16  nSize = pMatrix->GetNumSubNodes();
2250     for (sal_uInt16 i = 0; i < nSize; i++)
2251         if (SmNode *pTemp = pMatrix->GetSubNode(i))
2252         {
2253             *pS << sal_uInt8(LINE); //line
2254             HandleNodes(pTemp,nLevel+1);
2255             *pS << sal_uInt8(END); //end line
2256         }
2257     *pS << sal_uInt8(END);
2258 }
2259 
2260 
2261 //Root Node, PILE equivalent, i.e. vertical stack
HandleTable(SmNode * pNode,int nLevel)2262 void MathType::HandleTable(SmNode *pNode,int nLevel)
2263 {
2264     sal_uInt16  nSize = pNode->GetNumSubNodes();
2265     //The root of the starmath is a table, if
2266     //we convert this them each iteration of
2267     //conversion from starmath to mathtype will
2268     //add an extra unnecessary level to the
2269     //mathtype output stack which would grow
2270     //without bound in a multi step conversion
2271 
2272     if (nLevel == 0)
2273         *pS << sal_uInt8(0x0A); //initial size
2274 
2275     if ( nLevel || (nSize >1))
2276     {
2277         *pS << sal_uInt8(PILE);
2278         *pS << sal_uInt8(nHAlign); //vAlign ?
2279         *pS << sal_uInt8(0x01); //hAlign
2280     }
2281 
2282     for (sal_uInt16 i = 0; i < nSize; i++)
2283         if (SmNode *pTemp = pNode->GetSubNode(i))
2284         {
2285             *pS << sal_uInt8(LINE);
2286             HandleNodes(pTemp,nLevel+1);
2287             *pS << sal_uInt8(END);
2288         }
2289     if (nLevel || (nSize>1))
2290         *pS << sal_uInt8(END);
2291 }
2292 
2293 
HandleRoot(SmNode * pNode,int nLevel)2294 void MathType::HandleRoot(SmNode *pNode,int nLevel)
2295 {
2296     //sal_uInt16  nSize = pNode->GetNumSubNodes();
2297     SmNode *pTemp;
2298     *pS << sal_uInt8(TMPL); //Template
2299     *pS << sal_uInt8(0x0D); //selector
2300     if (pNode->GetSubNode(0))
2301         *pS << sal_uInt8(0x01); //variation
2302     else
2303         *pS << sal_uInt8(0x00); //variation
2304     *pS << sal_uInt8(0x00); //options
2305 
2306     /*
2307     if (pTemp = pNode->GetSubNode(1))
2308             HandleNodes(pTemp,nLevel+1);
2309     */
2310     if (NULL != (pTemp = pNode->GetSubNode(2)))
2311     {
2312         *pS << sal_uInt8(LINE); //line
2313         HandleNodes(pTemp,nLevel+1);
2314         *pS << sal_uInt8(END);
2315     }
2316 
2317     if (NULL != (pTemp = pNode->GetSubNode(0)))
2318     {
2319         *pS << sal_uInt8(LINE); //line
2320         HandleNodes(pTemp,nLevel+1);
2321         *pS << sal_uInt8(END);
2322     }
2323     else
2324         *pS << sal_uInt8(LINE|0x10); //dummy line
2325 
2326 
2327 
2328     *pS << sal_uInt8(END);
2329 }
2330 
HandleCScript(SmNode * pNode,SmNode * pContent,int nLevel,sal_uLong * pPos,sal_Bool bTest)2331 sal_uInt8 MathType::HandleCScript(SmNode *pNode,SmNode *pContent,int nLevel,
2332     sal_uLong *pPos,sal_Bool bTest)
2333 {
2334     sal_uInt8 nVariation2=0xff;
2335 
2336     if (bTest && pNode->GetSubNode(CSUP+1))
2337     {
2338         nVariation2=0;
2339         if (pNode->GetSubNode(CSUB+1))
2340             nVariation2=2;
2341     }
2342     else if (pNode->GetSubNode(CSUB+1))
2343         nVariation2=1;
2344 
2345     if (nVariation2!=0xff)
2346     {
2347         if (pPos)
2348             *pPos = pS->Tell();
2349         *pS << sal_uInt8(TMPL); //Template
2350         *pS << sal_uInt8(0x2B); //selector
2351         *pS << nVariation2;
2352         *pS << sal_uInt8(0x00); //options
2353 
2354         if (pContent)
2355         {
2356             *pS << sal_uInt8(LINE); //line
2357             HandleNodes(pContent,nLevel+1);
2358             *pS << sal_uInt8(END); //line
2359         }
2360         else
2361             *pS << sal_uInt8(LINE|0x10);
2362 
2363         *pS << sal_uInt8(0x0B);
2364 
2365         SmNode *pTemp;
2366         if (NULL != (pTemp = pNode->GetSubNode(CSUB+1)))
2367         {
2368             *pS << sal_uInt8(LINE); //line
2369             HandleNodes(pTemp,nLevel+1);
2370             *pS << sal_uInt8(END); //line
2371         }
2372         else
2373             *pS << sal_uInt8(LINE|0x10);
2374         if (bTest && NULL != (pTemp = pNode->GetSubNode(CSUP+1)))
2375         {
2376             *pS << sal_uInt8(LINE); //line
2377             HandleNodes(pTemp,nLevel+1);
2378             *pS << sal_uInt8(END); //line
2379         }
2380         else
2381             *pS << sal_uInt8(LINE|0x10);
2382     }
2383     return nVariation2;
2384 }
2385 
2386 
2387 
2388 /*
2389  Sub and Sup scripts and another problem area, StarMath
2390  can have all possible options used at the same time, whereas
2391  Mathtype cannot. The ordering of the nodes for each system
2392  is quite different as well leading to some complexity
2393  */
HandleSubSupScript(SmNode * pNode,int nLevel)2394 void MathType::HandleSubSupScript(SmNode *pNode,int nLevel)
2395 {
2396     //sal_uInt16  nSize = pNode->GetNumSubNodes();
2397     SmNode *pTemp;
2398 
2399     sal_uInt8 nVariation=0xff;
2400     if (pNode->GetSubNode(LSUP+1))
2401     {
2402         nVariation=0;
2403         if (pNode->GetSubNode(LSUB+1))
2404             nVariation=2;
2405     }
2406     else if (NULL != (pTemp = pNode->GetSubNode(LSUB+1)))
2407         nVariation=1;
2408 
2409     if (nVariation!=0xff)
2410     {
2411         *pS << sal_uInt8(TMPL); //Template
2412         *pS << sal_uInt8(0x2c); //selector
2413         *pS << nVariation;
2414         *pS << sal_uInt8(0x00); //options
2415         *pS << sal_uInt8(0x0B);
2416 
2417         if (NULL != (pTemp = pNode->GetSubNode(LSUB+1)))
2418         {
2419             *pS << sal_uInt8(LINE); //line
2420             HandleNodes(pTemp,nLevel+1);
2421             *pS << sal_uInt8(END); //line
2422         }
2423         else
2424             *pS << sal_uInt8(LINE|0x10);
2425         if (NULL != (pTemp = pNode->GetSubNode(LSUP+1)))
2426         {
2427             *pS << sal_uInt8(LINE); //line
2428             HandleNodes(pTemp,nLevel+1);
2429             *pS << sal_uInt8(END); //line
2430         }
2431         else
2432             *pS << sal_uInt8(LINE|0x10);
2433         *pS << sal_uInt8(END);
2434         nVariation=0xff;
2435     }
2436 
2437 
2438     sal_uInt8 nVariation2=HandleCScript(pNode,NULL,nLevel);
2439 
2440     if (NULL != (pTemp = pNode->GetSubNode(0)))
2441     {
2442 //      *pS << sal_uInt8(0x0A);
2443 //      *pS << sal_uInt8(LINE);
2444         HandleNodes(pTemp,nLevel+1);
2445 //      *pS << sal_uInt8(END);
2446     }
2447 
2448     if (nVariation2 != 0xff)
2449         *pS << sal_uInt8(END);
2450 
2451     if (NULL != (pNode->GetSubNode(RSUP+1)))
2452     {
2453         nVariation=0;
2454         if (pNode->GetSubNode(RSUB+1))
2455             nVariation=2;
2456     }
2457     else if (NULL != (pTemp = pNode->GetSubNode(RSUB+1)))
2458         nVariation=1;
2459 
2460     if (nVariation!=0xff)
2461     {
2462         *pS << sal_uInt8(TMPL); //Template
2463         *pS << sal_uInt8(0x0F); //selector
2464         *pS << nVariation;
2465         *pS << sal_uInt8(0x00); //options
2466         *pS << sal_uInt8(0x0B);
2467 
2468         if (NULL != (pTemp = pNode->GetSubNode(RSUB+1)))
2469         {
2470             *pS << sal_uInt8(LINE); //line
2471             HandleNodes(pTemp,nLevel+1);
2472             *pS << sal_uInt8(END); //line
2473         }
2474         else
2475             *pS << sal_uInt8(LINE|0x10);
2476         if (NULL != (pTemp = pNode->GetSubNode(RSUP+1)))
2477         {
2478             *pS << sal_uInt8(LINE); //line
2479             HandleNodes(pTemp,nLevel+1);
2480             *pS << sal_uInt8(END); //line
2481         }
2482         else
2483             *pS << sal_uInt8(LINE|0x10);
2484     *pS << sal_uInt8(END); //line
2485     }
2486 
2487     //After subscript mathtype will keep the size of
2488     //normal text at the subscript size, sigh.
2489     *pS << sal_uInt8(0x0A);
2490 }
2491 
2492 
HandleFractions(SmNode * pNode,int nLevel)2493 void MathType::HandleFractions(SmNode *pNode,int nLevel)
2494 {
2495     //sal_uInt16  nSize = pNode->GetNumSubNodes();
2496     SmNode *pTemp;
2497     *pS << sal_uInt8(TMPL); //Template
2498     *pS << sal_uInt8(0x0E); //selector
2499     *pS << sal_uInt8(0x00); //variation
2500     *pS << sal_uInt8(0x00); //options
2501 
2502     *pS << sal_uInt8(0x0A);
2503     *pS << sal_uInt8(LINE); //line
2504     if (NULL != (pTemp = pNode->GetSubNode(0)))
2505         HandleNodes(pTemp,nLevel+1);
2506     *pS << sal_uInt8(END);
2507 
2508     *pS << sal_uInt8(0x0A);
2509     *pS << sal_uInt8(LINE); //line
2510     if (NULL != (pTemp = pNode->GetSubNode(2)))
2511         HandleNodes(pTemp,nLevel+1);
2512     *pS << sal_uInt8(END);
2513 
2514     *pS << sal_uInt8(END);
2515 }
2516 
2517 
HandleBrace(SmNode * pNode,int nLevel)2518 void MathType::HandleBrace(SmNode *pNode,int nLevel)
2519 {
2520     //sal_uInt16  nSize = pNode->GetNumSubNodes();
2521     SmNode *pTemp;
2522     SmNode *pLeft=pNode->GetSubNode(0);
2523     SmNode *pRight=pNode->GetSubNode(2);
2524 
2525     *pS << sal_uInt8(TMPL); //Template
2526     bIsReInterpBrace=0;
2527     sal_uInt8 nBSpec=0x10;
2528     sal_uLong nLoc = pS->Tell();
2529     if (pLeft)
2530     {
2531         switch (pLeft->GetToken().eType)
2532         {
2533             case TLANGLE:
2534                 *pS << sal_uInt8(tmANGLE); //selector
2535                 *pS << sal_uInt8(0x00); //variation
2536                 *pS << sal_uInt8(0x00); //options
2537                 break;
2538             case TLBRACE:
2539                 *pS << sal_uInt8(tmBRACE); //selector
2540                 *pS << sal_uInt8(0x00); //variation
2541                 *pS << sal_uInt8(0x00); //options
2542                 nBSpec+=3;
2543                 break;
2544             case TLBRACKET:
2545                 *pS << sal_uInt8(tmBRACK); //selector
2546                 *pS << sal_uInt8(0x00); //variation
2547                 *pS << sal_uInt8(0x00); //options
2548                 nBSpec+=3;
2549                 break;
2550             case TLFLOOR:
2551                 *pS << sal_uInt8(tmFLOOR); //selector
2552                 *pS << sal_uInt8(0x00); //variation
2553                 *pS << sal_uInt8(0x00); //options
2554                 break;
2555             case TLLINE:
2556                 *pS << sal_uInt8(tmBAR); //selector
2557                 *pS << sal_uInt8(0x00); //variation
2558                 *pS << sal_uInt8(0x00); //options
2559                 nBSpec+=3;
2560                 break;
2561             case TLDLINE:
2562                 *pS << sal_uInt8(tmDBAR); //selector
2563                 *pS << sal_uInt8(0x00); //variation
2564                 *pS << sal_uInt8(0x00); //options
2565                 break;
2566             default:
2567                 *pS << sal_uInt8(tmPAREN); //selector
2568                 *pS << sal_uInt8(0x00); //variation
2569                 *pS << sal_uInt8(0x00); //options
2570                 nBSpec+=3;
2571                 break;
2572         }
2573     }
2574 
2575     if (NULL != (pTemp = pNode->GetSubNode(1)))
2576     {
2577         *pS << sal_uInt8(LINE); //line
2578         HandleNodes(pTemp,nLevel+1);
2579         *pS << sal_uInt8(END); //options
2580     }
2581     nSpec=nBSpec;
2582     if (pLeft)
2583         HandleNodes(pLeft,nLevel+1);
2584     if (bIsReInterpBrace)
2585     {
2586         sal_uLong nLoc2 = pS->Tell();
2587         pS->Seek(nLoc);
2588         *pS << sal_uInt8(0x2D);
2589         pS->Seek(nLoc2);
2590         *pS << sal_uInt8(CHAR);
2591         *pS << sal_uInt8(0x96);
2592         *pS << sal_uInt16(0xEC07);
2593         bIsReInterpBrace=0;
2594     }
2595     if (pRight)
2596         HandleNodes(pRight,nLevel+1);
2597     nSpec=0x0;
2598     *pS << sal_uInt8(END);
2599 }
2600 
2601 
HandleVerticalBrace(SmNode * pNode,int nLevel)2602 void MathType::HandleVerticalBrace(SmNode *pNode,int nLevel)
2603 {
2604     SmNode *pTemp;
2605     *pS << sal_uInt8(TMPL); //Template
2606     if (pNode->GetToken().eType == TUNDERBRACE)
2607         *pS << sal_uInt8(tmLHBRACE); //selector
2608     else
2609         *pS << sal_uInt8(tmUHBRACE); //selector
2610     *pS << sal_uInt8(0x01); //variation
2611     *pS << sal_uInt8(0x00); //options
2612 
2613     if (NULL != (pTemp = pNode->GetSubNode(0)))
2614     {
2615         *pS << sal_uInt8(LINE); //line
2616         HandleNodes(pTemp,nLevel+1);
2617         *pS << sal_uInt8(END); //options
2618     }
2619 
2620     if (NULL != (pTemp = pNode->GetSubNode(2)))
2621     {
2622         *pS << sal_uInt8(LINE); //line
2623         HandleNodes(pTemp,nLevel+1);
2624         *pS << sal_uInt8(END); //options
2625     }
2626     *pS << sal_uInt8(END);
2627 }
2628 
HandleOperator(SmNode * pNode,int nLevel)2629 void MathType::HandleOperator(SmNode *pNode,int nLevel)
2630 {
2631     //sal_uInt16  nSize = pNode->GetNumSubNodes();
2632 
2633     if (HandleLim(pNode,nLevel))
2634         return;
2635 
2636     sal_uLong nPos;
2637     sal_uInt8 nVariation;
2638 
2639     switch (pNode->GetToken().eType)
2640     {
2641         case TIINT:
2642         case TIIINT:
2643         case TLINT:
2644         case TLLINT:
2645         case TLLLINT:
2646             nVariation=HandleCScript(pNode->GetSubNode(0),
2647                 pNode->GetSubNode(1),nLevel,&nPos,0);
2648             break;
2649         default:
2650             nVariation=HandleCScript(pNode->GetSubNode(0),
2651                 pNode->GetSubNode(1),nLevel,&nPos);
2652             break;
2653     }
2654 
2655     sal_uInt8 nOldVariation=nVariation;
2656     sal_uInt8 nIntVariation=nVariation;
2657 
2658     sal_uLong nPos2=0;
2659     if (nVariation != 0xff)
2660     {
2661         nPos2 = pS->Tell();
2662         pS->Seek(nPos);
2663         if (nVariation == 2)
2664         {
2665             nIntVariation=0;
2666             nVariation = 1;
2667         }
2668         else if (nVariation == 0)
2669             nVariation = 1;
2670         else if (nVariation == 1)
2671             nVariation = 0;
2672     }
2673     else
2674     {
2675         nVariation = 2;
2676         nIntVariation=0;
2677     }
2678     *pS << sal_uInt8(TMPL);
2679     switch(pNode->GetToken().eType)
2680     {
2681     case TINT:
2682         if (nOldVariation != 0xff)
2683             *pS << sal_uInt8(0x18); //selector
2684         else
2685             *pS << sal_uInt8(0x15); //selector
2686         *pS << nIntVariation; //variation
2687         break;
2688     case TIINT:
2689         if (nOldVariation != 0xff)
2690         {
2691             *pS << sal_uInt8(0x19);
2692             *pS << sal_uInt8(0x01);
2693         }
2694         else
2695         {
2696             *pS << sal_uInt8(0x16);
2697             *pS << sal_uInt8(0x00);
2698         }
2699         break;
2700     case TIIINT:
2701         if (nOldVariation != 0xff)
2702         {
2703             *pS << sal_uInt8(0x1a);
2704             *pS << sal_uInt8(0x01);
2705         }
2706         else
2707         {
2708             *pS << sal_uInt8(0x17);
2709             *pS << sal_uInt8(0x00);
2710         }
2711         break;
2712     case TLINT:
2713         if (nOldVariation != 0xff)
2714         {
2715             *pS << sal_uInt8(0x18);
2716             *pS << sal_uInt8(0x02);
2717         }
2718         else
2719         {
2720             *pS << sal_uInt8(0x15);
2721             *pS << sal_uInt8(0x03);
2722         }
2723         break;
2724     case TLLINT:
2725         if (nOldVariation != 0xff)
2726         {
2727             *pS << sal_uInt8(0x19);
2728             *pS << sal_uInt8(0x00);
2729         }
2730         else
2731         {
2732             *pS << sal_uInt8(0x16);
2733             *pS << sal_uInt8(0x02);
2734         }
2735         break;
2736     case TLLLINT:
2737         if (nOldVariation != 0xff)
2738         {
2739             *pS << sal_uInt8(0x1a);
2740             *pS << sal_uInt8(0x00);
2741         }
2742         else
2743         {
2744             *pS << sal_uInt8(0x17);
2745             *pS << sal_uInt8(0x02);
2746         }
2747         break;
2748     case TSUM:
2749     default:
2750         *pS << sal_uInt8(0x1d);
2751         *pS << nVariation;
2752         break;
2753     case TPROD:
2754         *pS << sal_uInt8(0x1f);
2755         *pS << nVariation;
2756         break;
2757     case TCOPROD:
2758         *pS << sal_uInt8(0x21);
2759         *pS << nVariation;
2760         break;
2761     }
2762     *pS << sal_uInt8(0x00); //options
2763 
2764     if (nPos2)
2765         pS->Seek(nPos2);
2766     else
2767     {
2768         *pS << sal_uInt8(LINE); //line
2769         HandleNodes(pNode->GetSubNode(1),nLevel+1);
2770         *pS << sal_uInt8(END); //line
2771         *pS << sal_uInt8(LINE|0x10);
2772         *pS << sal_uInt8(LINE|0x10);
2773     }
2774 
2775 
2776     *pS << sal_uInt8(0x0D);
2777     switch(pNode->GetToken().eType)
2778     {
2779     case TSUM:
2780     default:
2781         *pS << sal_uInt8(CHAR);
2782         *pS << sal_uInt8(0x86);
2783         *pS << sal_uInt16(0x2211);
2784         break;
2785     case TPROD:
2786         *pS << sal_uInt8(CHAR);
2787         *pS << sal_uInt8(0x86);
2788         *pS << sal_uInt16(0x220F);
2789         break;
2790     case TCOPROD:
2791         *pS << sal_uInt8(CHAR);
2792         *pS << sal_uInt8(0x8B);
2793         *pS << sal_uInt16(0x2210);
2794         break;
2795     case TIIINT:
2796     case TLLLINT:
2797         *pS << sal_uInt8(CHAR);
2798         *pS << sal_uInt8(0x86);
2799         *pS << sal_uInt16(0x222B);
2800     case TIINT:
2801     case TLLINT:
2802         *pS << sal_uInt8(CHAR);
2803         *pS << sal_uInt8(0x86);
2804         *pS << sal_uInt16(0x222B);
2805     case TINT:
2806     case TLINT:
2807         *pS << sal_uInt8(CHAR);
2808         *pS << sal_uInt8(0x86);
2809         *pS << sal_uInt16(0x222B);
2810         break;
2811     }
2812     *pS << sal_uInt8(END);
2813     *pS << sal_uInt8(0x0A);
2814 }
2815 
2816 
HandlePile(int & rSetAlign,int nLevel,sal_uInt8 nSelector,sal_uInt8 nVariation)2817 int MathType::HandlePile(int &rSetAlign,int nLevel,sal_uInt8 nSelector,
2818     sal_uInt8 nVariation)
2819 {
2820     *pS >> nHAlign;
2821     *pS >> nVAlign;
2822 
2823     HandleAlign(nHAlign,nVAlign,rSetAlign);
2824 
2825     APPEND(rRet," stack {\n");
2826     int nRet = HandleRecords(nLevel+1,nSelector,nVariation,-1,-1);
2827     rRet.Erase(rRet.Len()-3,2);
2828     APPEND(rRet,"} ");
2829 
2830     while (rSetAlign)
2831     {
2832         APPEND(rRet,"} ");
2833         rSetAlign--;
2834     }
2835     return nRet;
2836 }
2837 
HandleMatrix(int nLevel,sal_uInt8 nSelector,sal_uInt8 nVariation)2838 int MathType::HandleMatrix(int nLevel,sal_uInt8 nSelector,
2839     sal_uInt8 nVariation)
2840 {
2841     sal_uInt8 nH_just,nV_just,nRows,nCols;
2842     *pS >> nVAlign;
2843     *pS >> nH_just;
2844     *pS >> nV_just;
2845     *pS >> nRows;
2846     *pS >> nCols;
2847     int nBytes = ((nRows+1)*2)/8;
2848     if (((nRows+1)*2)%8)
2849         nBytes++;
2850     pS->SeekRel(nBytes);
2851     nBytes = ((nCols+1)*2)/8;
2852     if (((nCols+1)*2)%8)
2853         nBytes++;
2854     pS->SeekRel(nBytes);
2855     APPEND(rRet," matrix {\n");
2856     int nRet = HandleRecords(nLevel+1,nSelector,nVariation,nRows,nCols);
2857 
2858     xub_StrLen nI = rRet.SearchBackward('#');
2859     if ((nI != STRING_NOTFOUND) && (nI > 0))
2860         if (rRet.GetChar(nI-1) != '#')  //missing column
2861             APPEND(rRet,"{}");
2862 
2863     APPEND(rRet,"\n} ");
2864     return nRet;
2865 }
2866 
HandleTemplate(int nLevel,sal_uInt8 & rSelector,sal_uInt8 & rVariation,xub_StrLen & rLastTemplateBracket)2867 int MathType::HandleTemplate(int nLevel,sal_uInt8 &rSelector,
2868     sal_uInt8 &rVariation, xub_StrLen &rLastTemplateBracket)
2869 {
2870     sal_uInt8 nOption; //This appears utterly unused
2871     *pS >> rSelector;
2872     *pS >> rVariation;
2873     *pS >> nOption;
2874     DBG_ASSERT(rSelector < 48,"Selector out of range");
2875     if ((rSelector >= 21) && (rSelector <=26))
2876     {
2877         DBG_ASSERT(nOption < 2,"Option out of range");
2878     }
2879     else if (/*(rSelector >= 0) &&*/ (rSelector <=12))
2880     {
2881         DBG_ASSERT(nOption < 3,"Option out of range");
2882     }
2883 
2884     //For the (broken) case where one subscript template ends, and there is
2885     //another one after it, mathtype handles it as if the second one was
2886     //inside the first one and renders it as sub of sub
2887     sal_Bool bRemove=sal_False;
2888     if ( (rSelector == 0xf) && (rLastTemplateBracket != STRING_NOTFOUND) )
2889     {
2890         bRemove=sal_True;
2891         for (xub_StrLen nI = rLastTemplateBracket+1; nI < rRet.Len(); nI++ )
2892             if (rRet.GetChar(nI) != ' ')
2893             {
2894                 bRemove=sal_False;
2895                 break;
2896             }
2897     }
2898 
2899     //suborderlist
2900     int nRet = HandleRecords(nLevel+1,rSelector,rVariation);
2901 
2902     if (bRemove)
2903     {
2904         rRet.Erase(rLastTemplateBracket,1);
2905         APPEND(rRet,"} ");
2906         rLastTemplateBracket = STRING_NOTFOUND;
2907     }
2908     if (rSelector == 0xf)
2909         rLastTemplateBracket = rRet.SearchBackward('}');
2910     else
2911         rLastTemplateBracket = STRING_NOTFOUND;
2912 
2913     rSelector = sal::static_int_cast< sal_uInt8 >(-1);
2914     return nRet;
2915 }
2916 
HandleEmblishments()2917 void MathType::HandleEmblishments()
2918 {
2919     sal_uInt8 nEmbel;
2920     do
2921     {
2922         *pS >> nEmbel;
2923         switch (nEmbel)
2924         {
2925         case 0x02:
2926             APPEND(rRet," dot ");
2927             break;
2928         case 0x03:
2929             APPEND(rRet," ddot ");
2930             break;
2931         case 0x04:
2932             APPEND(rRet," dddot ");
2933             break;
2934         case 0x05:
2935             if (nPostSup == 0)
2936             {
2937                 APPEND(sPost," sup {}");
2938                 nPostSup = sPost.Len();
2939             }
2940             sPost.InsertAscii(" ' ",nPostSup-1);
2941             nPostSup += 3;
2942             break;
2943         case 0x06:
2944             if (nPostSup == 0)
2945             {
2946                 APPEND(sPost," sup {}");
2947                 nPostSup = sPost.Len();
2948             }
2949             sPost.InsertAscii(" '' ",nPostSup-1);
2950             nPostSup += 4;
2951             break;
2952         case 0x07:
2953             if (nPostlSup == 0)
2954             {
2955                 APPEND(sPost," lsup {}");
2956                 nPostlSup = sPost.Len();
2957             }
2958             sPost.InsertAscii(" ' ",nPostlSup-1);
2959             nPostlSup += 3;
2960             break;
2961         case 0x08:
2962             APPEND(rRet," tilde ");
2963             break;
2964         case 0x09:
2965             APPEND(rRet," hat ");
2966             break;
2967         case 0x0b:
2968             APPEND(rRet," vec ");
2969             break;
2970         case 0x10:
2971             APPEND(rRet," overstrike ");
2972             break;
2973         case 0x11:
2974             APPEND(rRet," bar ");
2975             break;
2976         case 0x12:
2977             if (nPostSup == 0)
2978             {
2979                 APPEND(sPost," sup {}");
2980                 nPostSup = sPost.Len();
2981             }
2982             sPost.InsertAscii(" ''' ",nPostSup-1);
2983             nPostSup += 5;
2984             break;
2985         case 0x14:
2986             APPEND(rRet," breve ");
2987             break;
2988         default:
2989             DBG_ASSERT(nEmbel < 21,"Embel out of range");
2990             break;
2991         }
2992         if (nVersion < 3)
2993             break;
2994     }while (nEmbel);
2995 }
2996 
HandleSetSize()2997 void MathType::HandleSetSize()
2998 {
2999     sal_uInt8 nTemp;
3000     *pS >> nTemp;
3001     switch (nTemp)
3002     {
3003         case 101:
3004             *pS >> nLSize;
3005             nLSize = -nLSize;
3006             break;
3007         case 100:
3008             *pS >> nTemp;
3009             nLSize = nTemp;
3010             *pS >> nDSize;
3011             break;
3012         default:
3013             nLSize = nTemp;
3014             *pS >> nTemp;
3015             nDSize = nTemp-128;
3016             break;
3017     }
3018 }
3019 
HandleChar(xub_StrLen & rTextStart,int & rSetSize,int nLevel,sal_uInt8 nTag,sal_uInt8 nSelector,sal_uInt8 nVariation,sal_Bool bSilent)3020 int MathType::HandleChar(xub_StrLen &rTextStart,int &rSetSize,int nLevel,
3021     sal_uInt8 nTag,sal_uInt8 nSelector,sal_uInt8 nVariation, sal_Bool bSilent)
3022 {
3023     sal_Unicode nChar;
3024     int nRet=1;
3025 
3026     if (xfAUTO(nTag))
3027     {
3028     //This is a candidate for function recognition, whatever
3029     //that is!
3030     }
3031 
3032     sal_uInt8 nOldTypeFace = nTypeFace;
3033     *pS >> nTypeFace;
3034     if (nVersion < 3)
3035     {
3036         sal_uInt8 nChar8;
3037         *pS >> nChar8;
3038         nChar = nChar8;
3039     }
3040     else
3041         *pS >> nChar;
3042 
3043     /*
3044     ##912##
3045     bad character, old mathtype < 3 has these
3046     */
3047     if (nChar < 0x20)
3048         return nRet;
3049 
3050     if (xfEMBELL(nTag))
3051     {
3052         //A bit tricky, the character emblishments for
3053         //mathtype can all be listed after eachother, in
3054         //starmath some must go before the character and some
3055         //must go after. In addition some of the emblishments
3056         //may repeated and in starmath some of these groups
3057         //must be gathered together. sPost is the portion that
3058         //follows the char and nPostSup and nPostlSup are the
3059         //indexes at which this class of emblishment is
3060         //collated together
3061         sPost.Erase();
3062         nPostSup = nPostlSup = 0;
3063         int nOriglen=rRet.Len()-rTextStart;
3064         APPEND(rRet," {");  // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n"
3065         if ((!bSilent) && ((nOriglen) > 1))
3066             rRet += '\"';
3067         nRet = HandleRecords(nLevel+1,nSelector,nVariation);
3068         if (!bSilent)
3069         {
3070             if (nOriglen > 1)
3071             {
3072                 String aStr;
3073                 TypeFaceToString(aStr,nOldTypeFace);
3074                 aStr += '\"';
3075                 rRet.Insert(aStr,rTextStart);
3076 
3077                 aStr.Erase();
3078                 TypeFaceToString(aStr,nTypeFace);
3079                 rRet.Append(aStr);
3080                 rRet += '{';
3081             }
3082             else
3083                 APPEND(rRet," {");
3084             rTextStart = rRet.Len();
3085         }
3086     }
3087 
3088     if (!bSilent)
3089     {
3090         xub_StrLen nOldLen = rRet.Len();
3091         //nLastSize = nCurSize;
3092         if (
3093             HandleSize(nLSize,nDSize,rSetSize) ||
3094             (nOldTypeFace != nTypeFace)
3095            )
3096         {
3097             if ((nOldLen - rTextStart) > 1)
3098             {
3099                 rRet.InsertAscii("\"",nOldLen);
3100                 String aStr;
3101                 TypeFaceToString(aStr,nOldTypeFace);
3102                 aStr += '\"';
3103                 rRet.Insert(aStr,rTextStart);
3104             }
3105             rTextStart = rRet.Len();
3106         }
3107         nOldLen = rRet.Len();
3108         if (!LookupChar(nChar,rRet,nVersion,nTypeFace))
3109         {
3110             if (nOldLen - rTextStart > 1)
3111             {
3112                 rRet.InsertAscii("\"",nOldLen);
3113                 String aStr;
3114                 TypeFaceToString(aStr,nOldTypeFace);
3115                 aStr += '\"';
3116                 rRet.Insert(aStr,rTextStart);
3117             }
3118             rTextStart = rRet.Len();
3119         }
3120         lcl_PrependDummyTerm(rRet, rTextStart);
3121     }
3122 
3123     if ((xfEMBELL(nTag)) && (!bSilent))
3124     {
3125         rRet += '}';    // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n"
3126         rRet += '}';
3127         rRet += sPost;
3128         rTextStart = rRet.Len();
3129     }
3130     return nRet;
3131 }
3132 
HandleLim(SmNode * pNode,int nLevel)3133 sal_Bool MathType::HandleLim(SmNode *pNode,int nLevel)
3134 {
3135     sal_Bool bRet=0;
3136     //Special case for the "lim" option in StarMath
3137     if ((pNode->GetToken().eType == TLIM)
3138         || (pNode->GetToken().eType == TLIMSUP)
3139         || (pNode->GetToken().eType == TLIMINF)
3140         )
3141     {
3142         if (pNode->GetSubNode(1))
3143         {
3144             sal_uInt8 nVariation2=HandleCScript(pNode->GetSubNode(0),NULL,
3145                 nLevel);
3146 
3147             *pS << sal_uInt8(0x0A);
3148             *pS << sal_uInt8(LINE); //line
3149             *pS << sal_uInt8(CHAR|0x10);
3150             *pS << sal_uInt8(0x82);
3151             *pS << sal_uInt16('l');
3152             *pS << sal_uInt8(CHAR|0x10);
3153             *pS << sal_uInt8(0x82);
3154             *pS << sal_uInt16('i');
3155             *pS << sal_uInt8(CHAR|0x10);
3156             *pS << sal_uInt8(0x82);
3157             *pS << sal_uInt16('m');
3158 
3159             if (pNode->GetToken().eType == TLIMSUP)
3160             {
3161                 *pS << sal_uInt8(CHAR); //some space
3162                 *pS << sal_uInt8(0x98);
3163                 *pS << sal_uInt16(0xEB04);
3164 
3165                 *pS << sal_uInt8(CHAR|0x10);
3166                 *pS << sal_uInt8(0x82);
3167                 *pS << sal_uInt16('s');
3168                 *pS << sal_uInt8(CHAR|0x10);
3169                 *pS << sal_uInt8(0x82);
3170                 *pS << sal_uInt16('u');
3171                 *pS << sal_uInt8(CHAR|0x10);
3172                 *pS << sal_uInt8(0x82);
3173                 *pS << sal_uInt16('p');
3174             }
3175             else if (pNode->GetToken().eType == TLIMINF)
3176             {
3177                 *pS << sal_uInt8(CHAR); //some space
3178                 *pS << sal_uInt8(0x98);
3179                 *pS << sal_uInt16(0xEB04);
3180 
3181                 *pS << sal_uInt8(CHAR|0x10);
3182                 *pS << sal_uInt8(0x82);
3183                 *pS << sal_uInt16('i');
3184                 *pS << sal_uInt8(CHAR|0x10);
3185                 *pS << sal_uInt8(0x82);
3186                 *pS << sal_uInt16('n');
3187                 *pS << sal_uInt8(CHAR|0x10);
3188                 *pS << sal_uInt8(0x82);
3189                 *pS << sal_uInt16('f');
3190             }
3191 
3192 
3193             *pS << sal_uInt8(CHAR); //some space
3194             *pS << sal_uInt8(0x98);
3195             *pS << sal_uInt16(0xEB04);
3196 
3197             if (nVariation2 != 0xff)
3198             {
3199                 *pS << sal_uInt8(END);
3200                 *pS << sal_uInt8(END);
3201             }
3202             HandleNodes(pNode->GetSubNode(1),nLevel+1);
3203             //*pS << sal_uInt8(END); //options
3204             bRet = 1;
3205         }
3206     }
3207     return bRet;
3208 }
3209 
HandleMAlign(SmNode * pNode,int nLevel)3210 void MathType::HandleMAlign(SmNode *pNode,int nLevel)
3211 {
3212     sal_uInt8 nPushedHAlign=nHAlign;
3213     switch(pNode->GetToken().eType)
3214     {
3215         case TALIGNC:
3216             nHAlign=2;
3217             break;
3218         case TALIGNR:
3219             nHAlign=3;
3220             break;
3221         default:
3222             nHAlign=1;
3223             break;
3224     }
3225     sal_uInt16  nSize = pNode->GetNumSubNodes();
3226     for (sal_uInt16 i = 0; i < nSize; i++)
3227         if (SmNode *pTemp = pNode->GetSubNode(i))
3228             HandleNodes(pTemp,nLevel+1);
3229     nHAlign=nPushedHAlign;
3230 }
3231 
HandleMath(SmNode * pNode,int)3232 void MathType::HandleMath(SmNode *pNode, int /*nLevel*/)
3233 {
3234     if (pNode->GetToken().eType == TMLINE)
3235     {
3236         *pS << sal_uInt8(END);
3237         *pS << sal_uInt8(LINE);
3238         bIsReInterpBrace=1;
3239         return;
3240     }
3241     SmMathSymbolNode *pTemp=(SmMathSymbolNode *)pNode;
3242     for(xub_StrLen i=0;i<pTemp->GetText().Len();i++)
3243     {
3244         sal_Unicode nArse = Convert(pTemp->GetText().GetChar(i));
3245         if ((nArse == 0x2224) || (nArse == 0x2288) || (nArse == 0x2285) ||
3246             (nArse == 0x2289))
3247         {
3248             *pS << sal_uInt8(CHAR|0x20);
3249         }
3250         else if ((nPendingAttributes) &&
3251                 (i == ((pTemp->GetText().Len()+1)/2)-1))
3252             {
3253                 *pS << sal_uInt8(0x22);
3254             }
3255         else
3256             *pS << sal_uInt8(CHAR); //char without formula recognition
3257         //The typeface seems to be MTEXTRA for unicode characters,
3258         //though how to determine when mathtype chooses one over
3259         //the other is unknown. This should do the trick
3260         //nevertheless.
3261         sal_uInt8 nBias;
3262         if ( (nArse == 0x2213) || (nArse == 0x2218) ||
3263             (nArse == 0x210F) || (
3264                 (nArse >= 0x22EE) && (nArse <= 0x22FF)
3265             ))
3266         {
3267             nBias = 0xB; //typeface
3268         }
3269         else if ((nArse > 0x2000) || (nArse == 0x00D7))
3270             nBias = 0x6; //typeface
3271         else if (nArse == 0x3d1)
3272             nBias = 0x4;
3273         else if ((nArse > 0xFF) && ((nArse < 0x393) || (nArse > 0x3c9)))
3274             nBias = 0xB; //typeface
3275         else if ((nArse == 0x2F) || (nArse == 0x2225))
3276             nBias = 0x2; //typeface
3277         else
3278             nBias = 0x3; //typeface
3279 
3280         *pS << sal_uInt8(nSpec+nBias+128); //typeface
3281 
3282         if (nArse == 0x2224)
3283         {
3284             *pS << sal_uInt16(0x7C);
3285             *pS << sal_uInt8(EMBEL);
3286             *pS << sal_uInt8(0x0A);
3287             *pS << sal_uInt8(END); //end embel
3288             *pS << sal_uInt8(END); //end embel
3289         }
3290         else if (nArse == 0x2225)
3291             *pS << sal_uInt16(0xEC09);
3292         else if (nArse == 0xE421)
3293             *pS << sal_uInt16(0x2265);
3294         else if (nArse == 0x230A)
3295             *pS << sal_uInt16(0xF8F0);
3296         else if (nArse == 0x230B)
3297             *pS << sal_uInt16(0xF8FB);
3298         else if (nArse == 0xE425)
3299             *pS << sal_uInt16(0x2264);
3300         else if (nArse == 0x226A)
3301         {
3302             *pS << sal_uInt16(0x3C);
3303             *pS << sal_uInt8(CHAR);
3304             *pS << sal_uInt8(0x98);
3305             *pS << sal_uInt16(0xEB01);
3306             *pS << sal_uInt8(CHAR);
3307             *pS << sal_uInt8(0x86);
3308             *pS << sal_uInt16(0x3c);
3309         }
3310         else if (nArse == 0x2288)
3311         {
3312             *pS << sal_uInt16(0x2286);
3313             *pS << sal_uInt8(EMBEL);
3314             *pS << sal_uInt8(0x0A);
3315             *pS << sal_uInt8(END); //end embel
3316             *pS << sal_uInt8(END); //end embel
3317         }
3318         else if (nArse == 0x2289)
3319         {
3320             *pS << sal_uInt16(0x2287);
3321             *pS << sal_uInt8(EMBEL);
3322             *pS << sal_uInt8(0x0A);
3323             *pS << sal_uInt8(END); //end embel
3324             *pS << sal_uInt8(END); //end embel
3325         }
3326         else if (nArse == 0x2285)
3327         {
3328             *pS << sal_uInt16(0x2283);
3329             *pS << sal_uInt8(EMBEL);
3330             *pS << sal_uInt8(0x0A);
3331             *pS << sal_uInt8(END); //end embel
3332             *pS << sal_uInt8(END); //end embel
3333         }
3334         else
3335             *pS << nArse;
3336     }
3337     nPendingAttributes = 0;
3338 }
3339 
HandleAttributes(SmNode * pNode,int nLevel)3340 void MathType::HandleAttributes(SmNode *pNode,int nLevel)
3341 {
3342     int nOldPending = 0;
3343     //sal_uInt16  nSize = pNode->GetNumSubNodes();
3344     SmNode *pTemp       = 0;
3345     SmTextNode *pIsText = 0;
3346 
3347     //SmTextNode *pTemp=(SmTextNode *)pNode;
3348     //for(int i=0;i<pTemp->GetText().Len();i++)
3349 
3350     if (NULL != (pTemp = pNode->GetSubNode(0)))
3351     {
3352         pIsText = (SmTextNode *)pNode->GetSubNode(1);
3353 
3354         switch (pTemp->GetToken().eType)
3355         {
3356         case TWIDEVEC:
3357             //theres just no way we can now handle any character
3358             //attributes (from mathtypes perspective) centered
3359             //over an expression but above template attributes
3360             //such as widevec and similiar constructs
3361             //we have to drop them
3362             nOldPending = StartTemplate(0x2f,0x01);
3363             break;
3364         case TCHECK: //Not Exportable
3365         case TACUTE: //Not Exportable
3366         case TGRAVE: //Not Exportable
3367         case TCIRCLE: //Not Exportable
3368         case TWIDETILDE: //Not Exportable
3369         case TWIDEHAT: //Not Exportable
3370             break;
3371         case TUNDERLINE:
3372             nOldPending = StartTemplate(0x10);
3373             break;
3374         case TOVERLINE: //If the next node is not text
3375                         //or text with more than one char
3376             if ((pIsText->GetToken().eType != TTEXT) ||
3377                 (pIsText->GetText().Len() > 1))
3378                 nOldPending = StartTemplate(0x11);
3379             break;
3380         default:
3381             nPendingAttributes++;
3382             break;
3383         }
3384     }
3385 
3386     if (pIsText)
3387         HandleNodes(pIsText,nLevel+1);
3388 
3389     switch (pTemp->GetToken().eType)
3390     {
3391         case TWIDEVEC:
3392         case TUNDERLINE:
3393             EndTemplate(nOldPending);
3394             break;
3395         case TOVERLINE:
3396             if ((pIsText->GetToken().eType != TTEXT) ||
3397                 (pIsText->GetText().Len() > 1))
3398                 EndTemplate(nOldPending);
3399             break;
3400         default:
3401             break;
3402     }
3403 
3404     //if there was no suitable place to put the attribute,
3405     //then we have to just give up on it
3406     if (nPendingAttributes)
3407         nPendingAttributes--;
3408     else
3409     {
3410         if ((nInsertion != 0) && NULL != (pTemp = pNode->GetSubNode(0)))
3411         {
3412             sal_uLong nPos = pS->Tell();
3413             nInsertion--;
3414             pS->Seek(nInsertion);
3415             switch(pTemp->GetToken().eType)
3416             {
3417             case TACUTE: //Not Exportable
3418             case TGRAVE: //Not Exportable
3419             case TCIRCLE: //Not Exportable
3420                 break;
3421             case TCDOT:
3422                 *pS << sal_uInt8(2);
3423                 break;
3424             case TDDOT:
3425                 *pS << sal_uInt8(3);
3426                 break;
3427             case TDDDOT:
3428                 *pS << sal_uInt8(4);
3429                 break;
3430             case TTILDE:
3431                 *pS << sal_uInt8(8);
3432                 break;
3433             case THAT:
3434                 *pS << sal_uInt8(9);
3435                 break;
3436             case TVEC:
3437                 *pS << sal_uInt8(11);
3438                 break;
3439             case TOVERSTRIKE:
3440                 *pS << sal_uInt8(16);
3441                 break;
3442             case TOVERLINE:
3443                 if ((pIsText->GetToken().eType == TTEXT) &&
3444                     (pIsText->GetText().Len() == 1))
3445                     *pS << sal_uInt8(17);
3446                 break;
3447             case TBREVE:
3448                 *pS << sal_uInt8(20);
3449                 break;
3450             case TWIDEVEC:
3451             case TUNDERLINE:
3452             case TWIDETILDE:
3453             case TWIDEHAT:
3454                 break;
3455             case TBAR:
3456                 *pS << sal_uInt8(17);
3457                 break;
3458             default:
3459                 *pS << sal_uInt8(0x2);
3460                 break;
3461             }
3462         pS->Seek(nPos);
3463         }
3464     }
3465 }
3466 
HandleText(SmNode * pNode,int)3467 void MathType::HandleText(SmNode *pNode, int /*nLevel*/)
3468 {
3469     SmTextNode *pTemp=(SmTextNode *)pNode;
3470     for(xub_StrLen i=0;i<pTemp->GetText().Len();i++)
3471     {
3472         if ((nPendingAttributes) &&
3473             (i == ((pTemp->GetText().Len()+1)/2)-1))
3474         {
3475             *pS << sal_uInt8(0x22);     //char, with attributes right
3476                                 //after the character
3477         }
3478         else
3479             *pS << sal_uInt8(CHAR);
3480             //*pS << sal_uInt8(CHAR|0x10); //char with formula recognition
3481 
3482 #if 1
3483         sal_uInt8 nFace = 0x1;
3484         if (pNode->GetFont().GetItalic() == ITALIC_NORMAL)
3485             nFace = 0x3;
3486         else if (pNode->GetFont().GetWeight() == WEIGHT_BOLD)
3487             nFace = 0x7;
3488         *pS << sal_uInt8(nFace+128); //typeface
3489 #else
3490         if ((pTemp->GetText().GetChar(i) >= '0') &&
3491             (pTemp->GetText().GetChar(i) <= '9'))
3492             *pS << sal_uInt8(0x8+128); //typeface
3493         else
3494             *pS << sal_uInt8(0x3+128); //typeface
3495 #endif
3496         sal_uInt16 nChar = pTemp->GetText().GetChar(i);
3497         *pS << Convert(nChar);
3498 
3499         //Mathtype can only have these sort of character
3500         //attributes on a single character, starmath can put them
3501         //anywhere, when the entity involved is a text run this is
3502         //a large effort to place the character attribute on the
3503         //central mathtype character so that it does pretty much
3504         //what the user probably has in mind. The attributes
3505         //filled in here are dummy ones which are replaced in the
3506         //ATTRIBUT handler if a suitable location for the
3507         //attributes was found here. Unfortunately it is
3508         //possible for starmath to place character attributes on
3509         //entities which cannot occur in mathtype e.g. a Summation
3510         //symbol so these attributes may be lost
3511         if ((nPendingAttributes) &&
3512             (i == ((pTemp->GetText().Len()+1)/2)-1))
3513         {
3514             *pS << sal_uInt8(EMBEL);
3515             while (nPendingAttributes)
3516             {
3517                 *pS << sal_uInt8(2);
3518                 //wedge the attributes in here and clear
3519                 //the pending stack
3520                 nPendingAttributes--;
3521             }
3522             nInsertion=pS->Tell();
3523             *pS << sal_uInt8(END); //end embel
3524             *pS << sal_uInt8(END); //end embel
3525         }
3526     }
3527 }
3528 
3529 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
3530