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