calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / starmath / source / mathtype.cxx
blob9273a4498b617b9b40dba2e0f4ea0adb66dc0599
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"
21 #include "eqnolefilehdr.hxx"
23 #include <filter/msfilter/classids.hxx>
24 #include <osl/diagnose.h>
25 #include <sfx2/docfile.hxx>
26 #include <sot/storage.hxx>
27 #include <array>
29 //These are the default MathType sizes
30 constexpr std::array<sal_Int16, 7> aSizeTable {
31 12,
34 24,
35 10,
36 12,
37 12,
40 void MathType::Init()
43 These are the default MathType italic/bold settings If mathtype is changed
44 from its defaults, there is nothing we can do, as this information is not
45 stored in the document
47 MathTypeFont aFont;
48 aUserStyles.reserve(11);
49 for(sal_uInt8 i=1;i<=11;i++)
51 aFont.nTface = i+128;
52 switch (i)
54 default:
55 aFont.nStyle=0;
56 break;
57 case 3:
58 case 4:
59 aFont.nStyle=1;
60 break;
61 case 7:
62 aFont.nStyle=2;
63 break;
65 aUserStyles.insert(aFont);
70 /*ToDo replace with table rather than switch, returns
71 sal_True in the case that the char is just a char, and
72 sal_False if the character is an operator which must not be
73 placed inside the quote sequence designed to protect
74 against being parsed as a keyword
76 General solution required to force starmath to handle
77 unicode math chars the way it handles its own math
78 chars rather than handle them as text as it will do
79 for the default case below, i.e. incorrect spacing
80 between math symbols and ordinary text e.g. 1=2 rather
81 than 1 = 2
83 bool MathType::LookupChar(sal_Unicode nChar,OUStringBuffer &rRet,sal_uInt8 nVersion,
84 sal_uInt8 nTypeFace)
86 bool bRet=false;
87 const char *pC = nullptr;
88 switch(nChar)
90 case 0x0000:
91 pC = " none ";
92 break;
93 case 0x00ac:
94 pC = " neg ";
95 break;
96 case 0x00b1:
97 pC = " +- ";
98 break;
99 case '(':
100 pC = " \\( ";
101 break;
102 case ')':
103 pC = " \\) ";
104 break;
105 case '[':
106 pC = " \\[ ";
107 break;
108 case ']':
109 pC = " \\] ";
110 break;
111 case '.':
112 pC = " \".\" ";
113 break;
114 case 0xae:
115 if ((nVersion < 3) && (nTypeFace == 0x86))
116 pC = " rightarrow ";
117 else
119 rRet.append(OUStringChar(nChar));
120 bRet=true;
122 break;
123 case 0x00fb:
124 if ((nVersion < 3) && (nTypeFace == 0x81))
125 nChar = 0xDF;
126 rRet.append(OUStringChar(nChar));
127 bRet=true;
128 break;
129 case 'a':
130 if ((nVersion < 3) && (nTypeFace == 0x84))
131 nChar = 0x3b1;
132 rRet.append(OUStringChar(nChar));
133 bRet=true;
134 break;
135 case 'b':
136 if ((nVersion < 3) && (nTypeFace == 0x84))
137 nChar = 0x3b2;
138 rRet.append(OUStringChar(nChar));
139 bRet=true;
140 break;
141 case 'l':
142 if ((nVersion < 3) && (nTypeFace == 0x84))
143 nChar = 0x3bb;
144 rRet.append(OUStringChar(nChar));
145 bRet=true;
146 break;
147 case 'n':
148 if ((nVersion < 3) && (nTypeFace == 0x84))
149 nChar = 0x3bd;
150 rRet.append(OUStringChar(nChar));
151 bRet=true;
152 break;
153 case 'r':
154 if ((nVersion < 3) && (nTypeFace == 0x84))
155 nChar = 0x3c1;
156 rRet.append(OUStringChar(nChar));
157 bRet=true;
158 break;
159 case 'D':
160 if ((nVersion < 3) && (nTypeFace == 0x84))
161 nChar = 0x394;
162 rRet.append(OUStringChar(nChar));
163 bRet=true;
164 break;
165 case 0xa9:
166 if ((nVersion < 3) && (nTypeFace == 0x82))
167 nChar = '\'';
168 rRet.append(OUStringChar(nChar));
169 bRet=true;
170 break;
171 case 0x00f1:
172 if ((nVersion < 3) && (nTypeFace == 0x86))
173 pC = " \\rangle ";
174 else
176 rRet.append(OUStringChar(nChar));
177 bRet=true;
179 break;
180 case 0x00a3:
181 if ((nVersion < 3) && (nTypeFace == 0x86))
182 pC = " <= ";
183 else
185 rRet.append(OUStringChar(nChar));
186 bRet=true;
188 break;
189 case 0x00de:
190 if ((nVersion < 3) && (nTypeFace == 0x86))
191 pC = " drarrow ";
192 else
194 rRet.append(OUStringChar(nChar));
195 bRet=true;
197 break;
198 case 0x0057:
199 if ((nVersion < 3) && (nTypeFace == 0x85))
200 pC = " %OMEGA ";
201 else
203 rRet.append(OUStringChar(nChar));
204 bRet=true;
206 break;
207 case 0x007b:
208 pC = " lbrace ";
209 break;
210 case 0x007c:
211 pC = " \\lline ";
212 break;
213 case 0x007d:
214 pC = " rbrace ";
215 break;
216 case 0x007e:
217 pC = " \"~\" ";
218 break;
219 case 0x2224:
220 pC = " ndivides ";
221 break;
222 case 0x2225:
223 pC = " parallel ";
224 break;
225 case 0x00d7:
226 if (nVersion < 3)
227 pC = " cdot ";
228 else
229 pC = " times ";
230 break;
231 case 0x00f7:
232 pC = " div ";
233 break;
234 case 0x019b:
235 pC = " lambdabar ";
236 break;
237 case 0x2026:
238 pC = " dotslow ";
239 break;
240 case 0x2022:
241 pC = " cdot ";
242 break;
243 case 0x2102:
244 pC = " setC ";
245 break;
246 case 0x210f:
247 pC = " hbar ";
248 break;
249 case 0x2111:
250 pC = " Im ";
251 break;
252 case 0x2115:
253 pC = " setN ";
254 break;
255 case 0x2118:
256 pC = " wp ";
257 break;
258 case 0x211a:
259 pC = " setQ ";
260 break;
261 case 0x211c:
262 pC = " Re ";
263 break;
264 case 0x211d:
265 pC = " setR ";
266 break;
267 case 0x2124:
268 pC = " setZ ";
269 break;
270 case 0x2135:
271 pC = " aleph ";
272 break;
273 case 0x2190:
274 pC = " leftarrow ";
275 break;
276 case 0x2191:
277 pC = " uparrow ";
278 break;
279 case 0x2192:
280 pC = " rightarrow ";
281 break;
282 case 0x0362:
283 pC = " widevec ";
284 break;
285 case 0x2193:
286 pC = " downarrow ";
287 break;
288 case 0x21d0:
289 pC = " dlarrow ";
290 break;
291 case 0x21d2:
292 pC = " drarrow ";
293 break;
294 case 0x21d4:
295 pC = " dlrarrow ";
296 break;
297 case 0x2200:
298 pC = " forall ";
299 break;
300 case 0x2202:
301 pC = " partial ";
302 break;
303 case 0x2203:
304 pC = " exists ";
305 break;
306 case 0x2204:
307 pC = " notexists ";
308 break;
309 case 0x2205:
310 pC = " emptyset ";
311 break;
312 case 0x2207:
313 pC = " nabla ";
314 break;
315 case 0x2112:
316 pC = " laplace ";
317 break;
318 case 0x03F6:
319 pC = " backepsilon ";
320 break;
321 case 0x2208: // in
322 case 0x2209: // notin
323 rRet.append(" func " + OUStringChar(nChar) + " ");
324 break;
325 case 0x220d: // owns
326 rRet.append(u" func \u220b ");
327 break;
328 case 0x220f:
329 pC = " prod ";
330 break;
331 case 0x2210:
332 pC = " coprod ";
333 break;
334 case 0x2211:
335 pC = " sum ";
336 break;
337 case 0x2212:
338 pC = " - ";
339 break;
340 case 0x2213:
341 pC = " -+ ";
342 break;
343 case 0x2217:
344 pC = " * ";
345 break;
346 case 0x2218:
347 pC = " circ ";
348 break;
349 case 0x221d:
350 pC = " prop ";
351 break;
352 case 0x221e:
353 pC = " infinity ";
354 break;
355 case 0x2227:
356 pC = " and ";
357 break;
358 case 0x2228:
359 pC = " or ";
360 break;
361 case 0x2229:
362 pC = " intersection ";
363 break;
364 case 0x222a:
365 pC = " union ";
366 break;
367 case 0x222b:
368 pC = " int ";
369 break;
370 case 0x222c:
371 pC = " iint ";
372 break;
373 case 0x222d:
374 pC = " iiint ";
375 break;
376 case 0x222e:
377 pC = " lint ";
378 break;
379 case 0x222f:
380 pC = " llint ";
381 break;
382 case 0x2230:
383 pC = " lllint ";
384 break;
385 case 0x2245:
386 pC = " simeq ";
387 break;
388 case 0x2248:
389 pC = " approx ";
390 break;
391 case 0x2260:
392 pC = " <> ";
393 break;
394 case 0x2261:
395 pC = " equiv ";
396 break;
397 case 0x2264:
398 pC = " <= ";
399 break;
400 case 0x2265:
401 pC = " >= ";
402 break;
404 case 0x227A:
405 pC = " prec ";
406 break;
407 case 0x227B:
408 pC = " succ ";
409 break;
410 case 0x227C:
411 pC = " preccurlyeq ";
412 break;
413 case 0x227D:
414 pC = " succcurlyeq ";
415 break;
416 case 0x227E:
417 pC = " precsim ";
418 break;
419 case 0x227F:
420 pC = " succsim ";
421 break;
422 case 0x2280:
423 pC = " nprec ";
424 break;
425 case 0x2281:
426 pC = " nsucc ";
427 break;
429 case 0x2282: // subset
430 case 0x2283: // supset
431 case 0x2284: // nsubset
432 case 0x2285: // nsupset
433 case 0x2286: // subseteq
434 case 0x2287: // supseteq
435 case 0x2288: // nsubseteq
436 case 0x2289: // nsupseteq
437 case 0x22b2: // NORMAL SUBGROUP OF
438 case 0x22b3: // CONTAINS AS NORMAL SUBGROUP
439 rRet.append(" func " + OUStringChar(nChar) + " ");
440 break;
441 case 0x22a5:
442 pC = " ortho ";
443 break;
444 case 0x22c5:
445 pC = " cdot ";
446 break;
447 case 0x22ee:
448 pC = " dotsvert ";
449 break;
450 case 0x22ef:
451 pC = " dotsaxis ";
452 break;
453 case 0x22f0:
454 pC = " dotsup ";
455 break;
456 case 0x22f1:
457 pC = " dotsdown ";
458 break;
459 case MS_LANGLE:
460 case MS_LMATHANGLE:
461 pC = " langle ";
462 break;
463 case MS_RANGLE:
464 case MS_RMATHANGLE:
465 pC = " rangle ";
466 break;
467 case 0x301a:
468 pC = " ldbracket ";
469 break;
470 case 0x301b:
471 pC = " rdbracket ";
472 break;
473 case 0xe083:
474 rRet.append("+");
475 bRet=true;
476 break;
477 case '^':
478 case 0xe091:
479 pC = " widehat ";
480 break;
481 case 0xe096:
482 pC = " widetilde ";
483 break;
484 case 0xe098:
485 pC = " widevec ";
486 break;
487 case 0xE421:
488 pC = " geslant ";
489 break;
490 case 0xE425:
491 pC = " leslant ";
492 break;
493 case 0xeb01: //no space
494 case 0xeb08: //normal space
495 bRet=true;
496 break;
497 case 0xef04: //tiny space
498 case 0xef05: //tiny space
499 case 0xeb02: //small space
500 case 0xeb04: //medium space
501 rRet.append("`");
502 break;
503 case 0xeb05: //large space
504 rRet.append("~");
505 break;
506 case 0x3a9:
507 pC = " %OMEGA ";
508 break;
509 default:
510 rRet.append(OUStringChar(nChar));
511 bRet=true;
512 break;
514 if (pC)
515 rRet.appendAscii(pC);
516 return bRet;
519 void MathTypeFont::AppendStyleToText(OUString &rRet)
521 const char *pC = nullptr;
522 switch (nStyle)
524 default:
525 case 0:
526 break;
527 case 1:
528 pC = " ital ";
529 break;
530 case 2:
531 pC = " bold ";
532 break;
533 case 3:
534 pC = " bold italic";
535 break;
537 if (pC)
538 rRet += OUString::createFromAscii( pC );
541 void MathType::TypeFaceToString(OUString &rTxt,sal_uInt8 nFace)
543 MathTypeFont aFont(nFace);
544 auto aItr = aUserStyles.find(aFont);
545 if (aItr != aUserStyles.end())
546 aFont.nStyle = aItr->nStyle;
547 aFont.AppendStyleToText(rTxt);
550 bool MathType::Parse(SotStorage *pStor)
552 tools::SvRef<SotStorageStream> xSrc = pStor->OpenSotStream(
553 "Equation Native",
554 StreamMode::STD_READ);
555 if ( (!xSrc.is()) || (ERRCODE_NONE != xSrc->GetError()))
556 return false;
557 return Parse(xSrc.get());
560 bool MathType::Parse(SvStream* pStream)
562 pS = pStream;
563 pS->SetEndian( SvStreamEndian::LITTLE );
565 EQNOLEFILEHDR aHdr;
566 aHdr.Read(pS);
567 sal_uInt8 nProdVersion;
568 sal_uInt8 nProdSubVersion;
569 sal_uInt8 nPlatform;
570 sal_uInt8 nProduct;
571 pS->ReadUChar( nVersion );
572 pS->ReadUChar( nPlatform );
573 pS->ReadUChar( nProduct );
574 pS->ReadUChar( nProdVersion );
575 pS->ReadUChar( nProdSubVersion );
577 if (!pS->good() || nVersion > 3) // allow only supported versions of MathType to be parsed
578 return false;
580 bool bRet = HandleRecords(0);
581 //little crude hack to close occasionally open expressions
582 //a sophisticated system to determine what expressions are
583 //opened is required, but this is as much work as rewriting
584 //starmaths internals.
585 rRet.append("{}");
587 return bRet;
590 static void lcl_PrependDummyTerm(OUStringBuffer &rRet, sal_Int32 &rTextStart)
592 if ((rTextStart < rRet.getLength()) &&
593 (rRet[rTextStart] == '=') &&
594 ((rTextStart == 0) || (rRet[ rTextStart-1 ] == '{'))
597 rRet.insert(rTextStart, " {}");
598 rTextStart+=3;
602 static void lcl_AppendDummyTerm(OUStringBuffer &rRet)
604 bool bOk=false;
605 for(int nI=rRet.getLength()-1;nI >= 0; nI--)
607 sal_Int32 nIdx = sal::static_int_cast< sal_Int32 >(nI);
608 sal_Unicode nChar = rRet[nIdx];
609 if (nChar == ' ')
610 continue;
611 if (rRet[nIdx] != '{')
612 bOk=true;
613 break;
615 if (!bOk) //No term, use dummy
616 rRet.append(" {}");
619 void MathType::HandleNudge()
621 sal_uInt8 nXNudge(0);
622 pS->ReadUChar(nXNudge);
623 sal_uInt8 nYNudge(0);
624 pS->ReadUChar(nYNudge);
625 if (nXNudge == 128 && nYNudge == 128)
627 sal_uInt16 nXLongNudge(0);
628 sal_uInt16 nYLongNudge(0);
629 pS->ReadUInt16(nXLongNudge);
630 pS->ReadUInt16(nYLongNudge);
634 /* Fabulously complicated as many tokens have to be reordered and generally
635 * moved around from mathtypes paradigm to starmaths. */
636 bool MathType::HandleRecords(int nLevel, sal_uInt8 nSelector,
637 sal_uInt8 nVariation, int nMatrixRows, int nMatrixCols)
639 //depth-protect
640 if (nLevel > 1024)
641 return false;
643 sal_uInt8 nTag,nRecord;
644 sal_uInt8 nTabType;
645 sal_uInt16 nTabOffset;
646 int i, newline=0;
647 bool bSilent=false;
648 int nPart=0;
649 OUString sPush,sMainTerm;
650 int nSetSize=0,nSetAlign=0;
651 int nCurRow=0,nCurCol=0;
652 bool bOpenString=false;
653 sal_Int32 nTextStart = 0;
654 sal_Int32 nSubSupStartPos = 0;
655 sal_Int32 nLastTemplateBracket=-1;
656 bool bRet = true;
660 nTag = 0;
661 pS->ReadUChar( nTag );
662 nRecord = nTag&0x0F;
664 /*MathType strings can of course include words which
665 *are StarMath keywords, the simplest solution is
666 to escape strings of greater than len 1 with double
667 quotes to avoid scanning the TokenTable for matches
669 Unfortunately it may turn out that the string gets
670 split during the handling of a character emblishment
671 so this special case must be handled in the
672 character handler case 2:
674 if ((nRecord == CHAR) && (!bOpenString))
676 bOpenString=true;
677 nTextStart = rRet.getLength();
679 else if ((nRecord != CHAR) && bOpenString)
681 bOpenString=false;
682 if ((rRet.getLength() - nTextStart) > 1)
684 OUString aStr;
685 TypeFaceToString(aStr,nTypeFace);
686 aStr += "\"";
687 rRet.insert(nTextStart,aStr);
688 rRet.append("\"");
690 else if (nRecord == END && !rRet.isEmpty())
692 sal_Unicode cChar = 0;
693 sal_Int32 nI = rRet.getLength()-1;
694 while (nI)
696 cChar = rRet[nI];
697 if (cChar != ' ')
698 break;
699 --nI;
701 if ((cChar == '=') || (cChar == '+') || (cChar == '-'))
702 rRet.append("{}");
706 switch(nRecord)
708 case LINE:
710 if (xfLMOVE(nTag))
711 HandleNudge();
713 if (newline>0)
714 rRet.append("\nnewline\n");
715 if (!(xfNULL(nTag)))
717 switch (nSelector)
719 case tmANGLE:
720 if (nVariation==0)
721 rRet.append(" langle ");
722 else if (nVariation==1)
723 rRet.append(" \\langle ");
724 break;
725 case tmPAREN:
726 if (nVariation==0)
727 rRet.append(" left (");
728 else if (nVariation==1)
729 rRet.append("\\(");
730 break;
731 case tmBRACE:
732 if ((nVariation==0) || (nVariation==1))
733 rRet.append(" left lbrace ");
734 else
735 rRet.append(" left none ");
736 break;
737 case tmBRACK:
738 if (nVariation==0)
739 rRet.append(" left [");
740 else if (nVariation==1)
741 rRet.append("\\[");
742 break;
743 case tmLBLB:
744 case tmLBRP:
745 rRet.append(" \\[");
746 break;
747 case tmBAR:
748 if (nVariation==0)
749 rRet.append(" lline ");
750 else if (nVariation==1)
751 rRet.append(" \\lline ");
752 break;
753 case tmDBAR:
754 if (nVariation==0)
755 rRet.append(" ldline ");
756 else if (nVariation==1)
757 rRet.append(" \\ldline ");
758 break;
759 case tmFLOOR:
760 if (nVariation == 0 || nVariation & 0x01) // tvFENCE_L
761 rRet.append(" left lfloor ");
762 else
763 rRet.append(" left none ");
764 break;
765 case tmCEILING:
766 if (nVariation==0)
767 rRet.append(" lceil ");
768 else if (nVariation==1)
769 rRet.append(" \\lceil ");
770 break;
771 case tmRBRB:
772 case tmRBLB:
773 rRet.append(" \\]");
774 break;
775 case tmLPRB:
776 rRet.append(" \\(");
777 break;
778 case tmROOT:
779 if (nPart == 0)
781 if (nVariation == 0)
782 rRet.append(" sqrt");
783 else
785 rRet.append(" nroot");
786 sPush = rRet.makeStringAndClear();
789 rRet.append(" {");
790 break;
791 case tmFRACT:
792 if (nPart == 0)
793 rRet.append(" { ");
796 if (nPart == 1)
797 rRet.append(" over ");
798 rRet.append(" {");
799 break;
800 case tmSCRIPT:
801 nSubSupStartPos = rRet.getLength();
802 if ((nVariation == 0) ||
803 ((nVariation == 2) && (nPart==1)))
805 lcl_AppendDummyTerm(rRet);
806 rRet.append(" rSup");
808 else if ((nVariation == 1) ||
809 ((nVariation == 2) && (nPart==0)))
811 lcl_AppendDummyTerm(rRet);
812 rRet.append(" rSub");
814 rRet.append(" {");
815 break;
816 case tmUBAR:
817 if (nVariation == 0)
818 rRet.append(" {underline ");
819 else if (nVariation == 1)
820 rRet.append(" {underline underline ");
821 rRet.append(" {");
822 break;
823 case tmOBAR:
824 if (nVariation == 0)
825 rRet.append(" {overline ");
826 else if (nVariation == 1)
827 rRet.append(" {overline overline ");
828 rRet.append(" {");
829 break;
830 case tmLARROW:
831 if (nPart == 0)
833 if (nVariation == 0)
834 rRet.append(" widevec ");//left arrow above
835 else if (nVariation == 1)
836 rRet.append(" widevec ");//left arrow below
837 rRet.append(" {");
839 break;
840 case tmRARROW:
841 if (nPart == 0)
843 if (nVariation == 0)
844 rRet.append(" widevec ");//right arrow above
845 else if (nVariation == 1)
846 rRet.append(" widevec ");//right arrow below
847 rRet.append(" {");
849 break;
850 case tmBARROW:
851 if (nPart == 0)
853 if (nVariation == 0)
854 rRet.append(" widevec ");//double arrow above
855 else if (nVariation == 1)
856 rRet.append(" widevec ");//double arrow below
857 rRet.append(" {");
859 break;
860 case tmSINT:
861 if (nPart == 0)
863 if ((nVariation == 3) || (nVariation == 4))
864 rRet.append(" lInt");
865 else
866 rRet.append(" Int");
867 if ( (nVariation != 0) && (nVariation != 3))
869 sPush = rRet.makeStringAndClear();
872 if (((nVariation == 1) ||
873 (nVariation == 4)) && (nPart==1))
874 rRet.append(" rSub");
875 else if ((nVariation == 2) && (nPart==2))
876 rRet.append(" rSup");
877 else if ((nVariation == 2) && (nPart==1))
878 rRet.append(" rSub");
879 rRet.append(" {");
880 break;
881 case tmDINT:
882 if (nPart == 0)
884 if ((nVariation == 2) || (nVariation == 3))
885 rRet.append(" llInt");
886 else
887 rRet.append(" iInt");
888 if ( (nVariation != 0) && (nVariation != 2))
890 sPush = rRet.makeStringAndClear();
893 if (((nVariation == 1) ||
894 (nVariation == 3)) && (nPart==1))
895 rRet.append(" rSub");
896 rRet.append(" {");
897 break;
898 case tmTINT:
899 if (nPart == 0)
901 if ((nVariation == 2) || (nVariation == 3))
902 rRet.append(" lllInt");
903 else
904 rRet.append(" iiInt");
905 if ( (nVariation != 0) && (nVariation != 2))
907 sPush = rRet.makeStringAndClear();
910 if (((nVariation == 1) ||
911 (nVariation == 3)) && (nPart==1))
912 rRet.append(" rSub");
913 rRet.append(" {");
914 break;
915 case tmSSINT:
916 if (nPart == 0)
918 if (nVariation == 2)
919 rRet.append(" lInt");
920 else
921 rRet.append(" Int");
922 sPush = rRet.makeStringAndClear();
924 if (((nVariation == 1) ||
925 (nVariation == 2)) && (nPart==1))
926 rRet.append(" cSub");
927 else if ((nVariation == 0) && (nPart==2))
928 rRet.append(" cSup");
929 else if ((nVariation == 0) && (nPart==1))
930 rRet.append(" cSub");
931 rRet.append(" {");
932 break;
933 case tmDSINT:
934 if (nPart == 0)
936 if (nVariation == 0)
937 rRet.append(" llInt");
938 else
939 rRet.append(" iInt");
940 sPush = rRet.makeStringAndClear();
942 if (nPart==1)
943 rRet.append(" cSub");
944 rRet.append(" {");
945 break;
946 case tmTSINT:
947 if (nPart == 0)
949 if (nVariation == 0)
950 rRet.append(" lllInt");
951 else
952 rRet.append(" iiInt");
953 sPush = rRet.makeStringAndClear();
955 if (nPart==1)
956 rRet.append(" cSub");
957 rRet.append(" {");
958 break;
959 case tmUHBRACE:
960 case tmLHBRACE:
961 rRet.append(" {");
962 break;
963 case tmSUM:
964 if (nPart == 0)
966 rRet.append(" Sum");
967 if (nVariation != 2)
969 sPush = rRet.makeStringAndClear();
972 if ((nVariation == 0) && (nPart==1))
973 rRet.append(" cSub");
974 else if ((nVariation == 1) && (nPart==2))
975 rRet.append(" cSup");
976 else if ((nVariation == 1) && (nPart==1))
977 rRet.append(" cSub");
978 rRet.append(" {");
979 break;
980 case tmISUM:
981 if (nPart == 0)
983 rRet.append(" Sum");
984 sPush = rRet.makeStringAndClear();
986 if ((nVariation == 0) && (nPart==1))
987 rRet.append(" rSub");
988 else if ((nVariation == 1) && (nPart==2))
989 rRet.append(" rSup");
990 else if ((nVariation == 1) && (nPart==1))
991 rRet.append(" rSub");
992 rRet.append(" {");
993 break;
994 case tmPROD:
995 if (nPart == 0)
997 rRet.append(" Prod");
998 if (nVariation != 2)
1000 sPush = rRet.makeStringAndClear();
1003 if ((nVariation == 0) && (nPart==1))
1004 rRet.append(" cSub");
1005 else if ((nVariation == 1) && (nPart==2))
1006 rRet.append(" cSup");
1007 else if ((nVariation == 1) && (nPart==1))
1008 rRet.append(" cSub");
1009 rRet.append(" {");
1010 break;
1011 case tmIPROD:
1012 if (nPart == 0)
1014 rRet.append(" Prod");
1015 sPush = rRet.makeStringAndClear();
1017 if ((nVariation == 0) && (nPart==1))
1018 rRet.append(" rSub");
1019 else if ((nVariation == 1) && (nPart==2))
1020 rRet.append(" rSup");
1021 else if ((nVariation == 1) && (nPart==1))
1022 rRet.append(" rSub");
1023 rRet.append(" {");
1024 break;
1025 case tmCOPROD:
1026 if (nPart == 0)
1028 rRet.append(" coProd");
1029 if (nVariation != 2)
1031 sPush = rRet.makeStringAndClear();
1034 if ((nVariation == 0) && (nPart==1))
1035 rRet.append(" cSub");
1036 else if ((nVariation == 1) && (nPart==2))
1037 rRet.append(" cSup");
1038 else if ((nVariation == 1) && (nPart==1))
1039 rRet.append(" cSub");
1040 rRet.append(" {");
1041 break;
1042 case tmICOPROD:
1043 if (nPart == 0)
1045 rRet.append(" coProd");
1046 sPush = rRet.makeStringAndClear();
1048 if ((nVariation == 0) && (nPart==1))
1049 rRet.append(" rSub");
1050 else if ((nVariation == 1) && (nPart==2))
1051 rRet.append(" rSup");
1052 else if ((nVariation == 1) && (nPart==1))
1053 rRet.append(" rSub");
1054 rRet.append(" {");
1055 break;
1056 case tmUNION:
1057 if (nPart == 0)
1059 rRet.append(" union"); //union
1060 if (nVariation != 2)
1062 sPush = rRet.makeStringAndClear();
1065 if ((nVariation == 0) && (nPart==1))
1066 rRet.append(" cSub");
1067 else if ((nVariation == 1) && (nPart==2))
1068 rRet.append(" cSup");
1069 else if ((nVariation == 1) && (nPart==1))
1070 rRet.append(" cSub");
1071 rRet.append(" {");
1072 break;
1073 case tmIUNION:
1074 if (nPart == 0)
1076 rRet.append(" union"); //union
1077 sPush = rRet.makeStringAndClear();
1079 if ((nVariation == 0) && (nPart==1))
1080 rRet.append(" rSub");
1081 else if ((nVariation == 1) && (nPart==2))
1082 rRet.append(" rSup");
1083 else if ((nVariation == 1) && (nPart==1))
1084 rRet.append(" rSub");
1085 rRet.append(" {");
1086 break;
1087 case tmINTER:
1088 if (nPart == 0)
1090 rRet.append(" intersect"); //intersect
1091 if (nVariation != 2)
1093 sPush = rRet.makeStringAndClear();
1096 if ((nVariation == 0) && (nPart==1))
1097 rRet.append(" cSub");
1098 else if ((nVariation == 1) && (nPart==2))
1099 rRet.append(" cSup");
1100 else if ((nVariation == 1) && (nPart==1))
1101 rRet.append(" cSub");
1102 rRet.append(" {");
1103 break;
1104 case tmIINTER:
1105 if (nPart == 0)
1107 rRet.append(" intersect"); //intersect
1108 sPush = rRet.makeStringAndClear();
1110 if ((nVariation == 0) && (nPart==1))
1111 rRet.append(" rSub");
1112 else if ((nVariation == 1) && (nPart==2))
1113 rRet.append(" rSup");
1114 else if ((nVariation == 1) && (nPart==1))
1115 rRet.append(" rSub");
1116 rRet.append(" {");
1117 break;
1118 case tmLIM:
1119 if ((nVariation == 0) && (nPart==1))
1120 rRet.append(" cSup");
1121 else if ((nVariation == 1) && (nPart==1))
1122 rRet.append(" cSub");
1123 else if ((nVariation == 2) && (nPart==1))
1124 rRet.append(" cSub");
1125 else if ((nVariation == 2) && (nPart==2))
1126 rRet.append(" cSup");
1127 rRet.append(" {");
1128 break;
1129 case tmLDIV:
1130 if (nVariation == 0)
1132 if (nPart == 0)
1134 sPush = rRet.makeStringAndClear();
1137 rRet.append(" {");
1138 if (nVariation == 0)
1140 if (nPart == 1)
1141 rRet.append("alignr ");
1143 if (nPart == 0)
1144 rRet.append("\\lline ");
1145 if (nVariation == 1)
1146 rRet.append("overline ");
1147 break;
1148 case tmSLFRACT:
1149 rRet.append(" {");
1150 break;
1151 case tmINTOP:
1152 if (nPart == 0)
1154 sPush = rRet.makeStringAndClear();
1156 if ((nVariation == 0) && (nPart==0))
1157 rRet.append(" rSup");
1158 else if ((nVariation == 2) && (nPart==1))
1159 rRet.append(" rSup");
1160 else if ((nVariation == 1) && (nPart==0))
1161 rRet.append(" rSub");
1162 else if ((nVariation == 2) && (nPart==0))
1163 rRet.append(" rSub");
1164 rRet.append(" {");
1165 break;
1166 case tmSUMOP:
1167 if (nPart == 0)
1169 sPush = rRet.makeStringAndClear();
1171 if ((nVariation == 0) && (nPart==0))
1172 rRet.append(" cSup");
1173 else if ((nVariation == 2) && (nPart==1))
1174 rRet.append(" cSup");
1175 else if ((nVariation == 1) && (nPart==0))
1176 rRet.append(" cSub");
1177 else if ((nVariation == 2) && (nPart==0))
1178 rRet.append(" cSub");
1179 rRet.append(" {");
1180 break;
1181 case tmLSCRIPT:
1182 if (nPart == 0)
1183 rRet.append("\"\"");
1184 if ((nVariation == 0)
1185 || ((nVariation == 2) && (nPart==1)))
1186 rRet.append(" lSup");
1187 else if ((nVariation == 1)
1188 || ((nVariation == 2) && (nPart==0)))
1189 rRet.append(" lSub");
1190 rRet.append(" {");
1191 break;
1192 case tmDIRAC:
1193 if (nVariation==0)
1195 if (nPart == 0)
1196 rRet.append(" langle ");
1198 else if (nVariation==1)
1200 rRet.append(" \\langle ");
1201 newline--;
1203 else if (nVariation==2)
1205 rRet.append(" \\lline ");
1206 newline--;
1208 break;
1209 case tmUARROW:
1210 if (nVariation == 0)
1211 rRet.append(" widevec ");//left below
1212 else if (nVariation == 1)
1213 rRet.append(" widevec ");//right below
1214 else if (nVariation == 2)
1215 rRet.append(" widevec ");//double headed below
1216 rRet.append(" {");
1217 break;
1218 case tmOARROW:
1219 if (nVariation == 0)
1220 rRet.append(" widevec ");//left above
1221 else if (nVariation == 1)
1222 rRet.append(" widevec ");//right above
1223 else if (nVariation == 2)
1224 rRet.append(" widevec ");//double headed above
1225 rRet.append(" {");
1226 break;
1227 default:
1228 break;
1230 sal_Int16 nOldCurSize=nCurSize;
1231 sal_Int32 nSizeStartPos = rRet.getLength();
1232 HandleSize( nLSize, nDSize, nSetSize );
1233 bRet = HandleRecords( nLevel+1 );
1234 while (nSetSize)
1236 bool bOk=false;
1237 sal_Int32 nI = rRet.lastIndexOf('{');
1238 if (nI != -1)
1240 for(nI=nI+1;nI<rRet.getLength();nI++)
1241 if (rRet[nI] != ' ')
1243 bOk=true;
1244 break;
1247 else
1248 bOk=true;
1250 if (bOk)
1251 rRet.append("} ");
1252 else if (rRet.getLength() > nSizeStartPos)
1253 rRet = rRet.truncate(nSizeStartPos);
1254 nSetSize--;
1255 nCurSize=nOldCurSize;
1259 HandleMatrixSeparator(nMatrixRows,nMatrixCols,
1260 nCurCol,nCurRow);
1262 switch (nSelector)
1264 case tmANGLE:
1265 if (nVariation==0)
1266 rRet.append(" rangle ");
1267 else if (nVariation==2)
1268 rRet.append(" \\rangle ");
1269 break;
1270 case tmPAREN:
1271 if (nVariation==0)
1272 rRet.append(" right )");
1273 else if (nVariation==2)
1274 rRet.append("\\)");
1275 break;
1276 case tmBRACE:
1277 if ((nVariation==0) || (nVariation==2))
1278 rRet.append(" right rbrace ");
1279 else
1280 rRet.append(" right none ");
1281 break;
1282 case tmBRACK:
1283 if (nVariation==0)
1284 rRet.append(" right ]");
1285 else if (nVariation==2)
1286 rRet.append("\\]");
1287 break;
1288 case tmBAR:
1289 if (nVariation==0)
1290 rRet.append(" rline ");
1291 else if (nVariation==2)
1292 rRet.append(" \\rline ");
1293 break;
1294 case tmDBAR:
1295 if (nVariation==0)
1296 rRet.append(" rdline ");
1297 else if (nVariation==2)
1298 rRet.append(" \\rdline ");
1299 break;
1300 case tmFLOOR:
1301 if (nVariation == 0 || nVariation & 0x02) // tvFENCE_R
1302 rRet.append(" right rfloor ");
1303 else
1304 rRet.append(" right none ");
1305 break;
1306 case tmCEILING:
1307 if (nVariation==0)
1308 rRet.append(" rceil ");
1309 else if (nVariation==2)
1310 rRet.append(" \\rceil ");
1311 break;
1312 case tmLBLB:
1313 case tmRBLB:
1314 rRet.append("\\[");
1315 break;
1316 case tmRBRB:
1317 case tmLPRB:
1318 rRet.append("\\]");
1319 break;
1320 case tmROOT:
1321 rRet.append("} ");
1322 if (nVariation == 1)
1324 if (nPart == 0)
1326 newline--;
1327 sMainTerm = rRet.makeStringAndClear();
1329 else if (nPart == 1)
1331 rRet.insert(0, sPush);
1332 rRet.append(sMainTerm);
1333 sPush.clear();
1334 sMainTerm.clear();
1337 else
1339 if (nPart == 0)
1340 newline--;
1342 nPart++;
1343 break;
1344 case tmLBRP:
1345 rRet.append("\\)");
1346 break;
1347 case tmFRACT:
1348 rRet.append("} ");
1349 if (nPart == 0)
1350 newline--;
1351 else
1352 rRet.append("} ");
1353 nPart++;
1354 break;
1355 case tmSCRIPT:
1357 if ((nPart == 0) &&
1358 ((nVariation == 2) || (nVariation == 1)))
1359 newline--;
1361 bool bOk=false;
1362 sal_Int32 nI = rRet.lastIndexOf('{');
1363 if (nI != -1)
1365 for(nI=nI+1;nI<rRet.getLength();nI++)
1366 if (rRet[nI] != ' ')
1368 bOk=true;
1369 break;
1372 else
1373 bOk=true;
1375 if (bOk)
1376 rRet.append("} ");
1377 else if (rRet.getLength() > nSubSupStartPos)
1378 rRet = rRet.truncate(nSubSupStartPos);
1379 nPart++;
1381 break;
1382 case tmLSCRIPT:
1383 if ((nPart == 0) &&
1384 ((nVariation == 2) || (nVariation == 1)))
1385 newline--;
1386 rRet.append("} ");
1387 nPart++;
1388 break;
1389 case tmUARROW:
1390 case tmOARROW:
1391 rRet.append("} ");
1392 break;
1393 case tmUBAR:
1394 case tmOBAR:
1395 rRet.append("}} ");
1396 break;
1397 case tmLARROW:
1398 case tmRARROW:
1399 case tmBARROW:
1400 if (nPart == 0)
1402 newline--;
1403 rRet.append("} ");
1405 nPart++;
1406 break;
1407 case tmUHBRACE:
1408 rRet.append("} ");
1409 if (nPart == 0)
1411 newline--;
1412 rRet.append("overbrace");
1414 nPart++;
1415 break;
1416 case tmLHBRACE:
1417 rRet.append("} ");
1418 if (nPart == 0)
1420 newline--;
1421 rRet.append("underbrace");
1423 nPart++;
1424 break;
1425 case tmLIM:
1426 if (nPart==0)
1427 newline--;
1428 else if ((nPart==1) &&
1429 ((nVariation == 2) || (nVariation == 1)))
1430 newline--;
1431 rRet.append("} ");
1432 nPart++;
1433 break;
1434 case tmLDIV:
1435 rRet.append("} ");
1436 if (nVariation == 0)
1438 if (nPart == 0)
1440 sMainTerm = rRet.makeStringAndClear();
1442 else if (nPart == 1)
1444 rRet.insert(0, sPush);
1445 rRet.append(" over " + sMainTerm);
1446 sPush.clear();
1447 sMainTerm.clear();
1450 if (nPart == 0)
1451 newline--;
1452 nPart++;
1453 break;
1454 case tmSLFRACT:
1455 rRet.append("} ");
1456 if (nPart == 0)
1458 newline--;
1459 switch (nVariation)
1461 case 1:
1462 rRet.append("slash");
1463 break;
1464 default:
1465 rRet.append("wideslash");
1466 break;
1469 nPart++;
1470 break;
1471 case tmSUM:
1472 case tmISUM:
1473 case tmPROD:
1474 case tmIPROD:
1475 case tmCOPROD:
1476 case tmICOPROD:
1477 case tmUNION:
1478 case tmIUNION:
1479 case tmINTER:
1480 case tmIINTER:
1481 rRet.append("} ");
1482 if (nPart == 0)
1484 if (nVariation != 2)
1486 sMainTerm = rRet.makeStringAndClear();
1488 newline--;
1490 else if ((nPart == 1) && (nVariation == 0))
1492 rRet.insert(0, sPush);
1493 rRet.append(sMainTerm);
1494 sPush.clear();
1495 sMainTerm.clear();
1496 newline--;
1498 else if ((nPart == 1) && (nVariation == 1))
1499 newline--;
1500 else if ((nPart == 2) && (nVariation == 1))
1502 rRet.insert(0, sPush);
1503 rRet.append(sMainTerm);
1504 sPush.clear();
1505 sMainTerm.clear();
1506 newline--;
1508 nPart++;
1509 break;
1510 case tmSINT:
1511 rRet.append("} ");
1512 if (nPart == 0)
1514 if ((nVariation != 0) && (nVariation != 3))
1516 sMainTerm = rRet.makeStringAndClear();
1518 newline--;
1520 else if ((nPart == 1) &&
1521 ((nVariation == 1) || (nVariation==4)))
1523 rRet.insert(0, sPush);
1524 rRet.append(sMainTerm);
1525 sPush.clear();
1526 sMainTerm.clear();
1527 newline--;
1529 else if ((nPart == 1) && (nVariation == 2))
1530 newline--;
1531 else if ((nPart == 2) && (nVariation == 2))
1533 rRet.insert(0, sPush);
1534 rRet.append(sMainTerm);
1535 sPush.clear();
1536 sMainTerm.clear();
1537 newline--;
1539 nPart++;
1540 break;
1541 case tmDINT:
1542 case tmTINT:
1543 rRet.append("} ");
1544 if (nPart == 0)
1546 if ((nVariation != 0) && (nVariation != 2))
1548 sMainTerm = rRet.makeStringAndClear();
1550 newline--;
1552 else if ((nPart == 1) &&
1553 ((nVariation == 1) || (nVariation==3)))
1555 rRet.insert(0, sPush);
1556 rRet.append(sMainTerm);
1557 sPush.clear();
1558 sMainTerm.clear();
1559 newline--;
1561 nPart++;
1562 break;
1563 case tmSSINT:
1564 rRet.append("} ");
1565 if (nPart == 0)
1567 sMainTerm = rRet.makeStringAndClear();
1568 newline--;
1570 else if ((nPart == 1) &&
1571 ((nVariation == 1) || (nVariation==2)))
1573 rRet.insert(0, sPush);
1574 rRet.append(sMainTerm);
1575 sPush.clear();
1576 sMainTerm.clear();
1577 newline--;
1579 else if ((nPart == 1) && (nVariation == 0))
1580 newline--;
1581 else if ((nPart == 2) && (nVariation == 0))
1583 rRet.insert(0, sPush);
1584 rRet.append(sMainTerm);
1585 sPush.clear();
1586 sMainTerm.clear();
1587 newline--;
1589 nPart++;
1590 break;
1591 case tmDSINT:
1592 case tmTSINT:
1593 rRet.append("} ");
1594 if (nPart == 0)
1596 sMainTerm = rRet.makeStringAndClear();
1597 newline--;
1599 else if (nPart == 1)
1601 rRet.insert(0, sPush);
1602 rRet.append(sMainTerm);
1603 sPush.clear();
1604 sMainTerm.clear();
1605 newline--;
1607 nPart++;
1608 break;
1609 case tmINTOP:
1610 case tmSUMOP:
1611 rRet.append("} ");
1613 if ((nPart == 0) &&
1614 ((nVariation == 0) || (nVariation == 1)))
1616 sMainTerm = rRet.makeStringAndClear();
1617 newline--;
1619 else if ((nPart == 0) && (nVariation == 2))
1620 newline--;
1621 else if ((nPart == 1) && (nVariation == 2))
1623 sMainTerm = rRet.makeStringAndClear();
1624 newline--;
1626 else if ((nPart == 2) || ((nPart == 1) &&
1627 (nVariation == 0 || nVariation == 1)))
1629 rRet.insert(0, sPush);
1630 rRet.append(sMainTerm);
1631 sPush.clear();
1632 sMainTerm.clear();
1634 nPart++;
1635 break;
1636 case tmDIRAC:
1637 if (nVariation==0)
1639 if (nPart == 0)
1641 newline--; //there is another term to arrive
1642 rRet.append(" mline ");
1644 else
1645 rRet.append(" rangle ");
1647 else if (nVariation==1)
1648 rRet.append(" \\lline ");
1649 else if (nVariation==2)
1650 rRet.append(" \\rangle ");
1651 nPart++;
1652 break;
1653 default:
1654 break;
1656 bSilent = true; //Skip the optional brackets and/or
1657 //symbols that follow some of these
1658 //records. Foo Data.
1660 /*In matrices and piles we cannot separate equation
1661 *lines with the newline keyword*/
1662 if (nMatrixCols==0)
1663 newline++;
1666 break;
1667 case CHAR:
1668 if (xfLMOVE(nTag))
1669 HandleNudge();
1670 bRet = HandleChar( nTextStart, nSetSize, nLevel, nTag, nSelector, nVariation, bSilent );
1671 break;
1672 case TMPL:
1673 if (xfLMOVE(nTag))
1674 HandleNudge();
1675 bRet = HandleTemplate( nLevel, nSelector, nVariation, nLastTemplateBracket );
1676 break;
1677 case PILE:
1678 if (xfLMOVE(nTag))
1679 HandleNudge();
1680 bRet = HandlePile( nSetAlign, nLevel, nSelector, nVariation );
1681 HandleMatrixSeparator( nMatrixRows, nMatrixCols, nCurCol, nCurRow );
1682 break;
1683 case MATRIX:
1684 if (xfLMOVE(nTag))
1685 HandleNudge();
1686 bRet = HandleMatrix( nLevel, nSelector, nVariation );
1687 HandleMatrixSeparator( nMatrixRows, nMatrixCols, nCurCol, nCurRow );
1688 break;
1689 case EMBEL:
1690 if (xfLMOVE(nTag))
1691 HandleNudge();
1692 HandleEmblishments();
1693 break;
1694 case RULER:
1696 sal_uInt8 nTabStops(0);
1697 pS->ReadUChar( nTabStops );
1698 for (i=0;i<nTabStops;i++)
1700 pS->ReadUChar( nTabType );
1701 pS->ReadUInt16( nTabOffset );
1703 SAL_WARN("starmath", "Not seen in the wild Equation Ruler Field");
1704 break;
1706 case FONT:
1708 MathTypeFont aFont;
1709 pS->ReadUChar( aFont.nTface );
1711 The typeface number is the negative (which makes it
1712 positive) of the typeface value (unbiased) that appears in
1713 CHAR records that might follow a given FONT record
1715 aFont.nTface = 128-aFont.nTface;
1716 pS->ReadUChar( aFont.nStyle );
1717 aUserStyles.insert(aFont);
1718 // read font name
1719 while(true)
1721 char nChar8(0);
1722 pS->ReadChar( nChar8 );
1723 if (nChar8 == 0)
1724 break;
1727 break;
1728 case SIZE:
1729 HandleSetSize();
1730 break;
1731 case 10:
1732 case 11:
1733 case 12:
1734 case 13:
1735 case 14:
1736 nLSize=nRecord-10;
1737 break;
1738 case END:
1739 default:
1740 break;
1743 while (nRecord != END && !pS->eof());
1744 while (nSetSize)
1746 rRet.append("}");
1747 nSetSize--;
1749 return bRet;
1752 /*Simply determine if we are at the end of a record or the end of a line,
1753 *with fiddly logic to see if we are in a matrix or a pile or neither
1755 Note we cannot tell until after the event that this is the last entry
1756 of a pile, so we must strip the last separator of a pile after this
1757 is detected in the PILE handler
1759 void MathType::HandleMatrixSeparator(int nMatrixRows,int nMatrixCols,
1760 int &rCurCol,int &rCurRow)
1762 if (nMatrixRows==0)
1763 return;
1765 if (rCurCol == nMatrixCols-1)
1767 if (rCurRow != nMatrixRows-1)
1768 rRet.append(" {} ##\n");
1769 if (nMatrixRows!=-1)
1771 rCurCol=0;
1772 rCurRow++;
1775 else
1777 rRet.append(" {} # ");
1778 if (nMatrixRows!=-1)
1779 rCurCol++;
1780 else
1781 rRet.append("\n");
1785 /* set the alignment of the following term, but starmath currently
1786 * cannot handle vertical alignment */
1787 void MathType::HandleAlign(sal_uInt8 nHorAlign, int &rSetAlign)
1789 switch(nHorAlign)
1791 case 1:
1792 default:
1793 rRet.append("alignl {");
1794 break;
1795 case 2:
1796 rRet.append("alignc {");
1797 break;
1798 case 3:
1799 rRet.append("alignr {");
1800 break;
1802 rSetAlign++;
1805 /* set size of text, complexity due to overuse of signedness as a flag
1806 * indicator by mathtype file format*/
1807 bool MathType::HandleSize(sal_Int16 nLstSize,sal_Int16 nDefSize, int &rSetSize)
1809 bool bRet=false;
1810 if (nLstSize < 0)
1812 const sal_Int16 nDefaultSize = 12;
1813 if ((-nLstSize/32 != nDefaultSize) && (-nLstSize/32 != nCurSize))
1815 if (rSetSize)
1817 rSetSize--;
1818 rRet.append("}");
1819 bRet=true;
1821 if (-nLstSize/32 != nLastSize)
1823 nLastSize = nCurSize;
1824 rRet.append(" size ");
1825 rRet.append(static_cast<sal_Int32>(-nLstSize/32));
1826 rRet.append("{");
1827 bRet=true;
1828 rSetSize++;
1830 nCurSize = -nLstSize/32;
1833 else
1835 /*sizetable should theoretically be filled with the default sizes
1836 *of the various font groupings matching starmaths equivalents
1837 in aTypeFaces, and a test would be done to see if the new font
1838 size would be the same as what starmath would have chosen for
1839 itself anyway in which case the size setting could be ignored*/
1840 nLstSize = aSizeTable.at(nLstSize);
1841 nLstSize = nLstSize + nDefSize;
1842 if (nLstSize != nCurSize)
1844 if (rSetSize)
1846 rSetSize--;
1847 rRet.append("}");
1848 bRet=true;
1850 if (nLstSize != nLastSize)
1852 nLastSize = nCurSize;
1853 rRet.append(" size ");
1854 rRet.append(static_cast<sal_Int32>(nLstSize));
1855 rRet.append("{");
1856 bRet=true;
1857 rSetSize++;
1859 nCurSize = nLstSize;
1862 return bRet;
1865 bool MathType::ConvertFromStarMath( SfxMedium& rMedium )
1867 if (!pTree)
1868 return false;
1870 SvStream *pStream = rMedium.GetOutStream();
1871 if ( pStream )
1873 tools::SvRef<SotStorage> pStor = new SotStorage( pStream, false );
1875 SvGlobalName aGName(MSO_EQUATION3_CLASSID);
1876 pStor->SetClass( aGName, SotClipboardFormatId::NONE, "Microsoft Equation 3.0");
1878 static sal_uInt8 const aCompObj[] = {
1879 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
1880 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0xCE, 0x02, 0x00,
1881 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
1882 0x00, 0x00, 0x00, 0x46, 0x17, 0x00, 0x00, 0x00,
1883 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
1884 0x74, 0x20, 0x45, 0x71, 0x75, 0x61, 0x74, 0x69,
1885 0x6F, 0x6E, 0x20, 0x33, 0x2E, 0x30, 0x00, 0x0C,
1886 0x00, 0x00, 0x00, 0x44, 0x53, 0x20, 0x45, 0x71,
1887 0x75, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x0B,
1888 0x00, 0x00, 0x00, 0x45, 0x71, 0x75, 0x61, 0x74,
1889 0x69, 0x6F, 0x6E, 0x2E, 0x33, 0x00, 0xF4, 0x39,
1890 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1891 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1893 tools::SvRef<SotStorageStream> xStor( pStor->OpenSotStream("\1CompObj"));
1894 xStor->WriteBytes(aCompObj, sizeof(aCompObj));
1896 static sal_uInt8 const aOle[] = {
1897 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
1898 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1899 0x00, 0x00, 0x00, 0x00
1901 tools::SvRef<SotStorageStream> xStor2( pStor->OpenSotStream("\1Ole"));
1902 xStor2->WriteBytes(aOle, sizeof(aOle));
1903 xStor.clear();
1904 xStor2.clear();
1906 tools::SvRef<SotStorageStream> xSrc = pStor->OpenSotStream("Equation Native");
1907 if ( (!xSrc.is()) || (ERRCODE_NONE != xSrc->GetError()))
1908 return false;
1910 pS = xSrc.get();
1911 pS->SetEndian( SvStreamEndian::LITTLE );
1913 pS->SeekRel(EQNOLEFILEHDR_SIZE); //Skip 28byte Header and fill it in later
1914 pS->WriteUChar( 0x03 );
1915 pS->WriteUChar( 0x01 );
1916 pS->WriteUChar( 0x01 );
1917 pS->WriteUChar( 0x03 );
1918 pS->WriteUChar( 0x00 );
1919 sal_uInt32 nSize = pS->Tell();
1920 nPendingAttributes=0;
1922 HandleNodes(pTree, 0);
1923 pS->WriteUChar( END );
1925 nSize = pS->Tell()-nSize;
1926 pS->Seek(0);
1927 EQNOLEFILEHDR aHdr(nSize+4+1);
1928 aHdr.Write(pS);
1930 pStor->Commit();
1933 return true;
1937 void MathType::HandleNodes(SmNode *pNode,int nLevel)
1939 switch(pNode->GetType())
1941 case SmNodeType::Attribute:
1942 HandleAttributes(pNode,nLevel);
1943 break;
1944 case SmNodeType::Text:
1945 HandleText(pNode);
1946 break;
1947 case SmNodeType::VerticalBrace:
1948 HandleVerticalBrace(pNode,nLevel);
1949 break;
1950 case SmNodeType::Brace:
1951 HandleBrace(pNode,nLevel);
1952 break;
1953 case SmNodeType::Oper:
1954 HandleOperator(pNode,nLevel);
1955 break;
1956 case SmNodeType::BinVer:
1957 HandleFractions(pNode,nLevel);
1958 break;
1959 case SmNodeType::Root:
1960 HandleRoot(pNode,nLevel);
1961 break;
1962 case SmNodeType::Special:
1964 SmTextNode *pText = static_cast<SmTextNode *>(pNode);
1965 //if the token str and the result text are the same then this
1966 //is to be seen as text, else assume it's a mathchar
1967 if (pText->GetText() == pText->GetToken().aText)
1968 HandleText(pText);
1969 else
1970 HandleMath(pText);
1972 break;
1973 case SmNodeType::Math:
1974 case SmNodeType::MathIdent:
1975 HandleMath(pNode);
1976 break;
1977 case SmNodeType::SubSup:
1978 HandleSubSupScript(pNode,nLevel);
1979 break;
1980 case SmNodeType::Expression:
1982 size_t nSize = pNode->GetNumSubNodes();
1983 for (size_t i = 0; i < nSize; ++i)
1985 if (SmNode *pTemp = pNode->GetSubNode(i))
1986 HandleNodes(pTemp,nLevel+1);
1988 break;
1990 case SmNodeType::Table:
1991 //Root Node, PILE equivalent, i.e. vertical stack
1992 HandleTable(pNode,nLevel);
1993 break;
1994 case SmNodeType::Matrix:
1995 HandleSmMatrix(static_cast<SmMatrixNode *>(pNode),nLevel);
1996 break;
1997 case SmNodeType::Line:
1999 pS->WriteUChar( 0x0a );
2000 pS->WriteUChar( LINE );
2001 size_t nSize = pNode->GetNumSubNodes();
2002 for (size_t i = 0; i < nSize; ++i)
2004 if (SmNode *pTemp = pNode->GetSubNode(i))
2005 HandleNodes(pTemp,nLevel+1);
2007 pS->WriteUChar( END );
2008 break;
2010 case SmNodeType::Align:
2011 HandleMAlign(pNode,nLevel);
2012 break;
2013 case SmNodeType::Blank:
2014 pS->WriteUChar( CHAR );
2015 pS->WriteUChar( 0x98 );
2016 if (pNode->GetToken().eType == TSBLANK)
2017 pS->WriteUInt16( 0xEB04 );
2018 else
2019 pS->WriteUInt16( 0xEB05 );
2020 break;
2021 default:
2023 size_t nSize = pNode->GetNumSubNodes();
2024 for (size_t i = 0; i < nSize; ++i)
2026 if (SmNode *pTemp = pNode->GetSubNode(i))
2027 HandleNodes(pTemp,nLevel+1);
2029 break;
2035 int MathType::StartTemplate(sal_uInt16 nSelector,sal_uInt16 nVariation)
2037 int nOldPending=nPendingAttributes;
2038 pS->WriteUChar( TMPL ); //Template
2039 pS->WriteUChar( nSelector ); //selector
2040 pS->WriteUChar( nVariation ); //variation
2041 pS->WriteUChar( 0x00 ); //options
2042 pS->WriteUChar( LINE );
2043 //there's just no way we can now handle any character
2044 //attributes (from mathtypes perspective) centered
2045 //over an expression but above template attribute
2046 //such as widevec and similar constructs
2047 //we have to drop them
2048 nPendingAttributes=0;
2049 return nOldPending;
2052 void MathType::EndTemplate(int nOldPendingAttributes)
2054 pS->WriteUChar( END ); //end line
2055 pS->WriteUChar( END ); //end template
2056 nPendingAttributes=nOldPendingAttributes;
2060 void MathType::HandleSmMatrix(SmMatrixNode *pMatrix,int nLevel)
2062 pS->WriteUChar( MATRIX );
2063 pS->WriteUChar( 0x00 ); //vAlign ?
2064 pS->WriteUChar( 0x00 ); //h_just
2065 pS->WriteUChar( 0x00 ); //v_just
2066 pS->WriteUChar( pMatrix->GetNumRows() ); //v_just
2067 pS->WriteUChar( pMatrix->GetNumCols() ); //v_just
2068 int nBytes=(pMatrix->GetNumRows()+1)*2/8;
2069 if (((pMatrix->GetNumRows()+1)*2)%8)
2070 nBytes++;
2071 for (int j = 0; j < nBytes; j++)
2072 pS->WriteUChar( 0x00 ); //row_parts
2073 nBytes=(pMatrix->GetNumCols()+1)*2/8;
2074 if (((pMatrix->GetNumCols()+1)*2)%8)
2075 nBytes++;
2076 for (int k = 0; k < nBytes; k++)
2077 pS->WriteUChar( 0x00 ); //col_parts
2078 size_t nSize = pMatrix->GetNumSubNodes();
2079 for (size_t i = 0; i < nSize; ++i)
2081 if (SmNode *pTemp = pMatrix->GetSubNode(i))
2083 pS->WriteUChar( LINE ); //line
2084 HandleNodes(pTemp,nLevel+1);
2085 pS->WriteUChar( END ); //end line
2088 pS->WriteUChar( END );
2092 //Root Node, PILE equivalent, i.e. vertical stack
2093 void MathType::HandleTable(SmNode *pNode,int nLevel)
2095 size_t nSize = pNode->GetNumSubNodes();
2096 //The root of the starmath is a table, if
2097 //we convert this them each iteration of
2098 //conversion from starmath to mathtype will
2099 //add an extra unnecessary level to the
2100 //mathtype output stack which would grow
2101 //without bound in a multi step conversion
2103 if (nLevel == 0)
2104 pS->WriteUChar( 0x0A ); //initial size
2106 if ( nLevel || (nSize >1))
2108 pS->WriteUChar( PILE );
2109 pS->WriteUChar( nHAlign ); //vAlign ?
2110 pS->WriteUChar( 0x01 ); //hAlign
2113 for (size_t i = 0; i < nSize; ++i)
2115 if (SmNode *pTemp = pNode->GetSubNode(i))
2117 pS->WriteUChar( LINE );
2118 HandleNodes(pTemp,nLevel+1);
2119 pS->WriteUChar( END );
2122 if (nLevel || (nSize>1))
2123 pS->WriteUChar( END );
2127 void MathType::HandleRoot(SmNode *pNode,int nLevel)
2129 SmNode *pTemp;
2130 pS->WriteUChar( TMPL ); //Template
2131 pS->WriteUChar( 0x0D ); //selector
2132 if (pNode->GetSubNode(0))
2133 pS->WriteUChar( 0x01 ); //variation
2134 else
2135 pS->WriteUChar( 0x00 ); //variation
2136 pS->WriteUChar( 0x00 ); //options
2138 if (nullptr != (pTemp = pNode->GetSubNode(2)))
2140 pS->WriteUChar( LINE ); //line
2141 HandleNodes(pTemp,nLevel+1);
2142 pS->WriteUChar( END );
2145 if (nullptr != (pTemp = pNode->GetSubNode(0)))
2147 pS->WriteUChar( LINE ); //line
2148 HandleNodes(pTemp,nLevel+1);
2149 pS->WriteUChar( END );
2151 else
2152 pS->WriteUChar( LINE|0x10 ); //dummy line
2155 pS->WriteUChar( END );
2158 sal_uInt8 MathType::HandleCScript(SmNode *pNode,SmNode *pContent,int nLevel,
2159 sal_uInt64 *pPos,bool bTest)
2161 sal_uInt8 nVariation2=0xff;
2163 if (bTest && pNode->GetSubNode(CSUP+1))
2165 nVariation2=0;
2166 if (pNode->GetSubNode(CSUB+1))
2167 nVariation2=2;
2169 else if (pNode->GetSubNode(CSUB+1))
2170 nVariation2=1;
2172 if (nVariation2!=0xff)
2174 if (pPos)
2175 *pPos = pS->Tell();
2176 pS->WriteUChar( TMPL ); //Template
2177 pS->WriteUChar( 0x2B ); //selector
2178 pS->WriteUChar( nVariation2 );
2179 pS->WriteUChar( 0x00 ); //options
2181 if (pContent)
2183 pS->WriteUChar( LINE ); //line
2184 HandleNodes(pContent,nLevel+1);
2185 pS->WriteUChar( END ); //line
2187 else
2188 pS->WriteUChar( LINE|0x10 );
2190 pS->WriteUChar( 0x0B );
2192 SmNode *pTemp;
2193 if (nullptr != (pTemp = pNode->GetSubNode(CSUB+1)))
2195 pS->WriteUChar( LINE ); //line
2196 HandleNodes(pTemp,nLevel+1);
2197 pS->WriteUChar( END ); //line
2199 else
2200 pS->WriteUChar( LINE|0x10 );
2201 if (bTest && nullptr != (pTemp = pNode->GetSubNode(CSUP+1)))
2203 pS->WriteUChar( LINE ); //line
2204 HandleNodes(pTemp,nLevel+1);
2205 pS->WriteUChar( END ); //line
2207 else
2208 pS->WriteUChar( LINE|0x10 );
2210 return nVariation2;
2215 Sub and Sup scripts and another problem area, StarMath
2216 can have all possible options used at the same time, whereas
2217 Mathtype cannot. The ordering of the nodes for each system
2218 is quite different as well leading to some complexity
2220 void MathType::HandleSubSupScript(SmNode *pNode,int nLevel)
2222 sal_uInt8 nVariation=0xff;
2223 if (pNode->GetSubNode(LSUP+1))
2225 nVariation=0;
2226 if (pNode->GetSubNode(LSUB+1))
2227 nVariation=2;
2229 else if ( nullptr != pNode->GetSubNode(LSUB+1) )
2230 nVariation=1;
2232 SmNode *pTemp;
2233 if (nVariation!=0xff)
2235 pS->WriteUChar( TMPL ); //Template
2236 pS->WriteUChar( 0x2c ); //selector
2237 pS->WriteUChar( nVariation );
2238 pS->WriteUChar( 0x00 ); //options
2239 pS->WriteUChar( 0x0B );
2241 if (nullptr != (pTemp = pNode->GetSubNode(LSUB+1)))
2243 pS->WriteUChar( LINE ); //line
2244 HandleNodes(pTemp,nLevel+1);
2245 pS->WriteUChar( END ); //line
2247 else
2248 pS->WriteUChar( LINE|0x10 );
2249 if (nullptr != (pTemp = pNode->GetSubNode(LSUP+1)))
2251 pS->WriteUChar( LINE ); //line
2252 HandleNodes(pTemp,nLevel+1);
2253 pS->WriteUChar( END ); //line
2255 else
2256 pS->WriteUChar( LINE|0x10 );
2257 pS->WriteUChar( END );
2258 nVariation=0xff;
2262 sal_uInt8 nVariation2=HandleCScript(pNode,nullptr,nLevel);
2264 if (nullptr != (pTemp = pNode->GetSubNode(0)))
2266 HandleNodes(pTemp,nLevel+1);
2269 if (nVariation2 != 0xff)
2270 pS->WriteUChar( END );
2272 if (nullptr != (pNode->GetSubNode(RSUP+1)))
2274 nVariation=0;
2275 if (pNode->GetSubNode(RSUB+1))
2276 nVariation=2;
2278 else if (nullptr != pNode->GetSubNode(RSUB+1))
2279 nVariation=1;
2281 if (nVariation!=0xff)
2283 pS->WriteUChar( TMPL ); //Template
2284 pS->WriteUChar( 0x0F ); //selector
2285 pS->WriteUChar( nVariation );
2286 pS->WriteUChar( 0x00 ); //options
2287 pS->WriteUChar( 0x0B );
2289 if (nullptr != (pTemp = pNode->GetSubNode(RSUB+1)))
2291 pS->WriteUChar( LINE ); //line
2292 HandleNodes(pTemp,nLevel+1);
2293 pS->WriteUChar( END ); //line
2295 else
2296 pS->WriteUChar( LINE|0x10 );
2297 if (nullptr != (pTemp = pNode->GetSubNode(RSUP+1)))
2299 pS->WriteUChar( LINE ); //line
2300 HandleNodes(pTemp,nLevel+1);
2301 pS->WriteUChar( END ); //line
2303 else
2304 pS->WriteUChar( LINE|0x10 );
2305 pS->WriteUChar( END ); //line
2308 //After subscript mathtype will keep the size of
2309 //normal text at the subscript size, sigh.
2310 pS->WriteUChar( 0x0A );
2314 void MathType::HandleFractions(SmNode *pNode,int nLevel)
2316 SmNode *pTemp;
2317 pS->WriteUChar( TMPL ); //Template
2318 pS->WriteUChar( 0x0E ); //selector
2319 pS->WriteUChar( 0x00 ); //variation
2320 pS->WriteUChar( 0x00 ); //options
2322 pS->WriteUChar( 0x0A );
2323 pS->WriteUChar( LINE ); //line
2324 if (nullptr != (pTemp = pNode->GetSubNode(0)))
2325 HandleNodes(pTemp,nLevel+1);
2326 pS->WriteUChar( END );
2328 pS->WriteUChar( 0x0A );
2329 pS->WriteUChar( LINE ); //line
2330 if (nullptr != (pTemp = pNode->GetSubNode(2)))
2331 HandleNodes(pTemp,nLevel+1);
2332 pS->WriteUChar( END );
2334 pS->WriteUChar( END );
2338 void MathType::HandleBrace(SmNode *pNode,int nLevel)
2340 SmNode *pTemp;
2341 SmNode *pLeft=pNode->GetSubNode(0);
2342 SmNode *pRight=pNode->GetSubNode(2);
2344 pS->WriteUChar( TMPL ); //Template
2345 bIsReInterpBrace=false;
2346 sal_uInt8 nBSpec=0x10;
2347 auto nLoc = pS->Tell();
2348 if (pLeft)
2350 switch (pLeft->GetToken().eType)
2352 case TLANGLE:
2353 pS->WriteUChar( tmANGLE ); //selector
2354 pS->WriteUChar( 0 ); //variation
2355 pS->WriteUChar( 0 ); //options
2356 break;
2357 case TLBRACE:
2358 pS->WriteUChar( tmBRACE ); //selector
2359 pS->WriteUChar( 0 ); //variation
2360 pS->WriteUChar( 0 ); //options
2361 nBSpec+=3;
2362 break;
2363 case TLBRACKET:
2364 pS->WriteUChar( tmBRACK ); //selector
2365 pS->WriteUChar( 0 ); //variation
2366 pS->WriteUChar( 0 ); //options
2367 nBSpec+=3;
2368 break;
2369 case TLFLOOR:
2370 pS->WriteUChar( tmFLOOR ); //selector
2371 pS->WriteUChar( 0 ); //variation
2372 pS->WriteUChar( 0 ); //options
2373 break;
2374 case TLLINE:
2375 pS->WriteUChar( tmBAR ); //selector
2376 pS->WriteUChar( 0 ); //variation
2377 pS->WriteUChar( 0 ); //options
2378 nBSpec+=3;
2379 break;
2380 case TLDLINE:
2381 pS->WriteUChar( tmDBAR ); //selector
2382 pS->WriteUChar( 0 ); //variation
2383 pS->WriteUChar( 0 ); //options
2384 break;
2385 default:
2386 pS->WriteUChar( tmPAREN ); //selector
2387 pS->WriteUChar( 0 ); //variation
2388 pS->WriteUChar( 0 ); //options
2389 nBSpec+=3;
2390 break;
2394 if (nullptr != (pTemp = pNode->GetSubNode(1)))
2396 pS->WriteUChar( LINE ); //line
2397 HandleNodes(pTemp,nLevel+1);
2398 pS->WriteUChar( END ); //options
2400 nSpec=nBSpec;
2401 if (pLeft)
2402 HandleNodes(pLeft,nLevel+1);
2403 if (bIsReInterpBrace)
2405 auto nLoc2 = pS->Tell();
2406 pS->Seek(nLoc);
2407 pS->WriteUChar( 0x2D );
2408 pS->Seek(nLoc2);
2409 pS->WriteUChar( CHAR );
2410 pS->WriteUChar( 0x96 );
2411 pS->WriteUInt16( 0xEC07 );
2412 bIsReInterpBrace=false;
2414 if (pRight)
2415 HandleNodes(pRight,nLevel+1);
2416 nSpec=0x0;
2417 pS->WriteUChar( END );
2421 void MathType::HandleVerticalBrace(SmNode *pNode,int nLevel)
2423 SmNode *pTemp;
2424 pS->WriteUChar( TMPL ); //Template
2425 if (pNode->GetToken().eType == TUNDERBRACE)
2426 pS->WriteUChar( tmLHBRACE ); //selector
2427 else
2428 pS->WriteUChar( tmUHBRACE ); //selector
2429 pS->WriteUChar( 0 ); //variation
2430 pS->WriteUChar( 0 ); //options
2432 if (nullptr != (pTemp = pNode->GetSubNode(0)))
2434 pS->WriteUChar( LINE ); //line
2435 HandleNodes(pTemp,nLevel+1);
2436 pS->WriteUChar( END ); //options
2439 if (nullptr != (pTemp = pNode->GetSubNode(2)))
2441 pS->WriteUChar( LINE ); //line
2442 HandleNodes(pTemp,nLevel+1);
2443 pS->WriteUChar( END ); //options
2445 pS->WriteUChar( END );
2448 void MathType::HandleOperator(SmNode *pNode,int nLevel)
2450 if (HandleLim(pNode,nLevel))
2451 return;
2453 sal_uInt64 nPos;
2454 sal_uInt8 nVariation;
2456 switch (pNode->GetToken().eType)
2458 case TIINT:
2459 case TIIINT:
2460 case TLINT:
2461 case TLLINT:
2462 case TLLLINT:
2463 nVariation=HandleCScript(pNode->GetSubNode(0),
2464 pNode->GetSubNode(1),nLevel,&nPos,false);
2465 break;
2466 default:
2467 nVariation=HandleCScript(pNode->GetSubNode(0),
2468 pNode->GetSubNode(1),nLevel,&nPos);
2469 break;
2472 sal_uInt8 nOldVariation=nVariation;
2473 sal_uInt8 nIntVariation=nVariation;
2475 sal_uInt64 nPos2=0;
2476 if (nVariation != 0xff)
2478 nPos2 = pS->Tell();
2479 pS->Seek(nPos);
2480 if (nVariation == 2)
2482 nIntVariation=0;
2483 nVariation = 1;
2485 else if (nVariation == 0)
2486 nVariation = 1;
2487 else if (nVariation == 1)
2488 nVariation = 0;
2490 else
2492 nVariation = 2;
2493 nIntVariation=0;
2495 pS->WriteUChar( TMPL );
2496 switch(pNode->GetToken().eType)
2498 case TINT:
2499 case TINTD:
2500 if (nOldVariation != 0xff)
2501 pS->WriteUChar( 0x18 ); //selector
2502 else
2503 pS->WriteUChar( 0x15 ); //selector
2504 pS->WriteUChar( nIntVariation ); //variation
2505 break;
2506 case TIINT:
2507 if (nOldVariation != 0xff)
2509 pS->WriteUChar( 0x19 );
2510 pS->WriteUChar( 0x01 );
2512 else
2514 pS->WriteUChar( 0x16 );
2515 pS->WriteUChar( 0x00 );
2517 break;
2518 case TIIINT:
2519 if (nOldVariation != 0xff)
2521 pS->WriteUChar( 0x1a );
2522 pS->WriteUChar( 0x01 );
2524 else
2526 pS->WriteUChar( 0x17 );
2527 pS->WriteUChar( 0x00 );
2529 break;
2530 case TLINT:
2531 if (nOldVariation != 0xff)
2533 pS->WriteUChar( 0x18 );
2534 pS->WriteUChar( 0x02 );
2536 else
2538 pS->WriteUChar( 0x15 );
2539 pS->WriteUChar( 0x03 );
2541 break;
2542 case TLLINT:
2543 if (nOldVariation != 0xff)
2545 pS->WriteUChar( 0x19 );
2546 pS->WriteUChar( 0x00 );
2548 else
2550 pS->WriteUChar( 0x16 );
2551 pS->WriteUChar( 0x02 );
2553 break;
2554 case TLLLINT:
2555 if (nOldVariation != 0xff)
2557 pS->WriteUChar( 0x1a );
2558 pS->WriteUChar( 0x00 );
2560 else
2562 pS->WriteUChar( 0x17 );
2563 pS->WriteUChar( 0x02 );
2565 break;
2566 case TSUM:
2567 default:
2568 pS->WriteUChar( 0x1d );
2569 pS->WriteUChar( nVariation );
2570 break;
2571 case TPROD:
2572 pS->WriteUChar( 0x1f );
2573 pS->WriteUChar( nVariation );
2574 break;
2575 case TCOPROD:
2576 pS->WriteUChar( 0x21 );
2577 pS->WriteUChar( nVariation );
2578 break;
2580 pS->WriteUChar( 0 ); //options
2582 if (nPos2)
2583 pS->Seek(nPos2);
2584 else
2586 pS->WriteUChar( LINE ); //line
2587 HandleNodes(pNode->GetSubNode(1),nLevel+1);
2588 pS->WriteUChar( END ); //line
2589 pS->WriteUChar( LINE|0x10 );
2590 pS->WriteUChar( LINE|0x10 );
2593 pS->WriteUChar( 0x0D );
2594 switch(pNode->GetToken().eType)
2596 case TSUM:
2597 default:
2598 pS->WriteUChar( CHAR );
2599 pS->WriteUChar( 0x86 );
2600 pS->WriteUInt16( 0x2211 );
2601 break;
2602 case TPROD:
2603 pS->WriteUChar( CHAR );
2604 pS->WriteUChar( 0x86 );
2605 pS->WriteUInt16( 0x220F );
2606 break;
2607 case TCOPROD:
2608 pS->WriteUChar( CHAR );
2609 pS->WriteUChar( 0x8B );
2610 pS->WriteUInt16( 0x2210 );
2611 break;
2612 case TIIINT:
2613 case TLLLINT:
2614 pS->WriteUChar( CHAR );
2615 pS->WriteUChar( 0x86 );
2616 pS->WriteUInt16( 0x222B );
2617 [[fallthrough]];
2618 case TIINT:
2619 case TLLINT:
2620 pS->WriteUChar( CHAR );
2621 pS->WriteUChar( 0x86 );
2622 pS->WriteUInt16( 0x222B );
2623 [[fallthrough]];
2624 case TINT:
2625 case TINTD:
2626 case TLINT:
2627 pS->WriteUChar( CHAR );
2628 pS->WriteUChar( 0x86 );
2629 pS->WriteUInt16( 0x222B );
2630 break;
2632 pS->WriteUChar( END );
2633 pS->WriteUChar( 0x0A );
2637 bool MathType::HandlePile(int &rSetAlign, int nLevel, sal_uInt8 nSelector, sal_uInt8 nVariation)
2639 sal_uInt8 nVAlign;
2640 pS->ReadUChar( nHAlign );
2641 pS->ReadUChar( nVAlign );
2643 HandleAlign(nHAlign, rSetAlign);
2645 rRet.append(" stack {\n");
2646 bool bRet = HandleRecords( nLevel+1, nSelector, nVariation, -1, -1 );
2647 int nRemoveFrom = rRet.getLength() >= 3 ? rRet.getLength() - 3 : 0;
2648 rRet.remove(nRemoveFrom, 2);
2649 rRet.append("} ");
2651 while (rSetAlign)
2653 rRet.append("} ");
2654 rSetAlign--;
2656 return bRet;
2659 bool MathType::HandleMatrix(int nLevel, sal_uInt8 nSelector, sal_uInt8 nVariation)
2661 sal_uInt8 nH_just,nV_just,nRows,nCols,nVAlign;
2662 pS->ReadUChar( nVAlign );
2663 pS->ReadUChar( nH_just );
2664 pS->ReadUChar( nV_just );
2665 pS->ReadUChar( nRows );
2666 pS->ReadUChar( nCols );
2667 if (!pS->good())
2668 return false;
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.append(" sup {}");
2763 nPostSup = sPost.getLength();
2765 sPost.insert(nPostSup-1," ' ");
2766 nPostSup += 3;
2767 break;
2768 case 0x06:
2769 if (!nPostSup)
2771 sPost.append(" sup {}");
2772 nPostSup = sPost.getLength();
2774 sPost.insert(nPostSup-1," '' ");
2775 nPostSup += 4;
2776 break;
2777 case 0x07:
2778 if (!nPostlSup)
2780 sPost.append(" lsup {}");
2781 nPostlSup = sPost.getLength();
2783 sPost.insert(nPostlSup-1," ' ");
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.append(" sup {}");
2805 nPostSup = sPost.getLength();
2807 sPost.insert(nPostSup-1," ''' ");
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(0);
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 = "";
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 + "{");
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("}}" + 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 == 0x2F) || (nArse == 0x2225))
3091 nBias = 0x2; //typeface
3092 else if ((nArse > 0x2000) || (nArse == 0x00D7))
3093 nBias = 0x6; //typeface
3094 else if (nArse == 0x3d1)
3095 nBias = 0x4;
3096 else if ((nArse > 0xFF) && ((nArse < 0x393) || (nArse > 0x3c9)))
3097 nBias = 0xB; //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 TWIDEHARPOON: //Not Exportable
3186 case TWIDETILDE: //Not Exportable
3187 case TWIDEHAT: //Not Exportable
3188 break;
3189 case TUNDERLINE:
3190 nOldPending = StartTemplate(0x10);
3191 break;
3192 case TOVERLINE: //If the next node is not text
3193 //or text with more than one char
3194 if (!pIsText ||
3195 pIsText->GetToken().eType != TTEXT ||
3196 pIsText->GetText().getLength() > 1)
3197 nOldPending = StartTemplate(0x11);
3198 break;
3199 default:
3200 nPendingAttributes++;
3201 break;
3205 if (pIsText)
3206 HandleNodes(pIsText,nLevel+1);
3208 if (pTemp)
3210 switch (pTemp->GetToken().eType)
3212 case TWIDEVEC:
3213 case TUNDERLINE:
3214 EndTemplate(nOldPending);
3215 break;
3216 case TOVERLINE:
3217 if (!pIsText ||
3218 pIsText->GetToken().eType != TTEXT ||
3219 pIsText->GetText().getLength() > 1)
3220 EndTemplate(nOldPending);
3221 break;
3222 default:
3223 break;
3227 //if there was no suitable place to put the attribute,
3228 //then we have to just give up on it
3229 if (nPendingAttributes)
3230 nPendingAttributes--;
3231 else
3233 if ((nInsertion != 0) && nullptr != (pTemp = pNode->GetSubNode(0)))
3235 auto nPos = pS->Tell();
3236 nInsertion--;
3237 pS->Seek(nInsertion);
3238 switch(pTemp->GetToken().eType)
3240 case TACUTE: //Not Exportable
3241 case TGRAVE: //Not Exportable
3242 case TCIRCLE: //Not Exportable
3243 break;
3244 case TCDOT:
3245 pS->WriteUChar( 2 );
3246 break;
3247 case TDDOT:
3248 pS->WriteUChar( 3 );
3249 break;
3250 case TDDDOT:
3251 pS->WriteUChar( 4 );
3252 break;
3253 case TTILDE:
3254 pS->WriteUChar( 8 );
3255 break;
3256 case THAT:
3257 pS->WriteUChar( 9 );
3258 break;
3259 case TVEC:
3260 pS->WriteUChar( 11 );
3261 break;
3262 case TOVERSTRIKE:
3263 pS->WriteUChar( 16 );
3264 break;
3265 case TOVERLINE:
3266 if (pIsText &&
3267 (pIsText->GetToken().eType == TTEXT &&
3268 pIsText->GetText().getLength() == 1))
3269 pS->WriteUChar( 17 );
3270 break;
3271 case TBREVE:
3272 pS->WriteUChar( 20 );
3273 break;
3274 case TWIDEVEC:
3275 case TWIDEHARPOON:
3276 case TUNDERLINE:
3277 case TWIDETILDE:
3278 case TWIDEHAT:
3279 break;
3280 case TBAR:
3281 pS->WriteUChar( 17 );
3282 break;
3283 default:
3284 pS->WriteUChar( 2 );
3285 break;
3287 pS->Seek(nPos);
3292 void MathType::HandleText(SmNode *pNode)
3294 SmTextNode *pTemp = static_cast<SmTextNode *>(pNode);
3295 for(sal_Int32 i=0;i<pTemp->GetText().getLength();i++)
3297 if (nPendingAttributes &&
3298 (i == ((pTemp->GetText().getLength()+1)/2)-1))
3300 pS->WriteUChar( 0x22 ); //char, with attributes right
3301 //after the character
3303 else
3304 pS->WriteUChar( CHAR );
3306 sal_uInt8 nFace = 0x1;
3307 if (pNode->GetFont().GetItalic() == ITALIC_NORMAL)
3308 nFace = 0x3;
3309 else if (pNode->GetFont().GetWeight() == WEIGHT_BOLD)
3310 nFace = 0x7;
3311 pS->WriteUChar( nFace+128 ); //typeface
3312 sal_uInt16 nChar = pTemp->GetText()[i];
3313 pS->WriteUInt16( SmTextNode::ConvertSymbolToUnicode(nChar) );
3315 //Mathtype can only have these sort of character
3316 //attributes on a single character, starmath can put them
3317 //anywhere, when the entity involved is a text run this is
3318 //a large effort to place the character attribute on the
3319 //central mathtype character so that it does pretty much
3320 //what the user probably has in mind. The attributes
3321 //filled in here are dummy ones which are replaced in the
3322 //ATTRIBUTE handler if a suitable location for the
3323 //attributes was found here. Unfortunately it is
3324 //possible for starmath to place character attributes on
3325 //entities which cannot occur in mathtype e.g. a Summation
3326 //symbol so these attributes may be lost
3327 if (nPendingAttributes &&
3328 (i == ((pTemp->GetText().getLength()+1)/2)-1))
3330 pS->WriteUChar( EMBEL );
3331 while (nPendingAttributes)
3333 pS->WriteUChar( 2 );
3334 //wedge the attributes in here and clear
3335 //the pending stack
3336 nPendingAttributes--;
3338 nInsertion=pS->Tell();
3339 pS->WriteUChar( END ); //end embel
3340 pS->WriteUChar( END ); //end embel
3345 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportMathType(SvStream &rStream)
3347 OUStringBuffer sText;
3348 MathType aEquation(sText);
3349 bool bRet = false;
3352 bRet = aEquation.Parse(&rStream);
3354 catch (const std::out_of_range&)
3357 return bRet;
3360 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */