xref: /aoo41x/main/starmath/source/mathtype.cxx (revision d107581f)
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