Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / starmath / source / mathtype.cxx
blob611ea68d3019fdfc2336513a9683f30951fc46d9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "mathtype.hxx"
22 #include <filter/msfilter/classids.hxx>
23 #include <osl/diagnose.h>
24 #include <sfx2/docfile.hxx>
25 #include <sot/storage.hxx>
27 #include "eqnolefilehdr.hxx"
28 #include <node.hxx>
30 void MathType::Init()
32 //These are the default MathType sizes
33 aSizeTable.push_back(12);
34 aSizeTable.push_back(8);
35 aSizeTable.push_back(6);
36 aSizeTable.push_back(24);
37 aSizeTable.push_back(10);
38 aSizeTable.push_back(12);
39 aSizeTable.push_back(12);
42 These are the default MathType italic/bold settings If mathtype is changed
43 from its defaults, there is nothing we can do, as this information is not
44 stored in the document
46 MathTypeFont aFont;
47 for(sal_uInt8 i=1;i<=11;i++)
49 aFont.nTface = i+128;
50 switch (i)
52 default:
53 aFont.nStyle=0;
54 break;
55 case 3:
56 case 4:
57 aFont.nStyle=1;
58 break;
59 case 7:
60 aFont.nStyle=2;
61 break;
63 aUserStyles.insert(aFont);
68 /*ToDo replace with table rather than switch, returns
69 sal_True in the case that the char is just a char, and
70 sal_False if the character is an operator which must not be
71 placed inside the quote sequence designed to protect
72 against being parsed as a keyword
74 General solution required to force starmath to handle
75 unicode math chars the way it handles its own math
76 chars rather than handle them as text as it will do
77 for the default case below, i.e. incorrect spacing
78 between math symbols and ordinary text e.g. 1=2 rather
79 than 1 = 2
81 bool MathType::LookupChar(sal_Unicode nChar,OUStringBuffer &rRet,sal_uInt8 nVersion,
82 sal_uInt8 nTypeFace)
84 bool bRet=false;
85 const char *pC = nullptr;
86 switch(nChar)
88 case 0x0000:
89 pC = " none ";
90 break;
91 case 0x00ac:
92 pC = " neg ";
93 break;
94 case 0x00b1:
95 pC = " +- ";
96 break;
97 case '(':
98 pC = " \\( ";
99 break;
100 case ')':
101 pC = " \\) ";
102 break;
103 case '[':
104 pC = " \\[ ";
105 break;
106 case ']':
107 pC = " \\] ";
108 break;
109 case '.':
110 pC = " \".\" ";
111 break;
112 case 0xae:
113 if ((nVersion < 3) && (nTypeFace == 0x86))
114 pC = " rightarrow ";
115 else
117 rRet.append(OUStringLiteral1(nChar));
118 bRet=true;
120 break;
121 case 0x00fb:
122 if ((nVersion < 3) && (nTypeFace == 0x81))
123 nChar = 0xDF;
124 rRet.append(OUStringLiteral1(nChar));
125 bRet=true;
126 break;
127 case 'a':
128 if ((nVersion < 3) && (nTypeFace == 0x84))
129 nChar = 0x3b1;
130 rRet.append(OUStringLiteral1(nChar));
131 bRet=true;
132 break;
133 case 'b':
134 if ((nVersion < 3) && (nTypeFace == 0x84))
135 nChar = 0x3b2;
136 rRet.append(OUStringLiteral1(nChar));
137 bRet=true;
138 break;
139 case 'l':
140 if ((nVersion < 3) && (nTypeFace == 0x84))
141 nChar = 0x3bb;
142 rRet.append(OUStringLiteral1(nChar));
143 bRet=true;
144 break;
145 case 'n':
146 if ((nVersion < 3) && (nTypeFace == 0x84))
147 nChar = 0x3bd;
148 rRet.append(OUStringLiteral1(nChar));
149 bRet=true;
150 break;
151 case 'r':
152 if ((nVersion < 3) && (nTypeFace == 0x84))
153 nChar = 0x3c1;
154 rRet.append(OUStringLiteral1(nChar));
155 bRet=true;
156 break;
157 case 'D':
158 if ((nVersion < 3) && (nTypeFace == 0x84))
159 nChar = 0x394;
160 rRet.append(OUStringLiteral1(nChar));
161 bRet=true;
162 break;
163 case 0xa9:
164 if ((nVersion < 3) && (nTypeFace == 0x82))
165 nChar = '\'';
166 rRet.append(OUStringLiteral1(nChar));
167 bRet=true;
168 break;
169 case 0x00f1:
170 if ((nVersion < 3) && (nTypeFace == 0x86))
171 pC = " \\rangle ";
172 else
174 rRet.append(OUStringLiteral1(nChar));
175 bRet=true;
177 break;
178 case 0x00a3:
179 if ((nVersion < 3) && (nTypeFace == 0x86))
180 pC = " <= ";
181 else
183 rRet.append(OUStringLiteral1(nChar));
184 bRet=true;
186 break;
187 case 0x00de:
188 if ((nVersion < 3) && (nTypeFace == 0x86))
189 pC = " drarrow ";
190 else
192 rRet.append(OUStringLiteral1(nChar));
193 bRet=true;
195 break;
196 case 0x0057:
197 if ((nVersion < 3) && (nTypeFace == 0x85))
198 pC = " %OMEGA ";
199 else
201 rRet.append(OUStringLiteral1(nChar));
202 bRet=true;
204 break;
205 case 0x007b:
206 pC = " lbrace ";
207 break;
208 case 0x007c:
209 pC = " \\lline ";
210 break;
211 case 0x007d:
212 pC = " rbrace ";
213 break;
214 case 0x007e:
215 pC = " \"~\" ";
216 break;
217 case 0x2224:
218 pC = " ndivides ";
219 break;
220 case 0x2225:
221 pC = " parallel ";
222 break;
223 case 0x00d7:
224 if (nVersion < 3)
225 pC = " cdot ";
226 else
227 pC = " times ";
228 break;
229 case 0x00f7:
230 pC = " div ";
231 break;
232 case 0x019b:
233 pC = " lambdabar ";
234 break;
235 case 0x2026:
236 pC = " dotslow ";
237 break;
238 case 0x2022:
239 pC = " cdot ";
240 break;
241 case 0x2102:
242 pC = " setC ";
243 break;
244 case 0x210f:
245 pC = " hbar ";
246 break;
247 case 0x2111:
248 pC = " Im ";
249 break;
250 case 0x2115:
251 pC = " setN ";
252 break;
253 case 0x2118:
254 pC = " wp ";
255 break;
256 case 0x211a:
257 pC = " setQ ";
258 break;
259 case 0x211c:
260 pC = " Re ";
261 break;
262 case 0x211d:
263 pC = " setR ";
264 break;
265 case 0x2124:
266 pC = " setZ ";
267 break;
268 case 0x2135:
269 pC = " aleph ";
270 break;
271 case 0x2190:
272 pC = " leftarrow ";
273 break;
274 case 0x2191:
275 pC = " uparrow ";
276 break;
277 case 0x2192:
278 pC = " rightarrow ";
279 break;
280 case 0x0362:
281 pC = " widevec ";
282 break;
283 case 0x2193:
284 pC = " downarrow ";
285 break;
286 case 0x21d0:
287 pC = " dlarrow ";
288 break;
289 case 0x21d2:
290 pC = " drarrow ";
291 break;
292 case 0x21d4:
293 pC = " dlrarrow ";
294 break;
295 case 0x2200:
296 pC = " forall ";
297 break;
298 case 0x2202:
299 pC = " partial ";
300 break;
301 case 0x2203:
302 pC = " exists ";
303 break;
304 case 0x2204:
305 pC = " notexists ";
306 break;
307 case 0x2205:
308 pC = " emptyset ";
309 break;
310 case 0x2207:
311 pC = " nabla ";
312 break;
313 case 0x2208:
314 pC = " in ";
315 break;
316 case 0x2209:
317 pC = " notin ";
318 break;
319 case 0x220d:
320 pC = " owns ";
321 break;
322 case 0x220f:
323 pC = " prod ";
324 break;
325 case 0x2210:
326 pC = " coprod ";
327 break;
328 case 0x2211:
329 pC = " sum ";
330 break;
331 case 0x2212:
332 pC = " - ";
333 break;
334 case 0x2213:
335 pC = " -+ ";
336 break;
337 case 0x2217:
338 pC = " * ";
339 break;
340 case 0x2218:
341 pC = " circ ";
342 break;
343 case 0x221d:
344 pC = " prop ";
345 break;
346 case 0x221e:
347 pC = " infinity ";
348 break;
349 case 0x2227:
350 pC = " and ";
351 break;
352 case 0x2228:
353 pC = " or ";
354 break;
355 case 0x2229:
356 pC = " intersection ";
357 break;
358 case 0x222a:
359 pC = " union ";
360 break;
361 case 0x222b:
362 pC = " int ";
363 break;
364 case 0x222c:
365 pC = " iint ";
366 break;
367 case 0x222d:
368 pC = " iiint ";
369 break;
370 case 0x222e:
371 pC = " lint ";
372 break;
373 case 0x222f:
374 pC = " llint ";
375 break;
376 case 0x2230:
377 pC = " lllint ";
378 break;
379 case 0x2245:
380 pC = " simeq ";
381 break;
382 case 0x2248:
383 pC = " approx ";
384 break;
385 case 0x2260:
386 pC = " <> ";
387 break;
388 case 0x2261:
389 pC = " equiv ";
390 break;
391 case 0x2264:
392 pC = " <= ";
393 break;
394 case 0x2265:
395 pC = " >= ";
396 break;
398 case 0x227A:
399 pC = " prec ";
400 break;
401 case 0x227B:
402 pC = " succ ";
403 break;
404 case 0x227C:
405 pC = " preccurlyeq ";
406 break;
407 case 0x227D:
408 pC = " succcurlyeq ";
409 break;
410 case 0x227E:
411 pC = " precsim ";
412 break;
413 case 0x227F:
414 pC = " succsim ";
415 break;
416 case 0x2280:
417 pC = " nprec ";
418 break;
419 case 0x2281:
420 pC = " nsucc ";
421 break;
423 case 0x2282:
424 pC = " subset ";
425 break;
426 case 0x2283:
427 pC = " supset ";
428 break;
429 case 0x2284:
430 pC = " nsubset ";
431 break;
432 case 0x2285:
433 pC = " nsupset ";
434 break;
435 case 0x2286:
436 pC = " subseteq ";
437 break;
438 case 0x2287:
439 pC = " supseteq ";
440 break;
441 case 0x2288:
442 pC = " nsubseteq ";
443 break;
444 case 0x2289:
445 pC = " nsupseteq ";
446 break;
447 case 0x22b2:
448 case 0x22b3:
449 rRet.append(" ").append(OUStringLiteral1(nChar)).append(" ");
450 break;
451 case 0x22a5:
452 pC = " ortho ";
453 break;
454 case 0x22c5:
455 pC = " cdot ";
456 break;
457 case 0x22ee:
458 pC = " dotsvert ";
459 break;
460 case 0x22ef:
461 pC = " dotsaxis ";
462 break;
463 case 0x22f0:
464 pC = " dotsup ";
465 break;
466 case 0x22f1:
467 pC = " dotsdown ";
468 break;
469 case MS_LANGLE:
470 case MS_LMATHANGLE:
471 pC = " langle ";
472 break;
473 case MS_RANGLE:
474 case MS_RMATHANGLE:
475 pC = " rangle ";
476 break;
477 case 0x301a:
478 pC = " ldbracket ";
479 break;
480 case 0x301b:
481 pC = " rdbracket ";
482 break;
483 case 0xe083:
484 rRet.append("+");
485 bRet=true;
486 break;
487 case '^':
488 case 0xe091:
489 pC = " widehat ";
490 break;
491 case 0xe096:
492 pC = " widetilde ";
493 break;
494 case 0xe098:
495 pC = " widevec ";
496 break;
497 case 0xE421:
498 pC = " geslant ";
499 break;
500 case 0xE425:
501 pC = " leslant ";
502 break;
503 case 0xeb01: //no space
504 case 0xeb08: //normal space
505 bRet=true;
506 break;
507 case 0xef04: //tiny space
508 case 0xef05: //tiny space
509 case 0xeb02: //small space
510 case 0xeb04: //medium space
511 rRet.append("`");
512 break;
513 case 0xeb05: //large space
514 rRet.append("~");
515 break;
516 case 0x3a9:
517 pC = " %OMEGA ";
518 break;
519 default:
520 rRet.append(OUStringLiteral1(nChar));
521 bRet=true;
522 break;
524 if (pC)
525 rRet.appendAscii(pC);
526 return bRet;
529 void MathTypeFont::AppendStyleToText(OUString &rRet)
531 const char *pC = nullptr;
532 switch (nStyle)
534 default:
535 case 0:
536 break;
537 case 1:
538 pC = " ital ";
539 break;
540 case 2:
541 pC = " bold ";
542 break;
543 case 3:
544 pC = " bold italic";
545 break;
547 if (pC)
548 rRet += OUString::createFromAscii( pC );
551 void MathType::TypeFaceToString(OUString &rTxt,sal_uInt8 nFace)
553 MathTypeFont aFont(nFace);
554 MathTypeFontSet::iterator aItr = aUserStyles.find(aFont);
555 if (aItr != aUserStyles.end())
556 aFont.nStyle = aItr->nStyle;
557 aFont.AppendStyleToText(rTxt);
560 bool MathType::Parse(SotStorage *pStor)
562 tools::SvRef<SotStorageStream> xSrc = pStor->OpenSotStream(
563 "Equation Native",
564 StreamMode::STD_READ);
565 if ( (!xSrc.is()) || (ERRCODE_NONE != xSrc->GetError()))
566 return false;
567 return Parse(xSrc.get());
570 bool MathType::Parse(SvStream* pStream)
572 pS = pStream;
573 pS->SetEndian( SvStreamEndian::LITTLE );
575 EQNOLEFILEHDR aHdr;
576 aHdr.Read(pS);
577 sal_uInt8 nProdVersion;
578 sal_uInt8 nProdSubVersion;
579 sal_uInt8 nPlatform;
580 sal_uInt8 nProduct;
581 pS->ReadUChar( nVersion );
582 pS->ReadUChar( nPlatform );
583 pS->ReadUChar( nProduct );
584 pS->ReadUChar( nProdVersion );
585 pS->ReadUChar( nProdSubVersion );
587 if (nVersion > 3) // allow only supported versions of MathType to be parsed
588 return false;
590 bool bRet = HandleRecords(0);
591 //little crude hack to close occasionally open expressions
592 //a sophisticated system to determine what expressions are
593 //opened is required, but this is as much work as rewriting
594 //starmaths internals.
595 rRet.append("{}");
597 return bRet;
600 static void lcl_PrependDummyTerm(OUStringBuffer &rRet, sal_Int32 &rTextStart)
602 if ((rTextStart < rRet.getLength()) &&
603 (rRet[rTextStart] == '=') &&
604 ((rTextStart == 0) || (rRet[ rTextStart-1 ] == '{'))
607 rRet.insert(rTextStart, " {}");
608 rTextStart+=3;
612 static void lcl_AppendDummyTerm(OUStringBuffer &rRet)
614 bool bOk=false;
615 for(int nI=rRet.getLength()-1;nI >= 0; nI--)
617 sal_Int32 nIdx = sal::static_int_cast< sal_Int32 >(nI);
618 sal_Unicode nChar = rRet[nIdx];
619 if (nChar == ' ')
620 continue;
621 if (rRet[nIdx] != '{')
622 bOk=true;
623 break;
625 if (!bOk) //No term, use dummy
626 rRet.append(" {}");
629 void MathType::HandleNudge()
631 sal_uInt8 nXNudge;
632 pS->ReadUChar( nXNudge );
633 sal_uInt8 nYNudge;
634 pS->ReadUChar( nYNudge );
635 if (nXNudge == 128 && nYNudge == 128)
637 sal_uInt16 nXLongNudge;
638 sal_uInt16 nYLongNudge;
639 pS->ReadUInt16( nXLongNudge );
640 pS->ReadUInt16( nYLongNudge );
644 /* Fabulously complicated as many tokens have to be reordered and generally
645 * moved around from mathtypes paradigm to starmaths. */
646 bool MathType::HandleRecords(int nLevel, sal_uInt8 nSelector,
647 sal_uInt8 nVariation, int nMatrixRows, int nMatrixCols)
649 //depth-protect
650 if (nLevel > 1024)
651 return false;
653 sal_uInt8 nTag,nRecord;
654 sal_uInt8 nTabType,nTabStops;
655 sal_uInt16 nTabOffset;
656 int i, newline=0;
657 bool bSilent=false;
658 int nPart=0;
659 OUString sPush,sMainTerm;
660 int nSetSize=0,nSetAlign=0;
661 int nCurRow=0,nCurCol=0;
662 bool bOpenString=false;
663 sal_Int32 nTextStart = 0;
664 sal_Int32 nSubSupStartPos = 0;
665 sal_Int32 nLastTemplateBracket=-1;
666 bool bRet = true;
670 nTag = 0;
671 pS->ReadUChar( nTag );
672 nRecord = nTag&0x0F;
674 /*MathType strings can of course include words which
675 *are StarMath keywords, the simplest solution is
676 to escape strings of greater than len 1 with double
677 quotes to avoid scanning the TokenTable for matches
679 Unfortunately it may turn out that the string gets
680 split during the handling of a character emblishment
681 so this special case must be handled in the
682 character handler case 2:
684 if ((nRecord == CHAR) && (!bOpenString))
686 bOpenString=true;
687 nTextStart = rRet.getLength();
689 else if ((nRecord != CHAR) && bOpenString)
691 bOpenString=false;
692 if ((rRet.getLength() - nTextStart) > 1)
694 OUString aStr;
695 TypeFaceToString(aStr,nTypeFace);
696 aStr += "\"";
697 rRet.insert(nTextStart,aStr);
698 rRet.append("\"");
700 else if (nRecord == END && !rRet.isEmpty())
702 sal_Unicode cChar = 0;
703 sal_Int32 nI = rRet.getLength()-1;
704 while (nI && ((cChar = rRet[nI]) == ' '))
705 --nI;
706 if ((cChar == '=') || (cChar == '+') || (cChar == '-'))
707 rRet.append("{}");
711 switch(nRecord)
713 case LINE:
715 if (xfLMOVE(nTag))
716 HandleNudge();
718 if (newline>0)
719 rRet.append("\nnewline\n");
720 if (!(xfNULL(nTag)))
722 switch (nSelector)
724 case tmANGLE:
725 if (nVariation==0)
726 rRet.append(" langle ");
727 else if (nVariation==1)
728 rRet.append(" \\langle ");
729 break;
730 case tmPAREN:
731 if (nVariation==0)
732 rRet.append(" left (");
733 else if (nVariation==1)
734 rRet.append("\\(");
735 break;
736 case tmBRACE:
737 if ((nVariation==0) || (nVariation==1))
738 rRet.append(" left lbrace ");
739 else
740 rRet.append(" left none ");
741 break;
742 case tmBRACK:
743 if (nVariation==0)
744 rRet.append(" left [");
745 else if (nVariation==1)
746 rRet.append("\\[");
747 break;
748 case tmLBLB:
749 case tmLBRP:
750 rRet.append(" \\[");
751 break;
752 case tmBAR:
753 if (nVariation==0)
754 rRet.append(" lline ");
755 else if (nVariation==1)
756 rRet.append(" \\lline ");
757 break;
758 case tmDBAR:
759 if (nVariation==0)
760 rRet.append(" ldline ");
761 else if (nVariation==1)
762 rRet.append(" \\ldline ");
763 break;
764 case tmFLOOR:
765 if (nVariation == 0 || nVariation == 1)
766 rRet.append(" left lfloor ");
767 else if (nVariation==1)
768 rRet.append(" left none ");
769 break;
770 case tmCEILING:
771 if (nVariation==0)
772 rRet.append(" lceil ");
773 else if (nVariation==1)
774 rRet.append(" \\lceil ");
775 break;
776 case tmRBRB:
777 case tmRBLB:
778 rRet.append(" \\]");
779 break;
780 case tmLPRB:
781 rRet.append(" \\(");
782 break;
783 case tmROOT:
784 if (nPart == 0)
786 if (nVariation == 0)
787 rRet.append(" sqrt");
788 else
790 rRet.append(" nroot");
791 sPush = rRet.makeStringAndClear();
794 rRet.append(" {");
795 break;
796 case tmFRACT:
797 if (nPart == 0)
798 rRet.append(" { ");
801 if (nPart == 1)
802 rRet.append(" over ");
803 rRet.append(" {");
804 break;
805 case tmSCRIPT:
806 nSubSupStartPos = rRet.getLength();
807 if ((nVariation == 0) ||
808 ((nVariation == 2) && (nPart==1)))
810 lcl_AppendDummyTerm(rRet);
811 rRet.append(" rSup");
813 else if ((nVariation == 1) ||
814 ((nVariation == 2) && (nPart==0)))
816 lcl_AppendDummyTerm(rRet);
817 rRet.append(" rSub");
819 rRet.append(" {");
820 break;
821 case tmUBAR:
822 if (nVariation == 0)
823 rRet.append(" {underline ");
824 else if (nVariation == 1)
825 rRet.append(" {underline underline ");
826 rRet.append(" {");
827 break;
828 case tmOBAR:
829 if (nVariation == 0)
830 rRet.append(" {overline ");
831 else if (nVariation == 1)
832 rRet.append(" {overline overline ");
833 rRet.append(" {");
834 break;
835 case tmLARROW:
836 if (nPart == 0)
838 if (nVariation == 0)
839 rRet.append(" widevec ");//left arrow above
840 else if (nVariation == 1)
841 rRet.append(" widevec ");//left arrow below
842 rRet.append(" {");
844 break;
845 case tmRARROW:
846 if (nPart == 0)
848 if (nVariation == 0)
849 rRet.append(" widevec ");//right arrow above
850 else if (nVariation == 1)
851 rRet.append(" widevec ");//right arrow below
852 rRet.append(" {");
854 break;
855 case tmBARROW:
856 if (nPart == 0)
858 if (nVariation == 0)
859 rRet.append(" widevec ");//double arrow above
860 else if (nVariation == 1)
861 rRet.append(" widevec ");//double arrow below
862 rRet.append(" {");
864 break;
865 case tmSINT:
866 if (nPart == 0)
868 if ((nVariation == 3) || (nVariation == 4))
869 rRet.append(" lInt");
870 else
871 rRet.append(" Int");
872 if ( (nVariation != 0) && (nVariation != 3))
874 sPush = rRet.makeStringAndClear();
877 if (((nVariation == 1) ||
878 (nVariation == 4)) && (nPart==1))
879 rRet.append(" rSub");
880 else if ((nVariation == 2) && (nPart==2))
881 rRet.append(" rSup");
882 else if ((nVariation == 2) && (nPart==1))
883 rRet.append(" rSub");
884 rRet.append(" {");
885 break;
886 case tmDINT:
887 if (nPart == 0)
889 if ((nVariation == 2) || (nVariation == 3))
890 rRet.append(" llInt");
891 else
892 rRet.append(" iInt");
893 if ( (nVariation != 0) && (nVariation != 2))
895 sPush = rRet.makeStringAndClear();
898 if (((nVariation == 1) ||
899 (nVariation == 3)) && (nPart==1))
900 rRet.append(" rSub");
901 rRet.append(" {");
902 break;
903 case tmTINT:
904 if (nPart == 0)
906 if ((nVariation == 2) || (nVariation == 3))
907 rRet.append(" lllInt");
908 else
909 rRet.append(" iiInt");
910 if ( (nVariation != 0) && (nVariation != 2))
912 sPush = rRet.makeStringAndClear();
915 if (((nVariation == 1) ||
916 (nVariation == 3)) && (nPart==1))
917 rRet.append(" rSub");
918 rRet.append(" {");
919 break;
920 case tmSSINT:
921 if (nPart == 0)
923 if (nVariation == 2)
924 rRet.append(" lInt");
925 else
926 rRet.append(" Int");
927 sPush = rRet.makeStringAndClear();
929 if (((nVariation == 1) ||
930 (nVariation == 2)) && (nPart==1))
931 rRet.append(" cSub");
932 else if ((nVariation == 0) && (nPart==2))
933 rRet.append(" cSup");
934 else if ((nVariation == 0) && (nPart==1))
935 rRet.append(" cSub");
936 rRet.append(" {");
937 break;
938 case tmDSINT:
939 if (nPart == 0)
941 if (nVariation == 0)
942 rRet.append(" llInt");
943 else
944 rRet.append(" iInt");
945 sPush = rRet.makeStringAndClear();
947 if (nPart==1)
948 rRet.append(" cSub");
949 rRet.append(" {");
950 break;
951 case tmTSINT:
952 if (nPart == 0)
954 if (nVariation == 0)
955 rRet.append(" lllInt");
956 else
957 rRet.append(" iiInt");
958 sPush = rRet.makeStringAndClear();
960 if (nPart==1)
961 rRet.append(" cSub");
962 rRet.append(" {");
963 break;
964 case tmUHBRACE:
965 case tmLHBRACE:
966 rRet.append(" {");
967 break;
968 case tmSUM:
969 if (nPart == 0)
971 rRet.append(" Sum");
972 if (nVariation != 2)
974 sPush = rRet.makeStringAndClear();
977 if ((nVariation == 0) && (nPart==1))
978 rRet.append(" cSub");
979 else if ((nVariation == 1) && (nPart==2))
980 rRet.append(" cSup");
981 else if ((nVariation == 1) && (nPart==1))
982 rRet.append(" cSub");
983 rRet.append(" {");
984 break;
985 case tmISUM:
986 if (nPart == 0)
988 rRet.append(" Sum");
989 sPush = rRet.makeStringAndClear();
991 if ((nVariation == 0) && (nPart==1))
992 rRet.append(" rSub");
993 else if ((nVariation == 1) && (nPart==2))
994 rRet.append(" rSup");
995 else if ((nVariation == 1) && (nPart==1))
996 rRet.append(" rSub");
997 rRet.append(" {");
998 break;
999 case tmPROD:
1000 if (nPart == 0)
1002 rRet.append(" Prod");
1003 if (nVariation != 2)
1005 sPush = rRet.makeStringAndClear();
1008 if ((nVariation == 0) && (nPart==1))
1009 rRet.append(" cSub");
1010 else if ((nVariation == 1) && (nPart==2))
1011 rRet.append(" cSup");
1012 else if ((nVariation == 1) && (nPart==1))
1013 rRet.append(" cSub");
1014 rRet.append(" {");
1015 break;
1016 case tmIPROD:
1017 if (nPart == 0)
1019 rRet.append(" Prod");
1020 sPush = rRet.makeStringAndClear();
1022 if ((nVariation == 0) && (nPart==1))
1023 rRet.append(" rSub");
1024 else if ((nVariation == 1) && (nPart==2))
1025 rRet.append(" rSup");
1026 else if ((nVariation == 1) && (nPart==1))
1027 rRet.append(" rSub");
1028 rRet.append(" {");
1029 break;
1030 case tmCOPROD:
1031 if (nPart == 0)
1033 rRet.append(" coProd");
1034 if (nVariation != 2)
1036 sPush = rRet.makeStringAndClear();
1039 if ((nVariation == 0) && (nPart==1))
1040 rRet.append(" cSub");
1041 else if ((nVariation == 1) && (nPart==2))
1042 rRet.append(" cSup");
1043 else if ((nVariation == 1) && (nPart==1))
1044 rRet.append(" cSub");
1045 rRet.append(" {");
1046 break;
1047 case tmICOPROD:
1048 if (nPart == 0)
1050 rRet.append(" coProd");
1051 sPush = rRet.makeStringAndClear();
1053 if ((nVariation == 0) && (nPart==1))
1054 rRet.append(" rSub");
1055 else if ((nVariation == 1) && (nPart==2))
1056 rRet.append(" rSup");
1057 else if ((nVariation == 1) && (nPart==1))
1058 rRet.append(" rSub");
1059 rRet.append(" {");
1060 break;
1061 case tmUNION:
1062 if (nPart == 0)
1064 rRet.append(" union"); //union
1065 if (nVariation != 2)
1067 sPush = rRet.makeStringAndClear();
1070 if ((nVariation == 0) && (nPart==1))
1071 rRet.append(" cSub");
1072 else if ((nVariation == 1) && (nPart==2))
1073 rRet.append(" cSup");
1074 else if ((nVariation == 1) && (nPart==1))
1075 rRet.append(" cSub");
1076 rRet.append(" {");
1077 break;
1078 case tmIUNION:
1079 if (nPart == 0)
1081 rRet.append(" union"); //union
1082 sPush = rRet.makeStringAndClear();
1084 if ((nVariation == 0) && (nPart==1))
1085 rRet.append(" rSub");
1086 else if ((nVariation == 1) && (nPart==2))
1087 rRet.append(" rSup");
1088 else if ((nVariation == 1) && (nPart==1))
1089 rRet.append(" rSub");
1090 rRet.append(" {");
1091 break;
1092 case tmINTER:
1093 if (nPart == 0)
1095 rRet.append(" intersect"); //intersect
1096 if (nVariation != 2)
1098 sPush = rRet.makeStringAndClear();
1101 if ((nVariation == 0) && (nPart==1))
1102 rRet.append(" cSub");
1103 else if ((nVariation == 1) && (nPart==2))
1104 rRet.append(" cSup");
1105 else if ((nVariation == 1) && (nPart==1))
1106 rRet.append(" cSub");
1107 rRet.append(" {");
1108 break;
1109 case tmIINTER:
1110 if (nPart == 0)
1112 rRet.append(" intersect"); //intersect
1113 sPush = rRet.makeStringAndClear();
1115 if ((nVariation == 0) && (nPart==1))
1116 rRet.append(" rSub");
1117 else if ((nVariation == 1) && (nPart==2))
1118 rRet.append(" rSup");
1119 else if ((nVariation == 1) && (nPart==1))
1120 rRet.append(" rSub");
1121 rRet.append(" {");
1122 break;
1123 case tmLIM:
1124 if ((nVariation == 0) && (nPart==1))
1125 rRet.append(" cSup");
1126 else if ((nVariation == 1) && (nPart==1))
1127 rRet.append(" cSub");
1128 else if ((nVariation == 2) && (nPart==1))
1129 rRet.append(" cSub");
1130 else if ((nVariation == 2) && (nPart==2))
1131 rRet.append(" cSup");
1132 rRet.append(" {");
1133 break;
1134 case tmLDIV:
1135 if (nVariation == 0)
1137 if (nPart == 0)
1139 sPush = rRet.makeStringAndClear();
1142 rRet.append(" {");
1143 if (nVariation == 0)
1145 if (nPart == 1)
1146 rRet.append("alignr ");
1148 if (nPart == 0)
1149 rRet.append("\\lline ");
1150 if (nVariation == 1)
1151 rRet.append("overline ");
1152 break;
1153 case tmSLFRACT:
1154 rRet.append(" {");
1155 break;
1156 case tmINTOP:
1157 if (nPart == 0)
1159 sPush = rRet.makeStringAndClear();
1161 if ((nVariation == 0) && (nPart==0))
1162 rRet.append(" rSup");
1163 else if ((nVariation == 2) && (nPart==1))
1164 rRet.append(" rSup");
1165 else if ((nVariation == 1) && (nPart==0))
1166 rRet.append(" rSub");
1167 else if ((nVariation == 2) && (nPart==0))
1168 rRet.append(" rSub");
1169 rRet.append(" {");
1170 break;
1171 case tmSUMOP:
1172 if (nPart == 0)
1174 sPush = rRet.makeStringAndClear();
1176 if ((nVariation == 0) && (nPart==0))
1177 rRet.append(" cSup");
1178 else if ((nVariation == 2) && (nPart==1))
1179 rRet.append(" cSup");
1180 else if ((nVariation == 1) && (nPart==0))
1181 rRet.append(" cSub");
1182 else if ((nVariation == 2) && (nPart==0))
1183 rRet.append(" cSub");
1184 rRet.append(" {");
1185 break;
1186 case tmLSCRIPT:
1187 if (nPart == 0)
1188 rRet.append("\"\"");
1189 if ((nVariation == 0)
1190 || ((nVariation == 2) && (nPart==1)))
1191 rRet.append(" lSup");
1192 else if ((nVariation == 1)
1193 || ((nVariation == 2) && (nPart==0)))
1194 rRet.append(" lSub");
1195 rRet.append(" {");
1196 break;
1197 case tmDIRAC:
1198 if (nVariation==0)
1200 if (nPart == 0)
1201 rRet.append(" langle ");
1203 else if (nVariation==1)
1205 rRet.append(" \\langle ");
1206 newline--;
1208 else if (nVariation==2)
1210 rRet.append(" \\lline ");
1211 newline--;
1213 break;
1214 case tmUARROW:
1215 if (nVariation == 0)
1216 rRet.append(" widevec ");//left below
1217 else if (nVariation == 1)
1218 rRet.append(" widevec ");//right below
1219 else if (nVariation == 2)
1220 rRet.append(" widevec ");//double headed below
1221 rRet.append(" {");
1222 break;
1223 case tmOARROW:
1224 if (nVariation == 0)
1225 rRet.append(" widevec ");//left above
1226 else if (nVariation == 1)
1227 rRet.append(" widevec ");//right above
1228 else if (nVariation == 2)
1229 rRet.append(" widevec ");//double headed above
1230 rRet.append(" {");
1231 break;
1232 default:
1233 break;
1235 sal_Int16 nOldCurSize=nCurSize;
1236 sal_Int32 nSizeStartPos = rRet.getLength();
1237 HandleSize( nLSize, nDSize, nSetSize );
1238 bRet = HandleRecords( nLevel+1 );
1239 while (nSetSize)
1241 bool bOk=false;
1242 sal_Int32 nI = rRet.lastIndexOf('{');
1243 if (nI != -1)
1245 for(nI=nI+1;nI<rRet.getLength();nI++)
1246 if (rRet[nI] != ' ')
1248 bOk=true;
1249 break;
1252 else
1253 bOk=true;
1255 if (bOk)
1256 rRet.append("} ");
1257 else if (rRet.getLength() > nSizeStartPos)
1258 rRet = rRet.truncate(nSizeStartPos);
1259 nSetSize--;
1260 nCurSize=nOldCurSize;
1264 HandleMatrixSeparator(nMatrixRows,nMatrixCols,
1265 nCurCol,nCurRow);
1267 switch (nSelector)
1269 case tmANGLE:
1270 if (nVariation==0)
1271 rRet.append(" rangle ");
1272 else if (nVariation==2)
1273 rRet.append(" \\rangle ");
1274 break;
1275 case tmPAREN:
1276 if (nVariation==0)
1277 rRet.append(" right )");
1278 else if (nVariation==2)
1279 rRet.append("\\)");
1280 break;
1281 case tmBRACE:
1282 if ((nVariation==0) || (nVariation==2))
1283 rRet.append(" right rbrace ");
1284 else
1285 rRet.append(" right none ");
1286 break;
1287 case tmBRACK:
1288 if (nVariation==0)
1289 rRet.append(" right ]");
1290 else if (nVariation==2)
1291 rRet.append("\\]");
1292 break;
1293 case tmBAR:
1294 if (nVariation==0)
1295 rRet.append(" rline ");
1296 else if (nVariation==2)
1297 rRet.append(" \\rline ");
1298 break;
1299 case tmDBAR:
1300 if (nVariation==0)
1301 rRet.append(" rdline ");
1302 else if (nVariation==2)
1303 rRet.append(" \\rdline ");
1304 break;
1305 case tmFLOOR:
1306 if (nVariation == 0 || nVariation == 2)
1307 rRet.append(" right rfloor ");
1308 else if (nVariation==2)
1309 rRet.append(" right none ");
1310 break;
1311 case tmCEILING:
1312 if (nVariation==0)
1313 rRet.append(" rceil ");
1314 else if (nVariation==2)
1315 rRet.append(" \\rceil ");
1316 break;
1317 case tmLBLB:
1318 case tmRBLB:
1319 rRet.append("\\[");
1320 break;
1321 case tmRBRB:
1322 case tmLPRB:
1323 rRet.append("\\]");
1324 break;
1325 case tmROOT:
1326 rRet.append("} ");
1327 if (nVariation == 1)
1329 if (nPart == 0)
1331 newline--;
1332 sMainTerm = rRet.makeStringAndClear();
1334 else if (nPart == 1)
1336 rRet.insert(0, sPush);
1337 rRet.append(sMainTerm);
1338 sPush.clear();
1339 sMainTerm.clear();
1342 else
1344 if (nPart == 0)
1345 newline--;
1347 nPart++;
1348 break;
1349 case tmLBRP:
1350 rRet.append("\\)");
1351 break;
1352 case tmFRACT:
1353 rRet.append("} ");
1354 if (nPart == 0)
1355 newline--;
1356 else
1357 rRet.append("} ");
1358 nPart++;
1359 break;
1360 case tmSCRIPT:
1362 if ((nPart == 0) &&
1363 ((nVariation == 2) || (nVariation == 1)))
1364 newline--;
1366 bool bOk=false;
1367 sal_Int32 nI = rRet.lastIndexOf('{');
1368 if (nI != -1)
1370 for(nI=nI+1;nI<rRet.getLength();nI++)
1371 if (rRet[nI] != ' ')
1373 bOk=true;
1374 break;
1377 else
1378 bOk=true;
1380 if (bOk)
1381 rRet.append("} ");
1382 else if (rRet.getLength() > nSubSupStartPos)
1383 rRet = rRet.truncate(nSubSupStartPos);
1384 nPart++;
1386 break;
1387 case tmLSCRIPT:
1388 if ((nPart == 0) &&
1389 ((nVariation == 2) || (nVariation == 1)))
1390 newline--;
1391 rRet.append("} ");
1392 nPart++;
1393 break;
1394 case tmUARROW:
1395 case tmOARROW:
1396 rRet.append("} ");
1397 break;
1398 case tmUBAR:
1399 case tmOBAR:
1400 rRet.append("}} ");
1401 break;
1402 case tmLARROW:
1403 case tmRARROW:
1404 case tmBARROW:
1405 if (nPart == 0)
1407 newline--;
1408 rRet.append("} ");
1410 nPart++;
1411 break;
1412 case tmUHBRACE:
1413 rRet.append("} ");
1414 if (nPart == 0)
1416 newline--;
1417 rRet.append("overbrace");
1419 nPart++;
1420 break;
1421 case tmLHBRACE:
1422 rRet.append("} ");
1423 if (nPart == 0)
1425 newline--;
1426 rRet.append("underbrace");
1428 nPart++;
1429 break;
1430 case tmLIM:
1431 if (nPart==0)
1432 newline--;
1433 else if ((nPart==1) &&
1434 ((nVariation == 2) || (nVariation == 1)))
1435 newline--;
1436 rRet.append("} ");
1437 nPart++;
1438 break;
1439 case tmLDIV:
1440 rRet.append("} ");
1441 if (nVariation == 0)
1443 if (nPart == 0)
1445 sMainTerm = rRet.makeStringAndClear();
1447 else if (nPart == 1)
1449 rRet.insert(0, sPush);
1450 rRet.append(" over ").append(sMainTerm);
1451 sPush.clear();
1452 sMainTerm.clear();
1455 if (nPart == 0)
1456 newline--;
1457 nPart++;
1458 break;
1459 case tmSLFRACT:
1460 rRet.append("} ");
1461 if (nPart == 0)
1463 newline--;
1464 switch (nVariation)
1466 case 1:
1467 rRet.append("slash");
1468 break;
1469 default:
1470 rRet.append("wideslash");
1471 break;
1474 nPart++;
1475 break;
1476 case tmSUM:
1477 case tmISUM:
1478 case tmPROD:
1479 case tmIPROD:
1480 case tmCOPROD:
1481 case tmICOPROD:
1482 case tmUNION:
1483 case tmIUNION:
1484 case tmINTER:
1485 case tmIINTER:
1486 rRet.append("} ");
1487 if (nPart == 0)
1489 if (nVariation != 2)
1491 sMainTerm = rRet.makeStringAndClear();
1493 newline--;
1495 else if ((nPart == 1) && (nVariation == 0))
1497 rRet.insert(0, sPush);
1498 rRet.append(sMainTerm);
1499 sPush.clear();
1500 sMainTerm.clear();
1501 newline--;
1503 else if ((nPart == 1) && (nVariation == 1))
1504 newline--;
1505 else if ((nPart == 2) && (nVariation == 1))
1507 rRet.insert(0, sPush);
1508 rRet.append(sMainTerm);
1509 sPush.clear();
1510 sMainTerm.clear();
1511 newline--;
1513 nPart++;
1514 break;
1515 case tmSINT:
1516 rRet.append("} ");
1517 if (nPart == 0)
1519 if ((nVariation != 0) && (nVariation != 3))
1521 sMainTerm = rRet.makeStringAndClear();
1523 newline--;
1525 else if ((nPart == 1) &&
1526 ((nVariation == 1) || (nVariation==4)))
1528 rRet.insert(0, sPush);
1529 rRet.append(sMainTerm);
1530 sPush.clear();
1531 sMainTerm.clear();
1532 newline--;
1534 else if ((nPart == 1) && (nVariation == 2))
1535 newline--;
1536 else if ((nPart == 2) && (nVariation == 2))
1538 rRet.insert(0, sPush);
1539 rRet.append(sMainTerm);
1540 sPush.clear();
1541 sMainTerm.clear();
1542 newline--;
1544 nPart++;
1545 break;
1546 case tmDINT:
1547 case tmTINT:
1548 rRet.append("} ");
1549 if (nPart == 0)
1551 if ((nVariation != 0) && (nVariation != 2))
1553 sMainTerm = rRet.makeStringAndClear();
1555 newline--;
1557 else if ((nPart == 1) &&
1558 ((nVariation == 1) || (nVariation==3)))
1560 rRet.insert(0, sPush);
1561 rRet.append(sMainTerm);
1562 sPush.clear();
1563 sMainTerm.clear();
1564 newline--;
1566 nPart++;
1567 break;
1568 case tmSSINT:
1569 rRet.append("} ");
1570 if (nPart == 0)
1572 sMainTerm = rRet.makeStringAndClear();
1573 newline--;
1575 else if ((nPart == 1) &&
1576 ((nVariation == 1) || (nVariation==2)))
1578 rRet.insert(0, sPush);
1579 rRet.append(sMainTerm);
1580 sPush.clear();
1581 sMainTerm.clear();
1582 newline--;
1584 else if ((nPart == 1) && (nVariation == 0))
1585 newline--;
1586 else if ((nPart == 2) && (nVariation == 0))
1588 rRet.insert(0, sPush);
1589 rRet.append(sMainTerm);
1590 sPush.clear();
1591 sMainTerm.clear();
1592 newline--;
1594 nPart++;
1595 break;
1596 case tmDSINT:
1597 case tmTSINT:
1598 rRet.append("} ");
1599 if (nPart == 0)
1601 sMainTerm = rRet.makeStringAndClear();
1602 newline--;
1604 else if (nPart == 1)
1606 rRet.insert(0, sPush);
1607 rRet.append(sMainTerm);
1608 sPush.clear();
1609 sMainTerm.clear();
1610 newline--;
1612 nPart++;
1613 break;
1614 case tmINTOP:
1615 case tmSUMOP:
1616 rRet.append("} ");
1618 if ((nPart == 0) &&
1619 ((nVariation == 0) || (nVariation == 1)))
1621 sMainTerm = rRet.makeStringAndClear();
1622 newline--;
1624 else if ((nPart == 0) && (nVariation == 2))
1625 newline--;
1626 else if ((nPart == 1) && (nVariation == 2))
1628 sMainTerm = rRet.makeStringAndClear();
1629 newline--;
1631 else if ((nPart == 2) || ((nPart == 1) &&
1632 (nVariation == 0 || nVariation == 1)))
1634 rRet.insert(0, sPush);
1635 rRet.append(sMainTerm);
1636 sPush.clear();
1637 sMainTerm.clear();
1639 nPart++;
1640 break;
1641 case tmDIRAC:
1642 if (nVariation==0)
1644 if (nPart == 0)
1646 newline--; //there is another term to arrive
1647 rRet.append(" mline ");
1649 else
1650 rRet.append(" rangle ");
1652 else if (nVariation==1)
1653 rRet.append(" \\lline ");
1654 else if (nVariation==2)
1655 rRet.append(" \\rangle ");
1656 nPart++;
1657 break;
1658 default:
1659 break;
1661 bSilent = true; //Skip the optional brackets and/or
1662 //symbols that follow some of these
1663 //records. Foo Data.
1665 /*In matrices and piles we cannot separate equation
1666 *lines with the newline keyword*/
1667 if (nMatrixCols==0)
1668 newline++;
1671 break;
1672 case CHAR:
1673 if (xfLMOVE(nTag))
1674 HandleNudge();
1675 bRet = HandleChar( nTextStart, nSetSize, nLevel, nTag, nSelector, nVariation, bSilent );
1676 break;
1677 case TMPL:
1678 if (xfLMOVE(nTag))
1679 HandleNudge();
1680 bRet = HandleTemplate( nLevel, nSelector, nVariation, nLastTemplateBracket );
1681 break;
1682 case PILE:
1683 if (xfLMOVE(nTag))
1684 HandleNudge();
1685 bRet = HandlePile( nSetAlign, nLevel, nSelector, nVariation );
1686 HandleMatrixSeparator( nMatrixRows, nMatrixCols, nCurCol, nCurRow );
1687 break;
1688 case MATRIX:
1689 if (xfLMOVE(nTag))
1690 HandleNudge();
1691 bRet = HandleMatrix( nLevel, nSelector, nVariation );
1692 HandleMatrixSeparator( nMatrixRows, nMatrixCols, nCurCol, nCurRow );
1693 break;
1694 case EMBEL:
1695 if (xfLMOVE(nTag))
1696 HandleNudge();
1697 HandleEmblishments();
1698 break;
1699 case RULER:
1700 pS->ReadUChar( nTabStops );
1701 for (i=0;i<nTabStops;i++)
1703 pS->ReadUChar( nTabType );
1704 pS->ReadUInt16( nTabOffset );
1706 SAL_WARN("starmath", "Not seen in the wild Equation Ruler Field");
1707 break;
1708 case FONT:
1710 MathTypeFont aFont;
1711 pS->ReadUChar( aFont.nTface );
1713 The typeface number is the negative (which makes it
1714 positive) of the typeface value (unbiased) that appears in
1715 CHAR records that might follow a given FONT record
1717 aFont.nTface = 128-aFont.nTface;
1718 pS->ReadUChar( aFont.nStyle );
1719 aUserStyles.insert(aFont);
1720 // read font name
1721 while(true)
1723 sal_Char nChar8(0);
1724 pS->ReadChar( nChar8 );
1725 if (nChar8 == 0)
1726 break;
1729 break;
1730 case SIZE:
1731 HandleSetSize();
1732 break;
1733 case 10:
1734 case 11:
1735 case 12:
1736 case 13:
1737 case 14:
1738 nLSize=nRecord-10;
1739 break;
1740 case END:
1741 default:
1742 break;
1745 while (nRecord != END && !pS->eof());
1746 while (nSetSize)
1748 rRet.append("}");
1749 nSetSize--;
1751 return bRet;
1754 /*Simply determine if we are at the end of a record or the end of a line,
1755 *with fiddly logic to see if we are in a matrix or a pile or neither
1757 Note we cannot tell until after the event that this is the last entry
1758 of a pile, so we must strip the last separator of a pile after this
1759 is detected in the PILE handler
1761 void MathType::HandleMatrixSeparator(int nMatrixRows,int nMatrixCols,
1762 int &rCurCol,int &rCurRow)
1764 if (nMatrixRows!=0)
1766 if (rCurCol == nMatrixCols-1)
1768 if (rCurRow != nMatrixRows-1)
1769 rRet.append(" {} ##\n");
1770 if (nMatrixRows!=-1)
1772 rCurCol=0;
1773 rCurRow++;
1776 else
1778 rRet.append(" {} # ");
1779 if (nMatrixRows!=-1)
1780 rCurCol++;
1781 else
1782 rRet.append("\n");
1787 /* set the alignment of the following term, but starmath currently
1788 * cannot handle vertical alignment */
1789 void MathType::HandleAlign(sal_uInt8 nHorAlign, int &rSetAlign)
1791 switch(nHorAlign)
1793 case 1:
1794 default:
1795 rRet.append("alignl {");
1796 break;
1797 case 2:
1798 rRet.append("alignc {");
1799 break;
1800 case 3:
1801 rRet.append("alignr {");
1802 break;
1804 rSetAlign++;
1807 /* set size of text, complexity due to overuse of signedness as a flag
1808 * indicator by mathtype file format*/
1809 bool MathType::HandleSize(sal_Int16 nLstSize,sal_Int16 nDefSize, int &rSetSize)
1811 const sal_Int16 nDefaultSize = 12;
1812 bool bRet=false;
1813 if (nLstSize < 0)
1815 if ((-nLstSize/32 != nDefaultSize) && (-nLstSize/32 != nCurSize))
1817 if (rSetSize)
1819 rSetSize--;
1820 rRet.append("}");
1821 bRet=true;
1823 if (-nLstSize/32 != nLastSize)
1825 nLastSize = nCurSize;
1826 rRet.append(" size ");
1827 rRet.append(OUString::number(-nLstSize/32));
1828 rRet.append("{");
1829 bRet=true;
1830 rSetSize++;
1832 nCurSize = -nLstSize/32;
1835 else
1837 /*sizetable should theoreticaly be filled with the default sizes
1838 *of the various font groupings matching starmaths equivalents
1839 in aTypeFaces, and a test would be done to see if the new font
1840 size would be the same as what starmath would have chosen for
1841 itself anyway in which case the size setting could be ignored*/
1842 nLstSize = aSizeTable.at(nLstSize);
1843 nLstSize = nLstSize + nDefSize;
1844 if (nLstSize != nCurSize)
1846 if (rSetSize)
1848 rSetSize--;
1849 rRet.append("}");
1850 bRet=true;
1852 if (nLstSize != nLastSize)
1854 nLastSize = nCurSize;
1855 rRet.append(" size ");
1856 rRet.append(OUString::number(nLstSize));
1857 rRet.append("{");
1858 bRet=true;
1859 rSetSize++;
1861 nCurSize = nLstSize;
1864 return bRet;
1867 bool MathType::ConvertFromStarMath( SfxMedium& rMedium )
1869 if (!pTree)
1870 return false;
1872 SvStream *pStream = rMedium.GetOutStream();
1873 if ( pStream )
1875 tools::SvRef<SotStorage> pStor = new SotStorage( pStream, false );
1877 SvGlobalName aGName(MSO_EQUATION3_CLASSID);
1878 pStor->SetClass( aGName, SotClipboardFormatId::NONE, "Microsoft Equation 3.0");
1880 static sal_uInt8 const aCompObj[] = {
1881 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
1882 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0xCE, 0x02, 0x00,
1883 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
1884 0x00, 0x00, 0x00, 0x46, 0x17, 0x00, 0x00, 0x00,
1885 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
1886 0x74, 0x20, 0x45, 0x71, 0x75, 0x61, 0x74, 0x69,
1887 0x6F, 0x6E, 0x20, 0x33, 0x2E, 0x30, 0x00, 0x0C,
1888 0x00, 0x00, 0x00, 0x44, 0x53, 0x20, 0x45, 0x71,
1889 0x75, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x0B,
1890 0x00, 0x00, 0x00, 0x45, 0x71, 0x75, 0x61, 0x74,
1891 0x69, 0x6F, 0x6E, 0x2E, 0x33, 0x00, 0xF4, 0x39,
1892 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1893 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1895 tools::SvRef<SotStorageStream> xStor( pStor->OpenSotStream("\1CompObj"));
1896 xStor->WriteBytes(aCompObj, sizeof(aCompObj));
1898 static sal_uInt8 const aOle[] = {
1899 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
1900 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1901 0x00, 0x00, 0x00, 0x00
1903 tools::SvRef<SotStorageStream> xStor2( pStor->OpenSotStream("\1Ole"));
1904 xStor2->WriteBytes(aOle, sizeof(aOle));
1905 xStor.clear();
1906 xStor2.clear();
1908 tools::SvRef<SotStorageStream> xSrc = pStor->OpenSotStream("Equation Native");
1909 if ( (!xSrc.is()) || (ERRCODE_NONE != xSrc->GetError()))
1910 return false;
1912 pS = xSrc.get();
1913 pS->SetEndian( SvStreamEndian::LITTLE );
1915 pS->SeekRel(EQNOLEFILEHDR_SIZE); //Skip 28byte Header and fill it in later
1916 pS->WriteUChar( 0x03 );
1917 pS->WriteUChar( 0x01 );
1918 pS->WriteUChar( 0x01 );
1919 pS->WriteUChar( 0x03 );
1920 pS->WriteUChar( 0x00 );
1921 sal_uInt32 nSize = pS->Tell();
1922 nPendingAttributes=0;
1924 HandleNodes(pTree, 0);
1925 pS->WriteUChar( END );
1927 nSize = pS->Tell()-nSize;
1928 pS->Seek(0);
1929 EQNOLEFILEHDR aHdr(nSize+4+1);
1930 aHdr.Write(pS);
1932 pStor->Commit();
1935 return true;
1939 void MathType::HandleNodes(SmNode *pNode,int nLevel)
1941 switch(pNode->GetType())
1943 case SmNodeType::Attribut:
1944 HandleAttributes(pNode,nLevel);
1945 break;
1946 case SmNodeType::Text:
1947 HandleText(pNode);
1948 break;
1949 case SmNodeType::VerticalBrace:
1950 HandleVerticalBrace(pNode,nLevel);
1951 break;
1952 case SmNodeType::Brace:
1953 HandleBrace(pNode,nLevel);
1954 break;
1955 case SmNodeType::Oper:
1956 HandleOperator(pNode,nLevel);
1957 break;
1958 case SmNodeType::BinVer:
1959 HandleFractions(pNode,nLevel);
1960 break;
1961 case SmNodeType::Root:
1962 HandleRoot(pNode,nLevel);
1963 break;
1964 case SmNodeType::Special:
1966 SmTextNode *pText = static_cast<SmTextNode *>(pNode);
1967 //if the token str and the result text are the same then this
1968 //is to be seen as text, else assume it's a mathchar
1969 if (pText->GetText() == pText->GetToken().aText)
1970 HandleText(pText);
1971 else
1972 HandleMath(pText);
1974 break;
1975 case SmNodeType::Math:
1976 case SmNodeType::MathIdent:
1977 HandleMath(pNode);
1978 break;
1979 case SmNodeType::SubSup:
1980 HandleSubSupScript(pNode,nLevel);
1981 break;
1982 case SmNodeType::Expression:
1984 size_t nSize = pNode->GetNumSubNodes();
1985 for (size_t i = 0; i < nSize; ++i)
1987 if (SmNode *pTemp = pNode->GetSubNode(i))
1988 HandleNodes(pTemp,nLevel+1);
1990 break;
1992 case SmNodeType::Table:
1993 //Root Node, PILE equivalent, i.e. vertical stack
1994 HandleTable(pNode,nLevel);
1995 break;
1996 case SmNodeType::Matrix:
1997 HandleSmMatrix(static_cast<SmMatrixNode *>(pNode),nLevel);
1998 break;
1999 case SmNodeType::Line:
2001 pS->WriteUChar( 0x0a );
2002 pS->WriteUChar( LINE );
2003 size_t nSize = pNode->GetNumSubNodes();
2004 for (size_t i = 0; i < nSize; ++i)
2006 if (SmNode *pTemp = pNode->GetSubNode(i))
2007 HandleNodes(pTemp,nLevel+1);
2009 pS->WriteUChar( END );
2010 break;
2012 case SmNodeType::Align:
2013 HandleMAlign(pNode,nLevel);
2014 break;
2015 case SmNodeType::Blank:
2016 pS->WriteUChar( CHAR );
2017 pS->WriteUChar( 0x98 );
2018 if (pNode->GetToken().eType == TSBLANK)
2019 pS->WriteUInt16( 0xEB04 );
2020 else
2021 pS->WriteUInt16( 0xEB05 );
2022 break;
2023 default:
2025 size_t nSize = pNode->GetNumSubNodes();
2026 for (size_t i = 0; i < nSize; ++i)
2028 if (SmNode *pTemp = pNode->GetSubNode(i))
2029 HandleNodes(pTemp,nLevel+1);
2031 break;
2037 int MathType::StartTemplate(sal_uInt16 nSelector,sal_uInt16 nVariation)
2039 int nOldPending=nPendingAttributes;
2040 pS->WriteUChar( TMPL ); //Template
2041 pS->WriteUChar( nSelector ); //selector
2042 pS->WriteUChar( nVariation ); //variation
2043 pS->WriteUChar( 0x00 ); //options
2044 pS->WriteUChar( LINE );
2045 //there's just no way we can now handle any character
2046 //attributes (from mathtypes perspective) centered
2047 //over an expression but above template attribute
2048 //such as widevec and similar constructs
2049 //we have to drop them
2050 nPendingAttributes=0;
2051 return nOldPending;
2054 void MathType::EndTemplate(int nOldPendingAttributes)
2056 pS->WriteUChar( END ); //end line
2057 pS->WriteUChar( END ); //end template
2058 nPendingAttributes=nOldPendingAttributes;
2062 void MathType::HandleSmMatrix(SmMatrixNode *pMatrix,int nLevel)
2064 pS->WriteUChar( MATRIX );
2065 pS->WriteUChar( 0x00 ); //vAlign ?
2066 pS->WriteUChar( 0x00 ); //h_just
2067 pS->WriteUChar( 0x00 ); //v_just
2068 pS->WriteUChar( pMatrix->GetNumRows() ); //v_just
2069 pS->WriteUChar( pMatrix->GetNumCols() ); //v_just
2070 int nBytes=(pMatrix->GetNumRows()+1)*2/8;
2071 if (((pMatrix->GetNumRows()+1)*2)%8)
2072 nBytes++;
2073 for (int j = 0; j < nBytes; j++)
2074 pS->WriteUChar( 0x00 ); //row_parts
2075 nBytes=(pMatrix->GetNumCols()+1)*2/8;
2076 if (((pMatrix->GetNumCols()+1)*2)%8)
2077 nBytes++;
2078 for (int k = 0; k < nBytes; k++)
2079 pS->WriteUChar( 0x00 ); //col_parts
2080 size_t nSize = pMatrix->GetNumSubNodes();
2081 for (size_t i = 0; i < nSize; ++i)
2083 if (SmNode *pTemp = pMatrix->GetSubNode(i))
2085 pS->WriteUChar( LINE ); //line
2086 HandleNodes(pTemp,nLevel+1);
2087 pS->WriteUChar( END ); //end line
2090 pS->WriteUChar( END );
2094 //Root Node, PILE equivalent, i.e. vertical stack
2095 void MathType::HandleTable(SmNode *pNode,int nLevel)
2097 size_t nSize = pNode->GetNumSubNodes();
2098 //The root of the starmath is a table, if
2099 //we convert this them each iteration of
2100 //conversion from starmath to mathtype will
2101 //add an extra unnecessary level to the
2102 //mathtype output stack which would grow
2103 //without bound in a multi step conversion
2105 if (nLevel == 0)
2106 pS->WriteUChar( 0x0A ); //initial size
2108 if ( nLevel || (nSize >1))
2110 pS->WriteUChar( PILE );
2111 pS->WriteUChar( nHAlign ); //vAlign ?
2112 pS->WriteUChar( 0x01 ); //hAlign
2115 for (size_t i = 0; i < nSize; ++i)
2117 if (SmNode *pTemp = pNode->GetSubNode(i))
2119 pS->WriteUChar( LINE );
2120 HandleNodes(pTemp,nLevel+1);
2121 pS->WriteUChar( END );
2124 if (nLevel || (nSize>1))
2125 pS->WriteUChar( END );
2129 void MathType::HandleRoot(SmNode *pNode,int nLevel)
2131 SmNode *pTemp;
2132 pS->WriteUChar( TMPL ); //Template
2133 pS->WriteUChar( 0x0D ); //selector
2134 if (pNode->GetSubNode(0))
2135 pS->WriteUChar( 0x01 ); //variation
2136 else
2137 pS->WriteUChar( 0x00 ); //variation
2138 pS->WriteUChar( 0x00 ); //options
2140 if (nullptr != (pTemp = pNode->GetSubNode(2)))
2142 pS->WriteUChar( LINE ); //line
2143 HandleNodes(pTemp,nLevel+1);
2144 pS->WriteUChar( END );
2147 if (nullptr != (pTemp = pNode->GetSubNode(0)))
2149 pS->WriteUChar( LINE ); //line
2150 HandleNodes(pTemp,nLevel+1);
2151 pS->WriteUChar( END );
2153 else
2154 pS->WriteUChar( LINE|0x10 ); //dummy line
2157 pS->WriteUChar( END );
2160 sal_uInt8 MathType::HandleCScript(SmNode *pNode,SmNode *pContent,int nLevel,
2161 sal_uInt64 *pPos,bool bTest)
2163 sal_uInt8 nVariation2=0xff;
2165 if (bTest && pNode->GetSubNode(CSUP+1))
2167 nVariation2=0;
2168 if (pNode->GetSubNode(CSUB+1))
2169 nVariation2=2;
2171 else if (pNode->GetSubNode(CSUB+1))
2172 nVariation2=1;
2174 if (nVariation2!=0xff)
2176 if (pPos)
2177 *pPos = pS->Tell();
2178 pS->WriteUChar( TMPL ); //Template
2179 pS->WriteUChar( 0x2B ); //selector
2180 pS->WriteUChar( nVariation2 );
2181 pS->WriteUChar( 0x00 ); //options
2183 if (pContent)
2185 pS->WriteUChar( LINE ); //line
2186 HandleNodes(pContent,nLevel+1);
2187 pS->WriteUChar( END ); //line
2189 else
2190 pS->WriteUChar( LINE|0x10 );
2192 pS->WriteUChar( 0x0B );
2194 SmNode *pTemp;
2195 if (nullptr != (pTemp = pNode->GetSubNode(CSUB+1)))
2197 pS->WriteUChar( LINE ); //line
2198 HandleNodes(pTemp,nLevel+1);
2199 pS->WriteUChar( END ); //line
2201 else
2202 pS->WriteUChar( LINE|0x10 );
2203 if (bTest && nullptr != (pTemp = pNode->GetSubNode(CSUP+1)))
2205 pS->WriteUChar( LINE ); //line
2206 HandleNodes(pTemp,nLevel+1);
2207 pS->WriteUChar( END ); //line
2209 else
2210 pS->WriteUChar( LINE|0x10 );
2212 return nVariation2;
2217 Sub and Sup scripts and another problem area, StarMath
2218 can have all possible options used at the same time, whereas
2219 Mathtype cannot. The ordering of the nodes for each system
2220 is quite different as well leading to some complexity
2222 void MathType::HandleSubSupScript(SmNode *pNode,int nLevel)
2224 sal_uInt8 nVariation=0xff;
2225 if (pNode->GetSubNode(LSUP+1))
2227 nVariation=0;
2228 if (pNode->GetSubNode(LSUB+1))
2229 nVariation=2;
2231 else if ( nullptr != pNode->GetSubNode(LSUB+1) )
2232 nVariation=1;
2234 SmNode *pTemp;
2235 if (nVariation!=0xff)
2237 pS->WriteUChar( TMPL ); //Template
2238 pS->WriteUChar( 0x2c ); //selector
2239 pS->WriteUChar( nVariation );
2240 pS->WriteUChar( 0x00 ); //options
2241 pS->WriteUChar( 0x0B );
2243 if (nullptr != (pTemp = pNode->GetSubNode(LSUB+1)))
2245 pS->WriteUChar( LINE ); //line
2246 HandleNodes(pTemp,nLevel+1);
2247 pS->WriteUChar( END ); //line
2249 else
2250 pS->WriteUChar( LINE|0x10 );
2251 if (nullptr != (pTemp = pNode->GetSubNode(LSUP+1)))
2253 pS->WriteUChar( LINE ); //line
2254 HandleNodes(pTemp,nLevel+1);
2255 pS->WriteUChar( END ); //line
2257 else
2258 pS->WriteUChar( LINE|0x10 );
2259 pS->WriteUChar( END );
2260 nVariation=0xff;
2264 sal_uInt8 nVariation2=HandleCScript(pNode,nullptr,nLevel);
2266 if (nullptr != (pTemp = pNode->GetSubNode(0)))
2268 HandleNodes(pTemp,nLevel+1);
2271 if (nVariation2 != 0xff)
2272 pS->WriteUChar( END );
2274 if (nullptr != (pNode->GetSubNode(RSUP+1)))
2276 nVariation=0;
2277 if (pNode->GetSubNode(RSUB+1))
2278 nVariation=2;
2280 else if (nullptr != pNode->GetSubNode(RSUB+1))
2281 nVariation=1;
2283 if (nVariation!=0xff)
2285 pS->WriteUChar( TMPL ); //Template
2286 pS->WriteUChar( 0x0F ); //selector
2287 pS->WriteUChar( nVariation );
2288 pS->WriteUChar( 0x00 ); //options
2289 pS->WriteUChar( 0x0B );
2291 if (nullptr != (pTemp = pNode->GetSubNode(RSUB+1)))
2293 pS->WriteUChar( LINE ); //line
2294 HandleNodes(pTemp,nLevel+1);
2295 pS->WriteUChar( END ); //line
2297 else
2298 pS->WriteUChar( LINE|0x10 );
2299 if (nullptr != (pTemp = pNode->GetSubNode(RSUP+1)))
2301 pS->WriteUChar( LINE ); //line
2302 HandleNodes(pTemp,nLevel+1);
2303 pS->WriteUChar( END ); //line
2305 else
2306 pS->WriteUChar( LINE|0x10 );
2307 pS->WriteUChar( END ); //line
2310 //After subscript mathtype will keep the size of
2311 //normal text at the subscript size, sigh.
2312 pS->WriteUChar( 0x0A );
2316 void MathType::HandleFractions(SmNode *pNode,int nLevel)
2318 SmNode *pTemp;
2319 pS->WriteUChar( TMPL ); //Template
2320 pS->WriteUChar( 0x0E ); //selector
2321 pS->WriteUChar( 0x00 ); //variation
2322 pS->WriteUChar( 0x00 ); //options
2324 pS->WriteUChar( 0x0A );
2325 pS->WriteUChar( LINE ); //line
2326 if (nullptr != (pTemp = pNode->GetSubNode(0)))
2327 HandleNodes(pTemp,nLevel+1);
2328 pS->WriteUChar( END );
2330 pS->WriteUChar( 0x0A );
2331 pS->WriteUChar( LINE ); //line
2332 if (nullptr != (pTemp = pNode->GetSubNode(2)))
2333 HandleNodes(pTemp,nLevel+1);
2334 pS->WriteUChar( END );
2336 pS->WriteUChar( END );
2340 void MathType::HandleBrace(SmNode *pNode,int nLevel)
2342 SmNode *pTemp;
2343 SmNode *pLeft=pNode->GetSubNode(0);
2344 SmNode *pRight=pNode->GetSubNode(2);
2346 pS->WriteUChar( TMPL ); //Template
2347 bIsReInterpBrace=false;
2348 sal_uInt8 nBSpec=0x10;
2349 auto nLoc = pS->Tell();
2350 if (pLeft)
2352 switch (pLeft->GetToken().eType)
2354 case TLANGLE:
2355 pS->WriteUChar( tmANGLE ); //selector
2356 pS->WriteUChar( 0 ); //variation
2357 pS->WriteUChar( 0 ); //options
2358 break;
2359 case TLBRACE:
2360 pS->WriteUChar( tmBRACE ); //selector
2361 pS->WriteUChar( 0 ); //variation
2362 pS->WriteUChar( 0 ); //options
2363 nBSpec+=3;
2364 break;
2365 case TLBRACKET:
2366 pS->WriteUChar( tmBRACK ); //selector
2367 pS->WriteUChar( 0 ); //variation
2368 pS->WriteUChar( 0 ); //options
2369 nBSpec+=3;
2370 break;
2371 case TLFLOOR:
2372 pS->WriteUChar( tmFLOOR ); //selector
2373 pS->WriteUChar( 0 ); //variation
2374 pS->WriteUChar( 0 ); //options
2375 break;
2376 case TLLINE:
2377 pS->WriteUChar( tmBAR ); //selector
2378 pS->WriteUChar( 0 ); //variation
2379 pS->WriteUChar( 0 ); //options
2380 nBSpec+=3;
2381 break;
2382 case TLDLINE:
2383 pS->WriteUChar( tmDBAR ); //selector
2384 pS->WriteUChar( 0 ); //variation
2385 pS->WriteUChar( 0 ); //options
2386 break;
2387 default:
2388 pS->WriteUChar( tmPAREN ); //selector
2389 pS->WriteUChar( 0 ); //variation
2390 pS->WriteUChar( 0 ); //options
2391 nBSpec+=3;
2392 break;
2396 if (nullptr != (pTemp = pNode->GetSubNode(1)))
2398 pS->WriteUChar( LINE ); //line
2399 HandleNodes(pTemp,nLevel+1);
2400 pS->WriteUChar( END ); //options
2402 nSpec=nBSpec;
2403 if (pLeft)
2404 HandleNodes(pLeft,nLevel+1);
2405 if (bIsReInterpBrace)
2407 auto nLoc2 = pS->Tell();
2408 pS->Seek(nLoc);
2409 pS->WriteUChar( 0x2D );
2410 pS->Seek(nLoc2);
2411 pS->WriteUChar( CHAR );
2412 pS->WriteUChar( 0x96 );
2413 pS->WriteUInt16( 0xEC07 );
2414 bIsReInterpBrace=false;
2416 if (pRight)
2417 HandleNodes(pRight,nLevel+1);
2418 nSpec=0x0;
2419 pS->WriteUChar( END );
2423 void MathType::HandleVerticalBrace(SmNode *pNode,int nLevel)
2425 SmNode *pTemp;
2426 pS->WriteUChar( TMPL ); //Template
2427 if (pNode->GetToken().eType == TUNDERBRACE)
2428 pS->WriteUChar( tmLHBRACE ); //selector
2429 else
2430 pS->WriteUChar( tmUHBRACE ); //selector
2431 pS->WriteUChar( 0 ); //variation
2432 pS->WriteUChar( 0 ); //options
2434 if (nullptr != (pTemp = pNode->GetSubNode(0)))
2436 pS->WriteUChar( LINE ); //line
2437 HandleNodes(pTemp,nLevel+1);
2438 pS->WriteUChar( END ); //options
2441 if (nullptr != (pTemp = pNode->GetSubNode(2)))
2443 pS->WriteUChar( LINE ); //line
2444 HandleNodes(pTemp,nLevel+1);
2445 pS->WriteUChar( END ); //options
2447 pS->WriteUChar( END );
2450 void MathType::HandleOperator(SmNode *pNode,int nLevel)
2452 if (HandleLim(pNode,nLevel))
2453 return;
2455 sal_uInt64 nPos;
2456 sal_uInt8 nVariation;
2458 switch (pNode->GetToken().eType)
2460 case TIINT:
2461 case TIIINT:
2462 case TLINT:
2463 case TLLINT:
2464 case TLLLINT:
2465 nVariation=HandleCScript(pNode->GetSubNode(0),
2466 pNode->GetSubNode(1),nLevel,&nPos,false);
2467 break;
2468 default:
2469 nVariation=HandleCScript(pNode->GetSubNode(0),
2470 pNode->GetSubNode(1),nLevel,&nPos);
2471 break;
2474 sal_uInt8 nOldVariation=nVariation;
2475 sal_uInt8 nIntVariation=nVariation;
2477 sal_uInt64 nPos2=0;
2478 if (nVariation != 0xff)
2480 nPos2 = pS->Tell();
2481 pS->Seek(nPos);
2482 if (nVariation == 2)
2484 nIntVariation=0;
2485 nVariation = 1;
2487 else if (nVariation == 0)
2488 nVariation = 1;
2489 else if (nVariation == 1)
2490 nVariation = 0;
2492 else
2494 nVariation = 2;
2495 nIntVariation=0;
2497 pS->WriteUChar( TMPL );
2498 switch(pNode->GetToken().eType)
2500 case TINT:
2501 case TINTD:
2502 if (nOldVariation != 0xff)
2503 pS->WriteUChar( 0x18 ); //selector
2504 else
2505 pS->WriteUChar( 0x15 ); //selector
2506 pS->WriteUChar( nIntVariation ); //variation
2507 break;
2508 case TIINT:
2509 if (nOldVariation != 0xff)
2511 pS->WriteUChar( 0x19 );
2512 pS->WriteUChar( 0x01 );
2514 else
2516 pS->WriteUChar( 0x16 );
2517 pS->WriteUChar( 0x00 );
2519 break;
2520 case TIIINT:
2521 if (nOldVariation != 0xff)
2523 pS->WriteUChar( 0x1a );
2524 pS->WriteUChar( 0x01 );
2526 else
2528 pS->WriteUChar( 0x17 );
2529 pS->WriteUChar( 0x00 );
2531 break;
2532 case TLINT:
2533 if (nOldVariation != 0xff)
2535 pS->WriteUChar( 0x18 );
2536 pS->WriteUChar( 0x02 );
2538 else
2540 pS->WriteUChar( 0x15 );
2541 pS->WriteUChar( 0x03 );
2543 break;
2544 case TLLINT:
2545 if (nOldVariation != 0xff)
2547 pS->WriteUChar( 0x19 );
2548 pS->WriteUChar( 0x00 );
2550 else
2552 pS->WriteUChar( 0x16 );
2553 pS->WriteUChar( 0x02 );
2555 break;
2556 case TLLLINT:
2557 if (nOldVariation != 0xff)
2559 pS->WriteUChar( 0x1a );
2560 pS->WriteUChar( 0x00 );
2562 else
2564 pS->WriteUChar( 0x17 );
2565 pS->WriteUChar( 0x02 );
2567 break;
2568 case TSUM:
2569 default:
2570 pS->WriteUChar( 0x1d );
2571 pS->WriteUChar( nVariation );
2572 break;
2573 case TPROD:
2574 pS->WriteUChar( 0x1f );
2575 pS->WriteUChar( nVariation );
2576 break;
2577 case TCOPROD:
2578 pS->WriteUChar( 0x21 );
2579 pS->WriteUChar( nVariation );
2580 break;
2582 pS->WriteUChar( 0 ); //options
2584 if (nPos2)
2585 pS->Seek(nPos2);
2586 else
2588 pS->WriteUChar( LINE ); //line
2589 HandleNodes(pNode->GetSubNode(1),nLevel+1);
2590 pS->WriteUChar( END ); //line
2591 pS->WriteUChar( LINE|0x10 );
2592 pS->WriteUChar( LINE|0x10 );
2595 pS->WriteUChar( 0x0D );
2596 switch(pNode->GetToken().eType)
2598 case TSUM:
2599 default:
2600 pS->WriteUChar( CHAR );
2601 pS->WriteUChar( 0x86 );
2602 pS->WriteUInt16( 0x2211 );
2603 break;
2604 case TPROD:
2605 pS->WriteUChar( CHAR );
2606 pS->WriteUChar( 0x86 );
2607 pS->WriteUInt16( 0x220F );
2608 break;
2609 case TCOPROD:
2610 pS->WriteUChar( CHAR );
2611 pS->WriteUChar( 0x8B );
2612 pS->WriteUInt16( 0x2210 );
2613 break;
2614 case TIIINT:
2615 case TLLLINT:
2616 pS->WriteUChar( CHAR );
2617 pS->WriteUChar( 0x86 );
2618 pS->WriteUInt16( 0x222B );
2619 SAL_FALLTHROUGH;
2620 case TIINT:
2621 case TLLINT:
2622 pS->WriteUChar( CHAR );
2623 pS->WriteUChar( 0x86 );
2624 pS->WriteUInt16( 0x222B );
2625 SAL_FALLTHROUGH;
2626 case TINT:
2627 case TINTD:
2628 case TLINT:
2629 pS->WriteUChar( CHAR );
2630 pS->WriteUChar( 0x86 );
2631 pS->WriteUInt16( 0x222B );
2632 break;
2634 pS->WriteUChar( END );
2635 pS->WriteUChar( 0x0A );
2639 bool MathType::HandlePile(int &rSetAlign, int nLevel, sal_uInt8 nSelector, sal_uInt8 nVariation)
2641 sal_uInt8 nVAlign;
2642 pS->ReadUChar( nHAlign );
2643 pS->ReadUChar( nVAlign );
2645 HandleAlign(nHAlign, rSetAlign);
2647 rRet.append(" stack {\n");
2648 bool bRet = HandleRecords( nLevel+1, nSelector, nVariation, -1, -1 );
2649 int nRemoveFrom = rRet.getLength() >= 3 ? rRet.getLength() - 3 : 0;
2650 rRet.remove(nRemoveFrom, 2);
2651 rRet.append("} ");
2653 while (rSetAlign)
2655 rRet.append("} ");
2656 rSetAlign--;
2658 return bRet;
2661 bool MathType::HandleMatrix(int nLevel, sal_uInt8 nSelector, sal_uInt8 nVariation)
2663 sal_uInt8 nH_just,nV_just,nRows,nCols,nVAlign;
2664 pS->ReadUChar( nVAlign );
2665 pS->ReadUChar( nH_just );
2666 pS->ReadUChar( nV_just );
2667 pS->ReadUChar( nRows );
2668 pS->ReadUChar( nCols );
2669 int nBytes = ((nRows+1)*2)/8;
2670 if (((nRows+1)*2)%8)
2671 nBytes++;
2672 pS->SeekRel(nBytes);
2673 nBytes = ((nCols+1)*2)/8;
2674 if (((nCols+1)*2)%8)
2675 nBytes++;
2676 pS->SeekRel(nBytes);
2677 rRet.append(" matrix {\n");
2678 bool bRet = HandleRecords( nLevel+1, nSelector, nVariation, nRows, nCols );
2680 sal_Int32 nI = rRet.lastIndexOf('#');
2681 if (nI > 0)
2682 if (rRet[nI-1] != '#') //missing column
2683 rRet.append("{}");
2685 rRet.append("\n} ");
2686 return bRet;
2689 bool MathType::HandleTemplate(int nLevel, sal_uInt8 &rSelector,
2690 sal_uInt8 &rVariation, sal_Int32 &rLastTemplateBracket)
2692 sal_uInt8 nOption; //This appears utterly unused
2693 pS->ReadUChar( rSelector );
2694 pS->ReadUChar( rVariation );
2695 pS->ReadUChar( nOption );
2696 OSL_ENSURE(rSelector < 48,"Selector out of range");
2697 if ((rSelector >= 21) && (rSelector <=26))
2699 OSL_ENSURE(nOption < 2,"Option out of range");
2701 else if (rSelector <= 12)
2703 OSL_ENSURE(nOption < 3,"Option out of range");
2706 //For the (broken) case where one subscript template ends, and there is
2707 //another one after it, mathtype handles it as if the second one was
2708 //inside the first one and renders it as sub of sub
2709 bool bRemove=false;
2710 if ( (rSelector == 0xf) && (rLastTemplateBracket != -1) )
2712 bRemove=true;
2713 for (sal_Int32 nI = rLastTemplateBracket+1; nI < rRet.getLength(); nI++ )
2714 if (rRet[nI] != ' ')
2716 bRemove=false;
2717 break;
2721 //suborderlist
2722 bool bRet = HandleRecords( nLevel+1, rSelector, rVariation );
2724 if (bRemove)
2726 if (rLastTemplateBracket < rRet.getLength())
2727 rRet.remove(rLastTemplateBracket, 1);
2728 rRet.append("} ");
2729 rLastTemplateBracket = -1;
2731 if (rSelector == 0xf)
2732 rLastTemplateBracket = rRet.lastIndexOf('}');
2733 else
2734 rLastTemplateBracket = -1;
2736 rSelector = sal::static_int_cast< sal_uInt8 >(-1);
2737 return bRet;
2740 void MathType::HandleEmblishments()
2742 sal_uInt8 nEmbel;
2745 pS->ReadUChar( nEmbel );
2746 if (!pS->good())
2747 break;
2748 switch (nEmbel)
2750 case 0x02:
2751 rRet.append(" dot ");
2752 break;
2753 case 0x03:
2754 rRet.append(" ddot ");
2755 break;
2756 case 0x04:
2757 rRet.append(" dddot ");
2758 break;
2759 case 0x05:
2760 if (!nPostSup)
2762 sPost += " sup {}";
2763 nPostSup = sPost.getLength();
2765 sPost = sPost.replaceAt(nPostSup-1,0," ' ");
2766 nPostSup += 3;
2767 break;
2768 case 0x06:
2769 if (!nPostSup)
2771 sPost += " sup {}";
2772 nPostSup = sPost.getLength();
2774 sPost = sPost.replaceAt(nPostSup-1,0," '' ");
2775 nPostSup += 4;
2776 break;
2777 case 0x07:
2778 if (!nPostlSup)
2780 sPost += " lsup {}";
2781 nPostlSup = sPost.getLength();
2783 sPost = sPost.replaceAt(nPostlSup-1,0," ' ");
2784 nPostlSup += 3;
2785 break;
2786 case 0x08:
2787 rRet.append(" tilde ");
2788 break;
2789 case 0x09:
2790 rRet.append(" hat ");
2791 break;
2792 case 0x0b:
2793 rRet.append(" vec ");
2794 break;
2795 case 0x10:
2796 rRet.append(" overstrike ");
2797 break;
2798 case 0x11:
2799 rRet.append(" bar ");
2800 break;
2801 case 0x12:
2802 if (!nPostSup)
2804 sPost += " sup {}";
2805 nPostSup = sPost.getLength();
2807 sPost = sPost.replaceAt(nPostSup-1,0," ''' ");
2808 nPostSup += 5;
2809 break;
2810 case 0x14:
2811 rRet.append(" breve ");
2812 break;
2813 default:
2814 OSL_ENSURE(nEmbel < 21,"Embel out of range");
2815 break;
2817 if (nVersion < 3)
2818 break;
2819 }while (nEmbel);
2822 void MathType::HandleSetSize()
2824 sal_uInt8 nTemp;
2825 pS->ReadUChar( nTemp );
2826 switch (nTemp)
2828 case 101:
2829 pS->ReadInt16( nLSize );
2830 nLSize = -nLSize;
2831 break;
2832 case 100:
2833 pS->ReadUChar( nTemp );
2834 nLSize = nTemp;
2835 pS->ReadInt16( nDSize );
2836 break;
2837 default:
2838 nLSize = nTemp;
2839 pS->ReadUChar( nTemp );
2840 nDSize = nTemp-128;
2841 break;
2845 bool MathType::HandleChar(sal_Int32 &rTextStart, int &rSetSize, int nLevel,
2846 sal_uInt8 nTag, sal_uInt8 nSelector, sal_uInt8 nVariation, bool bSilent)
2848 sal_Unicode nChar(0);
2849 bool bRet = true;
2851 if (xfAUTO(nTag))
2853 //This is a candidate for function recognition, whatever
2854 //that is!
2857 sal_uInt8 nOldTypeFace = nTypeFace;
2858 pS->ReadUChar( nTypeFace );
2859 if (nVersion < 3)
2861 sal_uInt8 nChar8(0);
2862 pS->ReadUChar( nChar8 );
2863 nChar = nChar8;
2865 else
2866 pS->ReadUtf16( nChar );
2869 bad character, old mathtype < 3 has these
2871 if (nChar < 0x20)
2872 return bRet;
2874 if (xfEMBELL(nTag))
2876 //A bit tricky, the character emblishments for
2877 //mathtype can all be listed after each other, in
2878 //starmath some must go before the character and some
2879 //must go after. In addition some of the emblishments
2880 //may repeated and in starmath some of these groups
2881 //must be gathered together. sPost is the portion that
2882 //follows the char and nPostSup and nPostlSup are the
2883 //indexes at which this class of emblishment is
2884 //collated together
2885 sPost.clear();
2886 nPostSup = nPostlSup = 0;
2887 int nOriglen=rRet.getLength()-rTextStart;
2888 rRet.append(" {"); // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n"
2889 if ((!bSilent) && (nOriglen > 1))
2890 rRet.append("\"");
2891 bRet = HandleRecords( nLevel+1, nSelector, nVariation );
2892 if (!bSilent)
2894 if (nOriglen > 1)
2896 OUString aStr;
2897 TypeFaceToString(aStr,nOldTypeFace);
2898 aStr += "\"";
2899 rRet.insert(std::min(rTextStart, rRet.getLength()), aStr);
2901 aStr.clear();
2902 TypeFaceToString(aStr,nTypeFace);
2903 rRet.append(aStr).append("{");
2905 else
2906 rRet.append(" {");
2907 rTextStart = rRet.getLength();
2911 if (!bSilent)
2913 sal_Int32 nOldLen = rRet.getLength();
2914 if (
2915 HandleSize(nLSize,nDSize,rSetSize) ||
2916 (nOldTypeFace != nTypeFace)
2919 if ((nOldLen - rTextStart) > 1)
2921 rRet.insert(nOldLen, "\"");
2922 OUString aStr;
2923 TypeFaceToString(aStr,nOldTypeFace);
2924 aStr += "\"";
2925 rRet.insert(rTextStart,aStr);
2927 rTextStart = rRet.getLength();
2929 nOldLen = rRet.getLength();
2930 if (!LookupChar(nChar,rRet,nVersion,nTypeFace))
2932 if (nOldLen - rTextStart > 1)
2934 rRet.insert(nOldLen, "\"");
2935 OUString aStr;
2936 TypeFaceToString(aStr,nOldTypeFace);
2937 aStr += "\"";
2938 rRet.insert(rTextStart, aStr);
2940 rTextStart = rRet.getLength();
2942 lcl_PrependDummyTerm(rRet, rTextStart);
2945 if ((xfEMBELL(nTag)) && (!bSilent))
2947 rRet.append("}}").append(sPost); // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n"
2948 rTextStart = rRet.getLength();
2950 return bRet;
2953 bool MathType::HandleLim(SmNode *pNode,int nLevel)
2955 bool bRet=false;
2956 //Special case for the "lim" option in StarMath
2957 if ((pNode->GetToken().eType == TLIM)
2958 || (pNode->GetToken().eType == TLIMSUP)
2959 || (pNode->GetToken().eType == TLIMINF)
2962 if (pNode->GetSubNode(1))
2964 sal_uInt8 nVariation2=HandleCScript(pNode->GetSubNode(0),nullptr,
2965 nLevel);
2967 pS->WriteUChar( 0x0A );
2968 pS->WriteUChar( LINE ); //line
2969 pS->WriteUChar( CHAR|0x10 );
2970 pS->WriteUChar( 0x82 );
2971 pS->WriteUInt16( 'l' );
2972 pS->WriteUChar( CHAR|0x10 );
2973 pS->WriteUChar( 0x82 );
2974 pS->WriteUInt16( 'i' );
2975 pS->WriteUChar( CHAR|0x10 );
2976 pS->WriteUChar( 0x82 );
2977 pS->WriteUInt16( 'm' );
2979 if (pNode->GetToken().eType == TLIMSUP)
2981 pS->WriteUChar( CHAR ); //some space
2982 pS->WriteUChar( 0x98 );
2983 pS->WriteUInt16( 0xEB04 );
2985 pS->WriteUChar( CHAR|0x10 );
2986 pS->WriteUChar( 0x82 );
2987 pS->WriteUInt16( 's' );
2988 pS->WriteUChar( CHAR|0x10 );
2989 pS->WriteUChar( 0x82 );
2990 pS->WriteUInt16( 'u' );
2991 pS->WriteUChar( CHAR|0x10 );
2992 pS->WriteUChar( 0x82 );
2993 pS->WriteUInt16( 'p' );
2995 else if (pNode->GetToken().eType == TLIMINF)
2997 pS->WriteUChar( CHAR ); //some space
2998 pS->WriteUChar( 0x98 );
2999 pS->WriteUInt16( 0xEB04 );
3001 pS->WriteUChar( CHAR|0x10 );
3002 pS->WriteUChar( 0x82 );
3003 pS->WriteUInt16( 'i' );
3004 pS->WriteUChar( CHAR|0x10 );
3005 pS->WriteUChar( 0x82 );
3006 pS->WriteUInt16( 'n' );
3007 pS->WriteUChar( CHAR|0x10 );
3008 pS->WriteUChar( 0x82 );
3009 pS->WriteUInt16( 'f' );
3013 pS->WriteUChar( CHAR ); //some space
3014 pS->WriteUChar( 0x98 );
3015 pS->WriteUInt16( 0xEB04 );
3017 if (nVariation2 != 0xff)
3019 pS->WriteUChar( END );
3020 pS->WriteUChar( END );
3022 HandleNodes(pNode->GetSubNode(1),nLevel+1);
3023 bRet = true;
3026 return bRet;
3029 void MathType::HandleMAlign(SmNode *pNode,int nLevel)
3031 sal_uInt8 nPushedHAlign=nHAlign;
3032 switch(pNode->GetToken().eType)
3034 case TALIGNC:
3035 nHAlign=2;
3036 break;
3037 case TALIGNR:
3038 nHAlign=3;
3039 break;
3040 default:
3041 nHAlign=1;
3042 break;
3044 size_t nSize = pNode->GetNumSubNodes();
3045 for (size_t i = 0; i < nSize; ++i)
3047 if (SmNode *pTemp = pNode->GetSubNode(i))
3048 HandleNodes(pTemp,nLevel+1);
3050 nHAlign=nPushedHAlign;
3053 void MathType::HandleMath(SmNode *pNode)
3055 if (pNode->GetToken().eType == TMLINE)
3057 pS->WriteUChar( END );
3058 pS->WriteUChar( LINE );
3059 bIsReInterpBrace=true;
3060 return;
3062 SmMathSymbolNode *pTemp = static_cast<SmMathSymbolNode *>(pNode);
3063 for(sal_Int32 i=0;i<pTemp->GetText().getLength();i++)
3065 sal_Unicode nArse = SmTextNode::ConvertSymbolToUnicode(pTemp->GetText()[i]);
3066 if ((nArse == 0x2224) || (nArse == 0x2288) || (nArse == 0x2285) ||
3067 (nArse == 0x2289))
3069 pS->WriteUChar( CHAR|0x20 );
3071 else if ((nPendingAttributes) &&
3072 (i == ((pTemp->GetText().getLength()+1)/2)-1))
3074 pS->WriteUChar( 0x22 );
3076 else
3077 pS->WriteUChar( CHAR ); //char without formula recognition
3078 //The typeface seems to be MTEXTRA for unicode characters,
3079 //though how to determine when mathtype chooses one over
3080 //the other is unknown. This should do the trick
3081 //nevertheless.
3082 sal_uInt8 nBias;
3083 if ( (nArse == 0x2213) || (nArse == 0x2218) ||
3084 (nArse == 0x210F) || (
3085 (nArse >= 0x22EE) && (nArse <= 0x22FF)
3088 nBias = 0xB; //typeface
3090 else if ((nArse > 0x2000) || (nArse == 0x00D7))
3091 nBias = 0x6; //typeface
3092 else if (nArse == 0x3d1)
3093 nBias = 0x4;
3094 else if ((nArse > 0xFF) && ((nArse < 0x393) || (nArse > 0x3c9)))
3095 nBias = 0xB; //typeface
3096 else if ((nArse == 0x2F) || (nArse == 0x2225))
3097 nBias = 0x2; //typeface
3098 else
3099 nBias = 0x3; //typeface
3101 pS->WriteUChar( nSpec+nBias+128 ); //typeface
3103 if (nArse == 0x2224)
3105 pS->WriteUInt16( 0x7C );
3106 pS->WriteUChar( EMBEL );
3107 pS->WriteUChar( 0x0A );
3108 pS->WriteUChar( END ); //end embel
3109 pS->WriteUChar( END ); //end embel
3111 else if (nArse == 0x2225)
3112 pS->WriteUInt16( 0xEC09 );
3113 else if (nArse == 0xE421)
3114 pS->WriteUInt16( 0x2265 );
3115 else if (nArse == 0x230A)
3116 pS->WriteUInt16( 0xF8F0 );
3117 else if (nArse == 0x230B)
3118 pS->WriteUInt16( 0xF8FB );
3119 else if (nArse == 0xE425)
3120 pS->WriteUInt16( 0x2264 );
3121 else if (nArse == 0x226A)
3123 pS->WriteUInt16( 0x3C );
3124 pS->WriteUChar( CHAR );
3125 pS->WriteUChar( 0x98 );
3126 pS->WriteUInt16( 0xEB01 );
3127 pS->WriteUChar( CHAR );
3128 pS->WriteUChar( 0x86 );
3129 pS->WriteUInt16( 0x3c );
3131 else if (nArse == 0x2288)
3133 pS->WriteUInt16( 0x2286 );
3134 pS->WriteUChar( EMBEL );
3135 pS->WriteUChar( 0x0A );
3136 pS->WriteUChar( END ); //end embel
3137 pS->WriteUChar( END ); //end embel
3139 else if (nArse == 0x2289)
3141 pS->WriteUInt16( 0x2287 );
3142 pS->WriteUChar( EMBEL );
3143 pS->WriteUChar( 0x0A );
3144 pS->WriteUChar( END ); //end embel
3145 pS->WriteUChar( END ); //end embel
3147 else if (nArse == 0x2285)
3149 pS->WriteUInt16( 0x2283 );
3150 pS->WriteUChar( EMBEL );
3151 pS->WriteUChar( 0x0A );
3152 pS->WriteUChar( END ); //end embel
3153 pS->WriteUChar( END ); //end embel
3155 else
3156 pS->WriteUInt16( nArse );
3158 nPendingAttributes = 0;
3161 void MathType::HandleAttributes(SmNode *pNode,int nLevel)
3163 int nOldPending = 0;
3164 SmNode *pTemp = nullptr;
3165 SmTextNode *pIsText = nullptr;
3167 if (nullptr != (pTemp = pNode->GetSubNode(0)))
3169 pIsText = static_cast<SmTextNode *>(pNode->GetSubNode(1));
3171 switch (pTemp->GetToken().eType)
3173 case TWIDEVEC:
3174 //there's just no way we can now handle any character
3175 //attributes (from mathtypes perspective) centered
3176 //over an expression but above template attributes
3177 //such as widevec and similar constructs
3178 //we have to drop them
3179 nOldPending = StartTemplate(0x2f,0x01);
3180 break;
3181 case TCHECK: //Not Exportable
3182 case TACUTE: //Not Exportable
3183 case TGRAVE: //Not Exportable
3184 case TCIRCLE: //Not Exportable
3185 case TWIDETILDE: //Not Exportable
3186 case TWIDEHAT: //Not Exportable
3187 break;
3188 case TUNDERLINE:
3189 nOldPending = StartTemplate(0x10);
3190 break;
3191 case TOVERLINE: //If the next node is not text
3192 //or text with more than one char
3193 if ((pIsText->GetToken().eType != TTEXT) ||
3194 (pIsText->GetText().getLength() > 1))
3195 nOldPending = StartTemplate(0x11);
3196 break;
3197 default:
3198 nPendingAttributes++;
3199 break;
3203 if (pIsText)
3204 HandleNodes(pIsText,nLevel+1);
3206 switch (pTemp->GetToken().eType)
3208 case TWIDEVEC:
3209 case TUNDERLINE:
3210 EndTemplate(nOldPending);
3211 break;
3212 case TOVERLINE:
3213 if ((pIsText->GetToken().eType != TTEXT) ||
3214 (pIsText->GetText().getLength() > 1))
3215 EndTemplate(nOldPending);
3216 break;
3217 default:
3218 break;
3221 //if there was no suitable place to put the attribute,
3222 //then we have to just give up on it
3223 if (nPendingAttributes)
3224 nPendingAttributes--;
3225 else
3227 if ((nInsertion != 0) && nullptr != (pTemp = pNode->GetSubNode(0)))
3229 auto nPos = pS->Tell();
3230 nInsertion--;
3231 pS->Seek(nInsertion);
3232 switch(pTemp->GetToken().eType)
3234 case TACUTE: //Not Exportable
3235 case TGRAVE: //Not Exportable
3236 case TCIRCLE: //Not Exportable
3237 break;
3238 case TCDOT:
3239 pS->WriteUChar( 2 );
3240 break;
3241 case TDDOT:
3242 pS->WriteUChar( 3 );
3243 break;
3244 case TDDDOT:
3245 pS->WriteUChar( 4 );
3246 break;
3247 case TTILDE:
3248 pS->WriteUChar( 8 );
3249 break;
3250 case THAT:
3251 pS->WriteUChar( 9 );
3252 break;
3253 case TVEC:
3254 pS->WriteUChar( 11 );
3255 break;
3256 case TOVERSTRIKE:
3257 pS->WriteUChar( 16 );
3258 break;
3259 case TOVERLINE:
3260 if ((pIsText->GetToken().eType == TTEXT) &&
3261 (pIsText->GetText().getLength() == 1))
3262 pS->WriteUChar( 17 );
3263 break;
3264 case TBREVE:
3265 pS->WriteUChar( 20 );
3266 break;
3267 case TWIDEVEC:
3268 case TUNDERLINE:
3269 case TWIDETILDE:
3270 case TWIDEHAT:
3271 break;
3272 case TBAR:
3273 pS->WriteUChar( 17 );
3274 break;
3275 default:
3276 pS->WriteUChar( 2 );
3277 break;
3279 pS->Seek(nPos);
3284 void MathType::HandleText(SmNode *pNode)
3286 SmTextNode *pTemp = static_cast<SmTextNode *>(pNode);
3287 for(sal_Int32 i=0;i<pTemp->GetText().getLength();i++)
3289 if ((nPendingAttributes) &&
3290 (i == ((pTemp->GetText().getLength()+1)/2)-1))
3292 pS->WriteUChar( 0x22 ); //char, with attributes right
3293 //after the character
3295 else
3296 pS->WriteUChar( CHAR );
3298 sal_uInt8 nFace = 0x1;
3299 if (pNode->GetFont().GetItalic() == ITALIC_NORMAL)
3300 nFace = 0x3;
3301 else if (pNode->GetFont().GetWeight() == WEIGHT_BOLD)
3302 nFace = 0x7;
3303 pS->WriteUChar( nFace+128 ); //typeface
3304 sal_uInt16 nChar = pTemp->GetText()[i];
3305 pS->WriteUInt16( SmTextNode::ConvertSymbolToUnicode(nChar) );
3307 //Mathtype can only have these sort of character
3308 //attributes on a single character, starmath can put them
3309 //anywhere, when the entity involved is a text run this is
3310 //a large effort to place the character attribute on the
3311 //central mathtype character so that it does pretty much
3312 //what the user probably has in mind. The attributes
3313 //filled in here are dummy ones which are replaced in the
3314 //ATTRIBUT handler if a suitable location for the
3315 //attributes was found here. Unfortunately it is
3316 //possible for starmath to place character attributes on
3317 //entities which cannot occur in mathtype e.g. a Summation
3318 //symbol so these attributes may be lost
3319 if ((nPendingAttributes) &&
3320 (i == ((pTemp->GetText().getLength()+1)/2)-1))
3322 pS->WriteUChar( EMBEL );
3323 while (nPendingAttributes)
3325 pS->WriteUChar( 2 );
3326 //wedge the attributes in here and clear
3327 //the pending stack
3328 nPendingAttributes--;
3330 nInsertion=pS->Tell();
3331 pS->WriteUChar( END ); //end embel
3332 pS->WriteUChar( END ); //end embel
3337 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportMathType(SvStream &rStream)
3339 OUStringBuffer sText;
3340 MathType aEquation(sText);
3341 bool bRet = false;
3344 bRet = aEquation.Parse(&rStream);
3346 catch (const std::out_of_range&)
3349 return bRet;
3352 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */