Bump version to 6.4-15
[LibreOffice.git] / starmath / source / mathtype.cxx
blobcd33f289dda7948001a2a12d4d8ee9275c3c803c
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>
26 #include <sal/log.hxx>
28 #include "eqnolefilehdr.hxx"
29 #include <node.hxx>
31 void MathType::Init()
33 //These are the default MathType sizes
34 aSizeTable.push_back(12);
35 aSizeTable.push_back(8);
36 aSizeTable.push_back(6);
37 aSizeTable.push_back(24);
38 aSizeTable.push_back(10);
39 aSizeTable.push_back(12);
40 aSizeTable.push_back(12);
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 for(sal_uInt8 i=1;i<=11;i++)
50 aFont.nTface = i+128;
51 switch (i)
53 default:
54 aFont.nStyle=0;
55 break;
56 case 3:
57 case 4:
58 aFont.nStyle=1;
59 break;
60 case 7:
61 aFont.nStyle=2;
62 break;
64 aUserStyles.insert(aFont);
69 /*ToDo replace with table rather than switch, returns
70 sal_True in the case that the char is just a char, and
71 sal_False if the character is an operator which must not be
72 placed inside the quote sequence designed to protect
73 against being parsed as a keyword
75 General solution required to force starmath to handle
76 unicode math chars the way it handles its own math
77 chars rather than handle them as text as it will do
78 for the default case below, i.e. incorrect spacing
79 between math symbols and ordinary text e.g. 1=2 rather
80 than 1 = 2
82 bool MathType::LookupChar(sal_Unicode nChar,OUStringBuffer &rRet,sal_uInt8 nVersion,
83 sal_uInt8 nTypeFace)
85 bool bRet=false;
86 const char *pC = nullptr;
87 switch(nChar)
89 case 0x0000:
90 pC = " none ";
91 break;
92 case 0x00ac:
93 pC = " neg ";
94 break;
95 case 0x00b1:
96 pC = " +- ";
97 break;
98 case '(':
99 pC = " \\( ";
100 break;
101 case ')':
102 pC = " \\) ";
103 break;
104 case '[':
105 pC = " \\[ ";
106 break;
107 case ']':
108 pC = " \\] ";
109 break;
110 case '.':
111 pC = " \".\" ";
112 break;
113 case 0xae:
114 if ((nVersion < 3) && (nTypeFace == 0x86))
115 pC = " rightarrow ";
116 else
118 rRet.append(OUStringChar(nChar));
119 bRet=true;
121 break;
122 case 0x00fb:
123 if ((nVersion < 3) && (nTypeFace == 0x81))
124 nChar = 0xDF;
125 rRet.append(OUStringChar(nChar));
126 bRet=true;
127 break;
128 case 'a':
129 if ((nVersion < 3) && (nTypeFace == 0x84))
130 nChar = 0x3b1;
131 rRet.append(OUStringChar(nChar));
132 bRet=true;
133 break;
134 case 'b':
135 if ((nVersion < 3) && (nTypeFace == 0x84))
136 nChar = 0x3b2;
137 rRet.append(OUStringChar(nChar));
138 bRet=true;
139 break;
140 case 'l':
141 if ((nVersion < 3) && (nTypeFace == 0x84))
142 nChar = 0x3bb;
143 rRet.append(OUStringChar(nChar));
144 bRet=true;
145 break;
146 case 'n':
147 if ((nVersion < 3) && (nTypeFace == 0x84))
148 nChar = 0x3bd;
149 rRet.append(OUStringChar(nChar));
150 bRet=true;
151 break;
152 case 'r':
153 if ((nVersion < 3) && (nTypeFace == 0x84))
154 nChar = 0x3c1;
155 rRet.append(OUStringChar(nChar));
156 bRet=true;
157 break;
158 case 'D':
159 if ((nVersion < 3) && (nTypeFace == 0x84))
160 nChar = 0x394;
161 rRet.append(OUStringChar(nChar));
162 bRet=true;
163 break;
164 case 0xa9:
165 if ((nVersion < 3) && (nTypeFace == 0x82))
166 nChar = '\'';
167 rRet.append(OUStringChar(nChar));
168 bRet=true;
169 break;
170 case 0x00f1:
171 if ((nVersion < 3) && (nTypeFace == 0x86))
172 pC = " \\rangle ";
173 else
175 rRet.append(OUStringChar(nChar));
176 bRet=true;
178 break;
179 case 0x00a3:
180 if ((nVersion < 3) && (nTypeFace == 0x86))
181 pC = " <= ";
182 else
184 rRet.append(OUStringChar(nChar));
185 bRet=true;
187 break;
188 case 0x00de:
189 if ((nVersion < 3) && (nTypeFace == 0x86))
190 pC = " drarrow ";
191 else
193 rRet.append(OUStringChar(nChar));
194 bRet=true;
196 break;
197 case 0x0057:
198 if ((nVersion < 3) && (nTypeFace == 0x85))
199 pC = " %OMEGA ";
200 else
202 rRet.append(OUStringChar(nChar));
203 bRet=true;
205 break;
206 case 0x007b:
207 pC = " lbrace ";
208 break;
209 case 0x007c:
210 pC = " \\lline ";
211 break;
212 case 0x007d:
213 pC = " rbrace ";
214 break;
215 case 0x007e:
216 pC = " \"~\" ";
217 break;
218 case 0x2224:
219 pC = " ndivides ";
220 break;
221 case 0x2225:
222 pC = " parallel ";
223 break;
224 case 0x00d7:
225 if (nVersion < 3)
226 pC = " cdot ";
227 else
228 pC = " times ";
229 break;
230 case 0x00f7:
231 pC = " div ";
232 break;
233 case 0x019b:
234 pC = " lambdabar ";
235 break;
236 case 0x2026:
237 pC = " dotslow ";
238 break;
239 case 0x2022:
240 pC = " cdot ";
241 break;
242 case 0x2102:
243 pC = " setC ";
244 break;
245 case 0x210f:
246 pC = " hbar ";
247 break;
248 case 0x2111:
249 pC = " Im ";
250 break;
251 case 0x2115:
252 pC = " setN ";
253 break;
254 case 0x2118:
255 pC = " wp ";
256 break;
257 case 0x211a:
258 pC = " setQ ";
259 break;
260 case 0x211c:
261 pC = " Re ";
262 break;
263 case 0x211d:
264 pC = " setR ";
265 break;
266 case 0x2124:
267 pC = " setZ ";
268 break;
269 case 0x2135:
270 pC = " aleph ";
271 break;
272 case 0x2190:
273 pC = " leftarrow ";
274 break;
275 case 0x2191:
276 pC = " uparrow ";
277 break;
278 case 0x2192:
279 pC = " rightarrow ";
280 break;
281 case 0x0362:
282 pC = " widevec ";
283 break;
284 case 0x2193:
285 pC = " downarrow ";
286 break;
287 case 0x21d0:
288 pC = " dlarrow ";
289 break;
290 case 0x21d2:
291 pC = " drarrow ";
292 break;
293 case 0x21d4:
294 pC = " dlrarrow ";
295 break;
296 case 0x2200:
297 pC = " forall ";
298 break;
299 case 0x2202:
300 pC = " partial ";
301 break;
302 case 0x2203:
303 pC = " exists ";
304 break;
305 case 0x2204:
306 pC = " notexists ";
307 break;
308 case 0x2205:
309 pC = " emptyset ";
310 break;
311 case 0x2207:
312 pC = " nabla ";
313 break;
314 case 0x2208: // in
315 case 0x2209: // notin
316 rRet.append(" func ").append(OUStringChar(nChar)).append(" ");
317 break;
318 case 0x220d: // owns
319 rRet.append(u" func \u220b ");
320 break;
321 case 0x220f:
322 pC = " prod ";
323 break;
324 case 0x2210:
325 pC = " coprod ";
326 break;
327 case 0x2211:
328 pC = " sum ";
329 break;
330 case 0x2212:
331 pC = " - ";
332 break;
333 case 0x2213:
334 pC = " -+ ";
335 break;
336 case 0x2217:
337 pC = " * ";
338 break;
339 case 0x2218:
340 pC = " circ ";
341 break;
342 case 0x221d:
343 pC = " prop ";
344 break;
345 case 0x221e:
346 pC = " infinity ";
347 break;
348 case 0x2227:
349 pC = " and ";
350 break;
351 case 0x2228:
352 pC = " or ";
353 break;
354 case 0x2229:
355 pC = " intersection ";
356 break;
357 case 0x222a:
358 pC = " union ";
359 break;
360 case 0x222b:
361 pC = " int ";
362 break;
363 case 0x222c:
364 pC = " iint ";
365 break;
366 case 0x222d:
367 pC = " iiint ";
368 break;
369 case 0x222e:
370 pC = " lint ";
371 break;
372 case 0x222f:
373 pC = " llint ";
374 break;
375 case 0x2230:
376 pC = " lllint ";
377 break;
378 case 0x2245:
379 pC = " simeq ";
380 break;
381 case 0x2248:
382 pC = " approx ";
383 break;
384 case 0x2260:
385 pC = " <> ";
386 break;
387 case 0x2261:
388 pC = " equiv ";
389 break;
390 case 0x2264:
391 pC = " <= ";
392 break;
393 case 0x2265:
394 pC = " >= ";
395 break;
397 case 0x227A:
398 pC = " prec ";
399 break;
400 case 0x227B:
401 pC = " succ ";
402 break;
403 case 0x227C:
404 pC = " preccurlyeq ";
405 break;
406 case 0x227D:
407 pC = " succcurlyeq ";
408 break;
409 case 0x227E:
410 pC = " precsim ";
411 break;
412 case 0x227F:
413 pC = " succsim ";
414 break;
415 case 0x2280:
416 pC = " nprec ";
417 break;
418 case 0x2281:
419 pC = " nsucc ";
420 break;
422 case 0x2282: // subset
423 case 0x2283: // supset
424 case 0x2284: // nsubset
425 case 0x2285: // nsupset
426 case 0x2286: // subseteq
427 case 0x2287: // supseteq
428 case 0x2288: // nsubseteq
429 case 0x2289: // nsupseteq
430 case 0x22b2: // NORMAL SUBGROUP OF
431 case 0x22b3: // CONTAINS AS NORMAL SUBGROUP
432 rRet.append(" func ").append(OUStringChar(nChar)).append(" ");
433 break;
434 case 0x22a5:
435 pC = " ortho ";
436 break;
437 case 0x22c5:
438 pC = " cdot ";
439 break;
440 case 0x22ee:
441 pC = " dotsvert ";
442 break;
443 case 0x22ef:
444 pC = " dotsaxis ";
445 break;
446 case 0x22f0:
447 pC = " dotsup ";
448 break;
449 case 0x22f1:
450 pC = " dotsdown ";
451 break;
452 case MS_LANGLE:
453 case MS_LMATHANGLE:
454 pC = " langle ";
455 break;
456 case MS_RANGLE:
457 case MS_RMATHANGLE:
458 pC = " rangle ";
459 break;
460 case 0x301a:
461 pC = " ldbracket ";
462 break;
463 case 0x301b:
464 pC = " rdbracket ";
465 break;
466 case 0xe083:
467 rRet.append("+");
468 bRet=true;
469 break;
470 case '^':
471 case 0xe091:
472 pC = " widehat ";
473 break;
474 case 0xe096:
475 pC = " widetilde ";
476 break;
477 case 0xe098:
478 pC = " widevec ";
479 break;
480 case 0xE421:
481 pC = " geslant ";
482 break;
483 case 0xE425:
484 pC = " leslant ";
485 break;
486 case 0xeb01: //no space
487 case 0xeb08: //normal space
488 bRet=true;
489 break;
490 case 0xef04: //tiny space
491 case 0xef05: //tiny space
492 case 0xeb02: //small space
493 case 0xeb04: //medium space
494 rRet.append("`");
495 break;
496 case 0xeb05: //large space
497 rRet.append("~");
498 break;
499 case 0x3a9:
500 pC = " %OMEGA ";
501 break;
502 default:
503 rRet.append(OUStringChar(nChar));
504 bRet=true;
505 break;
507 if (pC)
508 rRet.appendAscii(pC);
509 return bRet;
512 void MathTypeFont::AppendStyleToText(OUString &rRet)
514 const char *pC = nullptr;
515 switch (nStyle)
517 default:
518 case 0:
519 break;
520 case 1:
521 pC = " ital ";
522 break;
523 case 2:
524 pC = " bold ";
525 break;
526 case 3:
527 pC = " bold italic";
528 break;
530 if (pC)
531 rRet += OUString::createFromAscii( pC );
534 void MathType::TypeFaceToString(OUString &rTxt,sal_uInt8 nFace)
536 MathTypeFont aFont(nFace);
537 MathTypeFontSet::iterator aItr = aUserStyles.find(aFont);
538 if (aItr != aUserStyles.end())
539 aFont.nStyle = aItr->nStyle;
540 aFont.AppendStyleToText(rTxt);
543 bool MathType::Parse(SotStorage *pStor)
545 tools::SvRef<SotStorageStream> xSrc = pStor->OpenSotStream(
546 "Equation Native",
547 StreamMode::STD_READ);
548 if ( (!xSrc.is()) || (ERRCODE_NONE != xSrc->GetError()))
549 return false;
550 return Parse(xSrc.get());
553 bool MathType::Parse(SvStream* pStream)
555 pS = pStream;
556 pS->SetEndian( SvStreamEndian::LITTLE );
558 EQNOLEFILEHDR aHdr;
559 aHdr.Read(pS);
560 sal_uInt8 nProdVersion;
561 sal_uInt8 nProdSubVersion;
562 sal_uInt8 nPlatform;
563 sal_uInt8 nProduct;
564 pS->ReadUChar( nVersion );
565 pS->ReadUChar( nPlatform );
566 pS->ReadUChar( nProduct );
567 pS->ReadUChar( nProdVersion );
568 pS->ReadUChar( nProdSubVersion );
570 if (nVersion > 3) // allow only supported versions of MathType to be parsed
571 return false;
573 bool bRet = HandleRecords(0);
574 //little crude hack to close occasionally open expressions
575 //a sophisticated system to determine what expressions are
576 //opened is required, but this is as much work as rewriting
577 //starmaths internals.
578 rRet.append("{}");
580 return bRet;
583 static void lcl_PrependDummyTerm(OUStringBuffer &rRet, sal_Int32 &rTextStart)
585 if ((rTextStart < rRet.getLength()) &&
586 (rRet[rTextStart] == '=') &&
587 ((rTextStart == 0) || (rRet[ rTextStart-1 ] == '{'))
590 rRet.insert(rTextStart, " {}");
591 rTextStart+=3;
595 static void lcl_AppendDummyTerm(OUStringBuffer &rRet)
597 bool bOk=false;
598 for(int nI=rRet.getLength()-1;nI >= 0; nI--)
600 sal_Int32 nIdx = sal::static_int_cast< sal_Int32 >(nI);
601 sal_Unicode nChar = rRet[nIdx];
602 if (nChar == ' ')
603 continue;
604 if (rRet[nIdx] != '{')
605 bOk=true;
606 break;
608 if (!bOk) //No term, use dummy
609 rRet.append(" {}");
612 void MathType::HandleNudge()
614 sal_uInt8 nXNudge;
615 pS->ReadUChar( nXNudge );
616 sal_uInt8 nYNudge;
617 pS->ReadUChar( nYNudge );
618 if (nXNudge == 128 && nYNudge == 128)
620 sal_uInt16 nXLongNudge;
621 sal_uInt16 nYLongNudge;
622 pS->ReadUInt16( nXLongNudge );
623 pS->ReadUInt16( nYLongNudge );
627 /* Fabulously complicated as many tokens have to be reordered and generally
628 * moved around from mathtypes paradigm to starmaths. */
629 bool MathType::HandleRecords(int nLevel, sal_uInt8 nSelector,
630 sal_uInt8 nVariation, int nMatrixRows, int nMatrixCols)
632 //depth-protect
633 if (nLevel > 1024)
634 return false;
636 sal_uInt8 nTag,nRecord;
637 sal_uInt8 nTabType,nTabStops;
638 sal_uInt16 nTabOffset;
639 int i, newline=0;
640 bool bSilent=false;
641 int nPart=0;
642 OUString sPush,sMainTerm;
643 int nSetSize=0,nSetAlign=0;
644 int nCurRow=0,nCurCol=0;
645 bool bOpenString=false;
646 sal_Int32 nTextStart = 0;
647 sal_Int32 nSubSupStartPos = 0;
648 sal_Int32 nLastTemplateBracket=-1;
649 bool bRet = true;
653 nTag = 0;
654 pS->ReadUChar( nTag );
655 nRecord = nTag&0x0F;
657 /*MathType strings can of course include words which
658 *are StarMath keywords, the simplest solution is
659 to escape strings of greater than len 1 with double
660 quotes to avoid scanning the TokenTable for matches
662 Unfortunately it may turn out that the string gets
663 split during the handling of a character emblishment
664 so this special case must be handled in the
665 character handler case 2:
667 if ((nRecord == CHAR) && (!bOpenString))
669 bOpenString=true;
670 nTextStart = rRet.getLength();
672 else if ((nRecord != CHAR) && bOpenString)
674 bOpenString=false;
675 if ((rRet.getLength() - nTextStart) > 1)
677 OUString aStr;
678 TypeFaceToString(aStr,nTypeFace);
679 aStr += "\"";
680 rRet.insert(nTextStart,aStr);
681 rRet.append("\"");
683 else if (nRecord == END && !rRet.isEmpty())
685 sal_Unicode cChar = 0;
686 sal_Int32 nI = rRet.getLength()-1;
687 while (nI && ((cChar = rRet[nI]) == ' '))
688 --nI;
689 if ((cChar == '=') || (cChar == '+') || (cChar == '-'))
690 rRet.append("{}");
694 switch(nRecord)
696 case LINE:
698 if (xfLMOVE(nTag))
699 HandleNudge();
701 if (newline>0)
702 rRet.append("\nnewline\n");
703 if (!(xfNULL(nTag)))
705 switch (nSelector)
707 case tmANGLE:
708 if (nVariation==0)
709 rRet.append(" langle ");
710 else if (nVariation==1)
711 rRet.append(" \\langle ");
712 break;
713 case tmPAREN:
714 if (nVariation==0)
715 rRet.append(" left (");
716 else if (nVariation==1)
717 rRet.append("\\(");
718 break;
719 case tmBRACE:
720 if ((nVariation==0) || (nVariation==1))
721 rRet.append(" left lbrace ");
722 else
723 rRet.append(" left none ");
724 break;
725 case tmBRACK:
726 if (nVariation==0)
727 rRet.append(" left [");
728 else if (nVariation==1)
729 rRet.append("\\[");
730 break;
731 case tmLBLB:
732 case tmLBRP:
733 rRet.append(" \\[");
734 break;
735 case tmBAR:
736 if (nVariation==0)
737 rRet.append(" lline ");
738 else if (nVariation==1)
739 rRet.append(" \\lline ");
740 break;
741 case tmDBAR:
742 if (nVariation==0)
743 rRet.append(" ldline ");
744 else if (nVariation==1)
745 rRet.append(" \\ldline ");
746 break;
747 case tmFLOOR:
748 if (nVariation == 0 || nVariation & 0x01) // tvFENCE_L
749 rRet.append(" left lfloor ");
750 else
751 rRet.append(" left none ");
752 break;
753 case tmCEILING:
754 if (nVariation==0)
755 rRet.append(" lceil ");
756 else if (nVariation==1)
757 rRet.append(" \\lceil ");
758 break;
759 case tmRBRB:
760 case tmRBLB:
761 rRet.append(" \\]");
762 break;
763 case tmLPRB:
764 rRet.append(" \\(");
765 break;
766 case tmROOT:
767 if (nPart == 0)
769 if (nVariation == 0)
770 rRet.append(" sqrt");
771 else
773 rRet.append(" nroot");
774 sPush = rRet.makeStringAndClear();
777 rRet.append(" {");
778 break;
779 case tmFRACT:
780 if (nPart == 0)
781 rRet.append(" { ");
784 if (nPart == 1)
785 rRet.append(" over ");
786 rRet.append(" {");
787 break;
788 case tmSCRIPT:
789 nSubSupStartPos = rRet.getLength();
790 if ((nVariation == 0) ||
791 ((nVariation == 2) && (nPart==1)))
793 lcl_AppendDummyTerm(rRet);
794 rRet.append(" rSup");
796 else if ((nVariation == 1) ||
797 ((nVariation == 2) && (nPart==0)))
799 lcl_AppendDummyTerm(rRet);
800 rRet.append(" rSub");
802 rRet.append(" {");
803 break;
804 case tmUBAR:
805 if (nVariation == 0)
806 rRet.append(" {underline ");
807 else if (nVariation == 1)
808 rRet.append(" {underline underline ");
809 rRet.append(" {");
810 break;
811 case tmOBAR:
812 if (nVariation == 0)
813 rRet.append(" {overline ");
814 else if (nVariation == 1)
815 rRet.append(" {overline overline ");
816 rRet.append(" {");
817 break;
818 case tmLARROW:
819 if (nPart == 0)
821 if (nVariation == 0)
822 rRet.append(" widevec ");//left arrow above
823 else if (nVariation == 1)
824 rRet.append(" widevec ");//left arrow below
825 rRet.append(" {");
827 break;
828 case tmRARROW:
829 if (nPart == 0)
831 if (nVariation == 0)
832 rRet.append(" widevec ");//right arrow above
833 else if (nVariation == 1)
834 rRet.append(" widevec ");//right arrow below
835 rRet.append(" {");
837 break;
838 case tmBARROW:
839 if (nPart == 0)
841 if (nVariation == 0)
842 rRet.append(" widevec ");//double arrow above
843 else if (nVariation == 1)
844 rRet.append(" widevec ");//double arrow below
845 rRet.append(" {");
847 break;
848 case tmSINT:
849 if (nPart == 0)
851 if ((nVariation == 3) || (nVariation == 4))
852 rRet.append(" lInt");
853 else
854 rRet.append(" Int");
855 if ( (nVariation != 0) && (nVariation != 3))
857 sPush = rRet.makeStringAndClear();
860 if (((nVariation == 1) ||
861 (nVariation == 4)) && (nPart==1))
862 rRet.append(" rSub");
863 else if ((nVariation == 2) && (nPart==2))
864 rRet.append(" rSup");
865 else if ((nVariation == 2) && (nPart==1))
866 rRet.append(" rSub");
867 rRet.append(" {");
868 break;
869 case tmDINT:
870 if (nPart == 0)
872 if ((nVariation == 2) || (nVariation == 3))
873 rRet.append(" llInt");
874 else
875 rRet.append(" iInt");
876 if ( (nVariation != 0) && (nVariation != 2))
878 sPush = rRet.makeStringAndClear();
881 if (((nVariation == 1) ||
882 (nVariation == 3)) && (nPart==1))
883 rRet.append(" rSub");
884 rRet.append(" {");
885 break;
886 case tmTINT:
887 if (nPart == 0)
889 if ((nVariation == 2) || (nVariation == 3))
890 rRet.append(" lllInt");
891 else
892 rRet.append(" iiInt");
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 tmSSINT:
904 if (nPart == 0)
906 if (nVariation == 2)
907 rRet.append(" lInt");
908 else
909 rRet.append(" Int");
910 sPush = rRet.makeStringAndClear();
912 if (((nVariation == 1) ||
913 (nVariation == 2)) && (nPart==1))
914 rRet.append(" cSub");
915 else if ((nVariation == 0) && (nPart==2))
916 rRet.append(" cSup");
917 else if ((nVariation == 0) && (nPart==1))
918 rRet.append(" cSub");
919 rRet.append(" {");
920 break;
921 case tmDSINT:
922 if (nPart == 0)
924 if (nVariation == 0)
925 rRet.append(" llInt");
926 else
927 rRet.append(" iInt");
928 sPush = rRet.makeStringAndClear();
930 if (nPart==1)
931 rRet.append(" cSub");
932 rRet.append(" {");
933 break;
934 case tmTSINT:
935 if (nPart == 0)
937 if (nVariation == 0)
938 rRet.append(" lllInt");
939 else
940 rRet.append(" iiInt");
941 sPush = rRet.makeStringAndClear();
943 if (nPart==1)
944 rRet.append(" cSub");
945 rRet.append(" {");
946 break;
947 case tmUHBRACE:
948 case tmLHBRACE:
949 rRet.append(" {");
950 break;
951 case tmSUM:
952 if (nPart == 0)
954 rRet.append(" Sum");
955 if (nVariation != 2)
957 sPush = rRet.makeStringAndClear();
960 if ((nVariation == 0) && (nPart==1))
961 rRet.append(" cSub");
962 else if ((nVariation == 1) && (nPart==2))
963 rRet.append(" cSup");
964 else if ((nVariation == 1) && (nPart==1))
965 rRet.append(" cSub");
966 rRet.append(" {");
967 break;
968 case tmISUM:
969 if (nPart == 0)
971 rRet.append(" Sum");
972 sPush = rRet.makeStringAndClear();
974 if ((nVariation == 0) && (nPart==1))
975 rRet.append(" rSub");
976 else if ((nVariation == 1) && (nPart==2))
977 rRet.append(" rSup");
978 else if ((nVariation == 1) && (nPart==1))
979 rRet.append(" rSub");
980 rRet.append(" {");
981 break;
982 case tmPROD:
983 if (nPart == 0)
985 rRet.append(" Prod");
986 if (nVariation != 2)
988 sPush = rRet.makeStringAndClear();
991 if ((nVariation == 0) && (nPart==1))
992 rRet.append(" cSub");
993 else if ((nVariation == 1) && (nPart==2))
994 rRet.append(" cSup");
995 else if ((nVariation == 1) && (nPart==1))
996 rRet.append(" cSub");
997 rRet.append(" {");
998 break;
999 case tmIPROD:
1000 if (nPart == 0)
1002 rRet.append(" Prod");
1003 sPush = rRet.makeStringAndClear();
1005 if ((nVariation == 0) && (nPart==1))
1006 rRet.append(" rSub");
1007 else if ((nVariation == 1) && (nPart==2))
1008 rRet.append(" rSup");
1009 else if ((nVariation == 1) && (nPart==1))
1010 rRet.append(" rSub");
1011 rRet.append(" {");
1012 break;
1013 case tmCOPROD:
1014 if (nPart == 0)
1016 rRet.append(" coProd");
1017 if (nVariation != 2)
1019 sPush = rRet.makeStringAndClear();
1022 if ((nVariation == 0) && (nPart==1))
1023 rRet.append(" cSub");
1024 else if ((nVariation == 1) && (nPart==2))
1025 rRet.append(" cSup");
1026 else if ((nVariation == 1) && (nPart==1))
1027 rRet.append(" cSub");
1028 rRet.append(" {");
1029 break;
1030 case tmICOPROD:
1031 if (nPart == 0)
1033 rRet.append(" coProd");
1034 sPush = rRet.makeStringAndClear();
1036 if ((nVariation == 0) && (nPart==1))
1037 rRet.append(" rSub");
1038 else if ((nVariation == 1) && (nPart==2))
1039 rRet.append(" rSup");
1040 else if ((nVariation == 1) && (nPart==1))
1041 rRet.append(" rSub");
1042 rRet.append(" {");
1043 break;
1044 case tmUNION:
1045 if (nPart == 0)
1047 rRet.append(" union"); //union
1048 if (nVariation != 2)
1050 sPush = rRet.makeStringAndClear();
1053 if ((nVariation == 0) && (nPart==1))
1054 rRet.append(" cSub");
1055 else if ((nVariation == 1) && (nPart==2))
1056 rRet.append(" cSup");
1057 else if ((nVariation == 1) && (nPart==1))
1058 rRet.append(" cSub");
1059 rRet.append(" {");
1060 break;
1061 case tmIUNION:
1062 if (nPart == 0)
1064 rRet.append(" union"); //union
1065 sPush = rRet.makeStringAndClear();
1067 if ((nVariation == 0) && (nPart==1))
1068 rRet.append(" rSub");
1069 else if ((nVariation == 1) && (nPart==2))
1070 rRet.append(" rSup");
1071 else if ((nVariation == 1) && (nPart==1))
1072 rRet.append(" rSub");
1073 rRet.append(" {");
1074 break;
1075 case tmINTER:
1076 if (nPart == 0)
1078 rRet.append(" intersect"); //intersect
1079 if (nVariation != 2)
1081 sPush = rRet.makeStringAndClear();
1084 if ((nVariation == 0) && (nPart==1))
1085 rRet.append(" cSub");
1086 else if ((nVariation == 1) && (nPart==2))
1087 rRet.append(" cSup");
1088 else if ((nVariation == 1) && (nPart==1))
1089 rRet.append(" cSub");
1090 rRet.append(" {");
1091 break;
1092 case tmIINTER:
1093 if (nPart == 0)
1095 rRet.append(" intersect"); //intersect
1096 sPush = rRet.makeStringAndClear();
1098 if ((nVariation == 0) && (nPart==1))
1099 rRet.append(" rSub");
1100 else if ((nVariation == 1) && (nPart==2))
1101 rRet.append(" rSup");
1102 else if ((nVariation == 1) && (nPart==1))
1103 rRet.append(" rSub");
1104 rRet.append(" {");
1105 break;
1106 case tmLIM:
1107 if ((nVariation == 0) && (nPart==1))
1108 rRet.append(" cSup");
1109 else if ((nVariation == 1) && (nPart==1))
1110 rRet.append(" cSub");
1111 else if ((nVariation == 2) && (nPart==1))
1112 rRet.append(" cSub");
1113 else if ((nVariation == 2) && (nPart==2))
1114 rRet.append(" cSup");
1115 rRet.append(" {");
1116 break;
1117 case tmLDIV:
1118 if (nVariation == 0)
1120 if (nPart == 0)
1122 sPush = rRet.makeStringAndClear();
1125 rRet.append(" {");
1126 if (nVariation == 0)
1128 if (nPart == 1)
1129 rRet.append("alignr ");
1131 if (nPart == 0)
1132 rRet.append("\\lline ");
1133 if (nVariation == 1)
1134 rRet.append("overline ");
1135 break;
1136 case tmSLFRACT:
1137 rRet.append(" {");
1138 break;
1139 case tmINTOP:
1140 if (nPart == 0)
1142 sPush = rRet.makeStringAndClear();
1144 if ((nVariation == 0) && (nPart==0))
1145 rRet.append(" rSup");
1146 else if ((nVariation == 2) && (nPart==1))
1147 rRet.append(" rSup");
1148 else if ((nVariation == 1) && (nPart==0))
1149 rRet.append(" rSub");
1150 else if ((nVariation == 2) && (nPart==0))
1151 rRet.append(" rSub");
1152 rRet.append(" {");
1153 break;
1154 case tmSUMOP:
1155 if (nPart == 0)
1157 sPush = rRet.makeStringAndClear();
1159 if ((nVariation == 0) && (nPart==0))
1160 rRet.append(" cSup");
1161 else if ((nVariation == 2) && (nPart==1))
1162 rRet.append(" cSup");
1163 else if ((nVariation == 1) && (nPart==0))
1164 rRet.append(" cSub");
1165 else if ((nVariation == 2) && (nPart==0))
1166 rRet.append(" cSub");
1167 rRet.append(" {");
1168 break;
1169 case tmLSCRIPT:
1170 if (nPart == 0)
1171 rRet.append("\"\"");
1172 if ((nVariation == 0)
1173 || ((nVariation == 2) && (nPart==1)))
1174 rRet.append(" lSup");
1175 else if ((nVariation == 1)
1176 || ((nVariation == 2) && (nPart==0)))
1177 rRet.append(" lSub");
1178 rRet.append(" {");
1179 break;
1180 case tmDIRAC:
1181 if (nVariation==0)
1183 if (nPart == 0)
1184 rRet.append(" langle ");
1186 else if (nVariation==1)
1188 rRet.append(" \\langle ");
1189 newline--;
1191 else if (nVariation==2)
1193 rRet.append(" \\lline ");
1194 newline--;
1196 break;
1197 case tmUARROW:
1198 if (nVariation == 0)
1199 rRet.append(" widevec ");//left below
1200 else if (nVariation == 1)
1201 rRet.append(" widevec ");//right below
1202 else if (nVariation == 2)
1203 rRet.append(" widevec ");//double headed below
1204 rRet.append(" {");
1205 break;
1206 case tmOARROW:
1207 if (nVariation == 0)
1208 rRet.append(" widevec ");//left above
1209 else if (nVariation == 1)
1210 rRet.append(" widevec ");//right above
1211 else if (nVariation == 2)
1212 rRet.append(" widevec ");//double headed above
1213 rRet.append(" {");
1214 break;
1215 default:
1216 break;
1218 sal_Int16 nOldCurSize=nCurSize;
1219 sal_Int32 nSizeStartPos = rRet.getLength();
1220 HandleSize( nLSize, nDSize, nSetSize );
1221 bRet = HandleRecords( nLevel+1 );
1222 while (nSetSize)
1224 bool bOk=false;
1225 sal_Int32 nI = rRet.lastIndexOf('{');
1226 if (nI != -1)
1228 for(nI=nI+1;nI<rRet.getLength();nI++)
1229 if (rRet[nI] != ' ')
1231 bOk=true;
1232 break;
1235 else
1236 bOk=true;
1238 if (bOk)
1239 rRet.append("} ");
1240 else if (rRet.getLength() > nSizeStartPos)
1241 rRet = rRet.truncate(nSizeStartPos);
1242 nSetSize--;
1243 nCurSize=nOldCurSize;
1247 HandleMatrixSeparator(nMatrixRows,nMatrixCols,
1248 nCurCol,nCurRow);
1250 switch (nSelector)
1252 case tmANGLE:
1253 if (nVariation==0)
1254 rRet.append(" rangle ");
1255 else if (nVariation==2)
1256 rRet.append(" \\rangle ");
1257 break;
1258 case tmPAREN:
1259 if (nVariation==0)
1260 rRet.append(" right )");
1261 else if (nVariation==2)
1262 rRet.append("\\)");
1263 break;
1264 case tmBRACE:
1265 if ((nVariation==0) || (nVariation==2))
1266 rRet.append(" right rbrace ");
1267 else
1268 rRet.append(" right none ");
1269 break;
1270 case tmBRACK:
1271 if (nVariation==0)
1272 rRet.append(" right ]");
1273 else if (nVariation==2)
1274 rRet.append("\\]");
1275 break;
1276 case tmBAR:
1277 if (nVariation==0)
1278 rRet.append(" rline ");
1279 else if (nVariation==2)
1280 rRet.append(" \\rline ");
1281 break;
1282 case tmDBAR:
1283 if (nVariation==0)
1284 rRet.append(" rdline ");
1285 else if (nVariation==2)
1286 rRet.append(" \\rdline ");
1287 break;
1288 case tmFLOOR:
1289 if (nVariation == 0 || nVariation & 0x02) // tvFENCE_R
1290 rRet.append(" right rfloor ");
1291 else
1292 rRet.append(" right none ");
1293 break;
1294 case tmCEILING:
1295 if (nVariation==0)
1296 rRet.append(" rceil ");
1297 else if (nVariation==2)
1298 rRet.append(" \\rceil ");
1299 break;
1300 case tmLBLB:
1301 case tmRBLB:
1302 rRet.append("\\[");
1303 break;
1304 case tmRBRB:
1305 case tmLPRB:
1306 rRet.append("\\]");
1307 break;
1308 case tmROOT:
1309 rRet.append("} ");
1310 if (nVariation == 1)
1312 if (nPart == 0)
1314 newline--;
1315 sMainTerm = rRet.makeStringAndClear();
1317 else if (nPart == 1)
1319 rRet.insert(0, sPush);
1320 rRet.append(sMainTerm);
1321 sPush.clear();
1322 sMainTerm.clear();
1325 else
1327 if (nPart == 0)
1328 newline--;
1330 nPart++;
1331 break;
1332 case tmLBRP:
1333 rRet.append("\\)");
1334 break;
1335 case tmFRACT:
1336 rRet.append("} ");
1337 if (nPart == 0)
1338 newline--;
1339 else
1340 rRet.append("} ");
1341 nPart++;
1342 break;
1343 case tmSCRIPT:
1345 if ((nPart == 0) &&
1346 ((nVariation == 2) || (nVariation == 1)))
1347 newline--;
1349 bool bOk=false;
1350 sal_Int32 nI = rRet.lastIndexOf('{');
1351 if (nI != -1)
1353 for(nI=nI+1;nI<rRet.getLength();nI++)
1354 if (rRet[nI] != ' ')
1356 bOk=true;
1357 break;
1360 else
1361 bOk=true;
1363 if (bOk)
1364 rRet.append("} ");
1365 else if (rRet.getLength() > nSubSupStartPos)
1366 rRet = rRet.truncate(nSubSupStartPos);
1367 nPart++;
1369 break;
1370 case tmLSCRIPT:
1371 if ((nPart == 0) &&
1372 ((nVariation == 2) || (nVariation == 1)))
1373 newline--;
1374 rRet.append("} ");
1375 nPart++;
1376 break;
1377 case tmUARROW:
1378 case tmOARROW:
1379 rRet.append("} ");
1380 break;
1381 case tmUBAR:
1382 case tmOBAR:
1383 rRet.append("}} ");
1384 break;
1385 case tmLARROW:
1386 case tmRARROW:
1387 case tmBARROW:
1388 if (nPart == 0)
1390 newline--;
1391 rRet.append("} ");
1393 nPart++;
1394 break;
1395 case tmUHBRACE:
1396 rRet.append("} ");
1397 if (nPart == 0)
1399 newline--;
1400 rRet.append("overbrace");
1402 nPart++;
1403 break;
1404 case tmLHBRACE:
1405 rRet.append("} ");
1406 if (nPart == 0)
1408 newline--;
1409 rRet.append("underbrace");
1411 nPart++;
1412 break;
1413 case tmLIM:
1414 if (nPart==0)
1415 newline--;
1416 else if ((nPart==1) &&
1417 ((nVariation == 2) || (nVariation == 1)))
1418 newline--;
1419 rRet.append("} ");
1420 nPart++;
1421 break;
1422 case tmLDIV:
1423 rRet.append("} ");
1424 if (nVariation == 0)
1426 if (nPart == 0)
1428 sMainTerm = rRet.makeStringAndClear();
1430 else if (nPart == 1)
1432 rRet.insert(0, sPush);
1433 rRet.append(" over ").append(sMainTerm);
1434 sPush.clear();
1435 sMainTerm.clear();
1438 if (nPart == 0)
1439 newline--;
1440 nPart++;
1441 break;
1442 case tmSLFRACT:
1443 rRet.append("} ");
1444 if (nPart == 0)
1446 newline--;
1447 switch (nVariation)
1449 case 1:
1450 rRet.append("slash");
1451 break;
1452 default:
1453 rRet.append("wideslash");
1454 break;
1457 nPart++;
1458 break;
1459 case tmSUM:
1460 case tmISUM:
1461 case tmPROD:
1462 case tmIPROD:
1463 case tmCOPROD:
1464 case tmICOPROD:
1465 case tmUNION:
1466 case tmIUNION:
1467 case tmINTER:
1468 case tmIINTER:
1469 rRet.append("} ");
1470 if (nPart == 0)
1472 if (nVariation != 2)
1474 sMainTerm = rRet.makeStringAndClear();
1476 newline--;
1478 else if ((nPart == 1) && (nVariation == 0))
1480 rRet.insert(0, sPush);
1481 rRet.append(sMainTerm);
1482 sPush.clear();
1483 sMainTerm.clear();
1484 newline--;
1486 else if ((nPart == 1) && (nVariation == 1))
1487 newline--;
1488 else if ((nPart == 2) && (nVariation == 1))
1490 rRet.insert(0, sPush);
1491 rRet.append(sMainTerm);
1492 sPush.clear();
1493 sMainTerm.clear();
1494 newline--;
1496 nPart++;
1497 break;
1498 case tmSINT:
1499 rRet.append("} ");
1500 if (nPart == 0)
1502 if ((nVariation != 0) && (nVariation != 3))
1504 sMainTerm = rRet.makeStringAndClear();
1506 newline--;
1508 else if ((nPart == 1) &&
1509 ((nVariation == 1) || (nVariation==4)))
1511 rRet.insert(0, sPush);
1512 rRet.append(sMainTerm);
1513 sPush.clear();
1514 sMainTerm.clear();
1515 newline--;
1517 else if ((nPart == 1) && (nVariation == 2))
1518 newline--;
1519 else if ((nPart == 2) && (nVariation == 2))
1521 rRet.insert(0, sPush);
1522 rRet.append(sMainTerm);
1523 sPush.clear();
1524 sMainTerm.clear();
1525 newline--;
1527 nPart++;
1528 break;
1529 case tmDINT:
1530 case tmTINT:
1531 rRet.append("} ");
1532 if (nPart == 0)
1534 if ((nVariation != 0) && (nVariation != 2))
1536 sMainTerm = rRet.makeStringAndClear();
1538 newline--;
1540 else if ((nPart == 1) &&
1541 ((nVariation == 1) || (nVariation==3)))
1543 rRet.insert(0, sPush);
1544 rRet.append(sMainTerm);
1545 sPush.clear();
1546 sMainTerm.clear();
1547 newline--;
1549 nPart++;
1550 break;
1551 case tmSSINT:
1552 rRet.append("} ");
1553 if (nPart == 0)
1555 sMainTerm = rRet.makeStringAndClear();
1556 newline--;
1558 else if ((nPart == 1) &&
1559 ((nVariation == 1) || (nVariation==2)))
1561 rRet.insert(0, sPush);
1562 rRet.append(sMainTerm);
1563 sPush.clear();
1564 sMainTerm.clear();
1565 newline--;
1567 else if ((nPart == 1) && (nVariation == 0))
1568 newline--;
1569 else if ((nPart == 2) && (nVariation == 0))
1571 rRet.insert(0, sPush);
1572 rRet.append(sMainTerm);
1573 sPush.clear();
1574 sMainTerm.clear();
1575 newline--;
1577 nPart++;
1578 break;
1579 case tmDSINT:
1580 case tmTSINT:
1581 rRet.append("} ");
1582 if (nPart == 0)
1584 sMainTerm = rRet.makeStringAndClear();
1585 newline--;
1587 else if (nPart == 1)
1589 rRet.insert(0, sPush);
1590 rRet.append(sMainTerm);
1591 sPush.clear();
1592 sMainTerm.clear();
1593 newline--;
1595 nPart++;
1596 break;
1597 case tmINTOP:
1598 case tmSUMOP:
1599 rRet.append("} ");
1601 if ((nPart == 0) &&
1602 ((nVariation == 0) || (nVariation == 1)))
1604 sMainTerm = rRet.makeStringAndClear();
1605 newline--;
1607 else if ((nPart == 0) && (nVariation == 2))
1608 newline--;
1609 else if ((nPart == 1) && (nVariation == 2))
1611 sMainTerm = rRet.makeStringAndClear();
1612 newline--;
1614 else if ((nPart == 2) || ((nPart == 1) &&
1615 (nVariation == 0 || nVariation == 1)))
1617 rRet.insert(0, sPush);
1618 rRet.append(sMainTerm);
1619 sPush.clear();
1620 sMainTerm.clear();
1622 nPart++;
1623 break;
1624 case tmDIRAC:
1625 if (nVariation==0)
1627 if (nPart == 0)
1629 newline--; //there is another term to arrive
1630 rRet.append(" mline ");
1632 else
1633 rRet.append(" rangle ");
1635 else if (nVariation==1)
1636 rRet.append(" \\lline ");
1637 else if (nVariation==2)
1638 rRet.append(" \\rangle ");
1639 nPart++;
1640 break;
1641 default:
1642 break;
1644 bSilent = true; //Skip the optional brackets and/or
1645 //symbols that follow some of these
1646 //records. Foo Data.
1648 /*In matrices and piles we cannot separate equation
1649 *lines with the newline keyword*/
1650 if (nMatrixCols==0)
1651 newline++;
1654 break;
1655 case CHAR:
1656 if (xfLMOVE(nTag))
1657 HandleNudge();
1658 bRet = HandleChar( nTextStart, nSetSize, nLevel, nTag, nSelector, nVariation, bSilent );
1659 break;
1660 case TMPL:
1661 if (xfLMOVE(nTag))
1662 HandleNudge();
1663 bRet = HandleTemplate( nLevel, nSelector, nVariation, nLastTemplateBracket );
1664 break;
1665 case PILE:
1666 if (xfLMOVE(nTag))
1667 HandleNudge();
1668 bRet = HandlePile( nSetAlign, nLevel, nSelector, nVariation );
1669 HandleMatrixSeparator( nMatrixRows, nMatrixCols, nCurCol, nCurRow );
1670 break;
1671 case MATRIX:
1672 if (xfLMOVE(nTag))
1673 HandleNudge();
1674 bRet = HandleMatrix( nLevel, nSelector, nVariation );
1675 HandleMatrixSeparator( nMatrixRows, nMatrixCols, nCurCol, nCurRow );
1676 break;
1677 case EMBEL:
1678 if (xfLMOVE(nTag))
1679 HandleNudge();
1680 HandleEmblishments();
1681 break;
1682 case RULER:
1683 pS->ReadUChar( nTabStops );
1684 for (i=0;i<nTabStops;i++)
1686 pS->ReadUChar( nTabType );
1687 pS->ReadUInt16( nTabOffset );
1689 SAL_WARN("starmath", "Not seen in the wild Equation Ruler Field");
1690 break;
1691 case FONT:
1693 MathTypeFont aFont;
1694 pS->ReadUChar( aFont.nTface );
1696 The typeface number is the negative (which makes it
1697 positive) of the typeface value (unbiased) that appears in
1698 CHAR records that might follow a given FONT record
1700 aFont.nTface = 128-aFont.nTface;
1701 pS->ReadUChar( aFont.nStyle );
1702 aUserStyles.insert(aFont);
1703 // read font name
1704 while(true)
1706 sal_Char nChar8(0);
1707 pS->ReadChar( nChar8 );
1708 if (nChar8 == 0)
1709 break;
1712 break;
1713 case SIZE:
1714 HandleSetSize();
1715 break;
1716 case 10:
1717 case 11:
1718 case 12:
1719 case 13:
1720 case 14:
1721 nLSize=nRecord-10;
1722 break;
1723 case END:
1724 default:
1725 break;
1728 while (nRecord != END && !pS->eof());
1729 while (nSetSize)
1731 rRet.append("}");
1732 nSetSize--;
1734 return bRet;
1737 /*Simply determine if we are at the end of a record or the end of a line,
1738 *with fiddly logic to see if we are in a matrix or a pile or neither
1740 Note we cannot tell until after the event that this is the last entry
1741 of a pile, so we must strip the last separator of a pile after this
1742 is detected in the PILE handler
1744 void MathType::HandleMatrixSeparator(int nMatrixRows,int nMatrixCols,
1745 int &rCurCol,int &rCurRow)
1747 if (nMatrixRows==0)
1748 return;
1750 if (rCurCol == nMatrixCols-1)
1752 if (rCurRow != nMatrixRows-1)
1753 rRet.append(" {} ##\n");
1754 if (nMatrixRows!=-1)
1756 rCurCol=0;
1757 rCurRow++;
1760 else
1762 rRet.append(" {} # ");
1763 if (nMatrixRows!=-1)
1764 rCurCol++;
1765 else
1766 rRet.append("\n");
1770 /* set the alignment of the following term, but starmath currently
1771 * cannot handle vertical alignment */
1772 void MathType::HandleAlign(sal_uInt8 nHorAlign, int &rSetAlign)
1774 switch(nHorAlign)
1776 case 1:
1777 default:
1778 rRet.append("alignl {");
1779 break;
1780 case 2:
1781 rRet.append("alignc {");
1782 break;
1783 case 3:
1784 rRet.append("alignr {");
1785 break;
1787 rSetAlign++;
1790 /* set size of text, complexity due to overuse of signedness as a flag
1791 * indicator by mathtype file format*/
1792 bool MathType::HandleSize(sal_Int16 nLstSize,sal_Int16 nDefSize, int &rSetSize)
1794 const sal_Int16 nDefaultSize = 12;
1795 bool bRet=false;
1796 if (nLstSize < 0)
1798 if ((-nLstSize/32 != nDefaultSize) && (-nLstSize/32 != nCurSize))
1800 if (rSetSize)
1802 rSetSize--;
1803 rRet.append("}");
1804 bRet=true;
1806 if (-nLstSize/32 != nLastSize)
1808 nLastSize = nCurSize;
1809 rRet.append(" size ");
1810 rRet.append(OUString::number(-nLstSize/32));
1811 rRet.append("{");
1812 bRet=true;
1813 rSetSize++;
1815 nCurSize = -nLstSize/32;
1818 else
1820 /*sizetable should theoretically be filled with the default sizes
1821 *of the various font groupings matching starmaths equivalents
1822 in aTypeFaces, and a test would be done to see if the new font
1823 size would be the same as what starmath would have chosen for
1824 itself anyway in which case the size setting could be ignored*/
1825 nLstSize = aSizeTable.at(nLstSize);
1826 nLstSize = nLstSize + nDefSize;
1827 if (nLstSize != nCurSize)
1829 if (rSetSize)
1831 rSetSize--;
1832 rRet.append("}");
1833 bRet=true;
1835 if (nLstSize != nLastSize)
1837 nLastSize = nCurSize;
1838 rRet.append(" size ");
1839 rRet.append(OUString::number(nLstSize));
1840 rRet.append("{");
1841 bRet=true;
1842 rSetSize++;
1844 nCurSize = nLstSize;
1847 return bRet;
1850 bool MathType::ConvertFromStarMath( SfxMedium& rMedium )
1852 if (!pTree)
1853 return false;
1855 SvStream *pStream = rMedium.GetOutStream();
1856 if ( pStream )
1858 tools::SvRef<SotStorage> pStor = new SotStorage( pStream, false );
1860 SvGlobalName aGName(MSO_EQUATION3_CLASSID);
1861 pStor->SetClass( aGName, SotClipboardFormatId::NONE, "Microsoft Equation 3.0");
1863 static sal_uInt8 const aCompObj[] = {
1864 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
1865 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0xCE, 0x02, 0x00,
1866 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
1867 0x00, 0x00, 0x00, 0x46, 0x17, 0x00, 0x00, 0x00,
1868 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
1869 0x74, 0x20, 0x45, 0x71, 0x75, 0x61, 0x74, 0x69,
1870 0x6F, 0x6E, 0x20, 0x33, 0x2E, 0x30, 0x00, 0x0C,
1871 0x00, 0x00, 0x00, 0x44, 0x53, 0x20, 0x45, 0x71,
1872 0x75, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x0B,
1873 0x00, 0x00, 0x00, 0x45, 0x71, 0x75, 0x61, 0x74,
1874 0x69, 0x6F, 0x6E, 0x2E, 0x33, 0x00, 0xF4, 0x39,
1875 0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1876 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1878 tools::SvRef<SotStorageStream> xStor( pStor->OpenSotStream("\1CompObj"));
1879 xStor->WriteBytes(aCompObj, sizeof(aCompObj));
1881 static sal_uInt8 const aOle[] = {
1882 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
1883 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1884 0x00, 0x00, 0x00, 0x00
1886 tools::SvRef<SotStorageStream> xStor2( pStor->OpenSotStream("\1Ole"));
1887 xStor2->WriteBytes(aOle, sizeof(aOle));
1888 xStor.clear();
1889 xStor2.clear();
1891 tools::SvRef<SotStorageStream> xSrc = pStor->OpenSotStream("Equation Native");
1892 if ( (!xSrc.is()) || (ERRCODE_NONE != xSrc->GetError()))
1893 return false;
1895 pS = xSrc.get();
1896 pS->SetEndian( SvStreamEndian::LITTLE );
1898 pS->SeekRel(EQNOLEFILEHDR_SIZE); //Skip 28byte Header and fill it in later
1899 pS->WriteUChar( 0x03 );
1900 pS->WriteUChar( 0x01 );
1901 pS->WriteUChar( 0x01 );
1902 pS->WriteUChar( 0x03 );
1903 pS->WriteUChar( 0x00 );
1904 sal_uInt32 nSize = pS->Tell();
1905 nPendingAttributes=0;
1907 HandleNodes(pTree, 0);
1908 pS->WriteUChar( END );
1910 nSize = pS->Tell()-nSize;
1911 pS->Seek(0);
1912 EQNOLEFILEHDR aHdr(nSize+4+1);
1913 aHdr.Write(pS);
1915 pStor->Commit();
1918 return true;
1922 void MathType::HandleNodes(SmNode *pNode,int nLevel)
1924 switch(pNode->GetType())
1926 case SmNodeType::Attribut:
1927 HandleAttributes(pNode,nLevel);
1928 break;
1929 case SmNodeType::Text:
1930 HandleText(pNode);
1931 break;
1932 case SmNodeType::VerticalBrace:
1933 HandleVerticalBrace(pNode,nLevel);
1934 break;
1935 case SmNodeType::Brace:
1936 HandleBrace(pNode,nLevel);
1937 break;
1938 case SmNodeType::Oper:
1939 HandleOperator(pNode,nLevel);
1940 break;
1941 case SmNodeType::BinVer:
1942 HandleFractions(pNode,nLevel);
1943 break;
1944 case SmNodeType::Root:
1945 HandleRoot(pNode,nLevel);
1946 break;
1947 case SmNodeType::Special:
1949 SmTextNode *pText = static_cast<SmTextNode *>(pNode);
1950 //if the token str and the result text are the same then this
1951 //is to be seen as text, else assume it's a mathchar
1952 if (pText->GetText() == pText->GetToken().aText)
1953 HandleText(pText);
1954 else
1955 HandleMath(pText);
1957 break;
1958 case SmNodeType::Math:
1959 case SmNodeType::MathIdent:
1960 HandleMath(pNode);
1961 break;
1962 case SmNodeType::SubSup:
1963 HandleSubSupScript(pNode,nLevel);
1964 break;
1965 case SmNodeType::Expression:
1967 size_t nSize = pNode->GetNumSubNodes();
1968 for (size_t i = 0; i < nSize; ++i)
1970 if (SmNode *pTemp = pNode->GetSubNode(i))
1971 HandleNodes(pTemp,nLevel+1);
1973 break;
1975 case SmNodeType::Table:
1976 //Root Node, PILE equivalent, i.e. vertical stack
1977 HandleTable(pNode,nLevel);
1978 break;
1979 case SmNodeType::Matrix:
1980 HandleSmMatrix(static_cast<SmMatrixNode *>(pNode),nLevel);
1981 break;
1982 case SmNodeType::Line:
1984 pS->WriteUChar( 0x0a );
1985 pS->WriteUChar( LINE );
1986 size_t nSize = pNode->GetNumSubNodes();
1987 for (size_t i = 0; i < nSize; ++i)
1989 if (SmNode *pTemp = pNode->GetSubNode(i))
1990 HandleNodes(pTemp,nLevel+1);
1992 pS->WriteUChar( END );
1993 break;
1995 case SmNodeType::Align:
1996 HandleMAlign(pNode,nLevel);
1997 break;
1998 case SmNodeType::Blank:
1999 pS->WriteUChar( CHAR );
2000 pS->WriteUChar( 0x98 );
2001 if (pNode->GetToken().eType == TSBLANK)
2002 pS->WriteUInt16( 0xEB04 );
2003 else
2004 pS->WriteUInt16( 0xEB05 );
2005 break;
2006 default:
2008 size_t nSize = pNode->GetNumSubNodes();
2009 for (size_t i = 0; i < nSize; ++i)
2011 if (SmNode *pTemp = pNode->GetSubNode(i))
2012 HandleNodes(pTemp,nLevel+1);
2014 break;
2020 int MathType::StartTemplate(sal_uInt16 nSelector,sal_uInt16 nVariation)
2022 int nOldPending=nPendingAttributes;
2023 pS->WriteUChar( TMPL ); //Template
2024 pS->WriteUChar( nSelector ); //selector
2025 pS->WriteUChar( nVariation ); //variation
2026 pS->WriteUChar( 0x00 ); //options
2027 pS->WriteUChar( LINE );
2028 //there's just no way we can now handle any character
2029 //attributes (from mathtypes perspective) centered
2030 //over an expression but above template attribute
2031 //such as widevec and similar constructs
2032 //we have to drop them
2033 nPendingAttributes=0;
2034 return nOldPending;
2037 void MathType::EndTemplate(int nOldPendingAttributes)
2039 pS->WriteUChar( END ); //end line
2040 pS->WriteUChar( END ); //end template
2041 nPendingAttributes=nOldPendingAttributes;
2045 void MathType::HandleSmMatrix(SmMatrixNode *pMatrix,int nLevel)
2047 pS->WriteUChar( MATRIX );
2048 pS->WriteUChar( 0x00 ); //vAlign ?
2049 pS->WriteUChar( 0x00 ); //h_just
2050 pS->WriteUChar( 0x00 ); //v_just
2051 pS->WriteUChar( pMatrix->GetNumRows() ); //v_just
2052 pS->WriteUChar( pMatrix->GetNumCols() ); //v_just
2053 int nBytes=(pMatrix->GetNumRows()+1)*2/8;
2054 if (((pMatrix->GetNumRows()+1)*2)%8)
2055 nBytes++;
2056 for (int j = 0; j < nBytes; j++)
2057 pS->WriteUChar( 0x00 ); //row_parts
2058 nBytes=(pMatrix->GetNumCols()+1)*2/8;
2059 if (((pMatrix->GetNumCols()+1)*2)%8)
2060 nBytes++;
2061 for (int k = 0; k < nBytes; k++)
2062 pS->WriteUChar( 0x00 ); //col_parts
2063 size_t nSize = pMatrix->GetNumSubNodes();
2064 for (size_t i = 0; i < nSize; ++i)
2066 if (SmNode *pTemp = pMatrix->GetSubNode(i))
2068 pS->WriteUChar( LINE ); //line
2069 HandleNodes(pTemp,nLevel+1);
2070 pS->WriteUChar( END ); //end line
2073 pS->WriteUChar( END );
2077 //Root Node, PILE equivalent, i.e. vertical stack
2078 void MathType::HandleTable(SmNode *pNode,int nLevel)
2080 size_t nSize = pNode->GetNumSubNodes();
2081 //The root of the starmath is a table, if
2082 //we convert this them each iteration of
2083 //conversion from starmath to mathtype will
2084 //add an extra unnecessary level to the
2085 //mathtype output stack which would grow
2086 //without bound in a multi step conversion
2088 if (nLevel == 0)
2089 pS->WriteUChar( 0x0A ); //initial size
2091 if ( nLevel || (nSize >1))
2093 pS->WriteUChar( PILE );
2094 pS->WriteUChar( nHAlign ); //vAlign ?
2095 pS->WriteUChar( 0x01 ); //hAlign
2098 for (size_t i = 0; i < nSize; ++i)
2100 if (SmNode *pTemp = pNode->GetSubNode(i))
2102 pS->WriteUChar( LINE );
2103 HandleNodes(pTemp,nLevel+1);
2104 pS->WriteUChar( END );
2107 if (nLevel || (nSize>1))
2108 pS->WriteUChar( END );
2112 void MathType::HandleRoot(SmNode *pNode,int nLevel)
2114 SmNode *pTemp;
2115 pS->WriteUChar( TMPL ); //Template
2116 pS->WriteUChar( 0x0D ); //selector
2117 if (pNode->GetSubNode(0))
2118 pS->WriteUChar( 0x01 ); //variation
2119 else
2120 pS->WriteUChar( 0x00 ); //variation
2121 pS->WriteUChar( 0x00 ); //options
2123 if (nullptr != (pTemp = pNode->GetSubNode(2)))
2125 pS->WriteUChar( LINE ); //line
2126 HandleNodes(pTemp,nLevel+1);
2127 pS->WriteUChar( END );
2130 if (nullptr != (pTemp = pNode->GetSubNode(0)))
2132 pS->WriteUChar( LINE ); //line
2133 HandleNodes(pTemp,nLevel+1);
2134 pS->WriteUChar( END );
2136 else
2137 pS->WriteUChar( LINE|0x10 ); //dummy line
2140 pS->WriteUChar( END );
2143 sal_uInt8 MathType::HandleCScript(SmNode *pNode,SmNode *pContent,int nLevel,
2144 sal_uInt64 *pPos,bool bTest)
2146 sal_uInt8 nVariation2=0xff;
2148 if (bTest && pNode->GetSubNode(CSUP+1))
2150 nVariation2=0;
2151 if (pNode->GetSubNode(CSUB+1))
2152 nVariation2=2;
2154 else if (pNode->GetSubNode(CSUB+1))
2155 nVariation2=1;
2157 if (nVariation2!=0xff)
2159 if (pPos)
2160 *pPos = pS->Tell();
2161 pS->WriteUChar( TMPL ); //Template
2162 pS->WriteUChar( 0x2B ); //selector
2163 pS->WriteUChar( nVariation2 );
2164 pS->WriteUChar( 0x00 ); //options
2166 if (pContent)
2168 pS->WriteUChar( LINE ); //line
2169 HandleNodes(pContent,nLevel+1);
2170 pS->WriteUChar( END ); //line
2172 else
2173 pS->WriteUChar( LINE|0x10 );
2175 pS->WriteUChar( 0x0B );
2177 SmNode *pTemp;
2178 if (nullptr != (pTemp = pNode->GetSubNode(CSUB+1)))
2180 pS->WriteUChar( LINE ); //line
2181 HandleNodes(pTemp,nLevel+1);
2182 pS->WriteUChar( END ); //line
2184 else
2185 pS->WriteUChar( LINE|0x10 );
2186 if (bTest && nullptr != (pTemp = pNode->GetSubNode(CSUP+1)))
2188 pS->WriteUChar( LINE ); //line
2189 HandleNodes(pTemp,nLevel+1);
2190 pS->WriteUChar( END ); //line
2192 else
2193 pS->WriteUChar( LINE|0x10 );
2195 return nVariation2;
2200 Sub and Sup scripts and another problem area, StarMath
2201 can have all possible options used at the same time, whereas
2202 Mathtype cannot. The ordering of the nodes for each system
2203 is quite different as well leading to some complexity
2205 void MathType::HandleSubSupScript(SmNode *pNode,int nLevel)
2207 sal_uInt8 nVariation=0xff;
2208 if (pNode->GetSubNode(LSUP+1))
2210 nVariation=0;
2211 if (pNode->GetSubNode(LSUB+1))
2212 nVariation=2;
2214 else if ( nullptr != pNode->GetSubNode(LSUB+1) )
2215 nVariation=1;
2217 SmNode *pTemp;
2218 if (nVariation!=0xff)
2220 pS->WriteUChar( TMPL ); //Template
2221 pS->WriteUChar( 0x2c ); //selector
2222 pS->WriteUChar( nVariation );
2223 pS->WriteUChar( 0x00 ); //options
2224 pS->WriteUChar( 0x0B );
2226 if (nullptr != (pTemp = pNode->GetSubNode(LSUB+1)))
2228 pS->WriteUChar( LINE ); //line
2229 HandleNodes(pTemp,nLevel+1);
2230 pS->WriteUChar( END ); //line
2232 else
2233 pS->WriteUChar( LINE|0x10 );
2234 if (nullptr != (pTemp = pNode->GetSubNode(LSUP+1)))
2236 pS->WriteUChar( LINE ); //line
2237 HandleNodes(pTemp,nLevel+1);
2238 pS->WriteUChar( END ); //line
2240 else
2241 pS->WriteUChar( LINE|0x10 );
2242 pS->WriteUChar( END );
2243 nVariation=0xff;
2247 sal_uInt8 nVariation2=HandleCScript(pNode,nullptr,nLevel);
2249 if (nullptr != (pTemp = pNode->GetSubNode(0)))
2251 HandleNodes(pTemp,nLevel+1);
2254 if (nVariation2 != 0xff)
2255 pS->WriteUChar( END );
2257 if (nullptr != (pNode->GetSubNode(RSUP+1)))
2259 nVariation=0;
2260 if (pNode->GetSubNode(RSUB+1))
2261 nVariation=2;
2263 else if (nullptr != pNode->GetSubNode(RSUB+1))
2264 nVariation=1;
2266 if (nVariation!=0xff)
2268 pS->WriteUChar( TMPL ); //Template
2269 pS->WriteUChar( 0x0F ); //selector
2270 pS->WriteUChar( nVariation );
2271 pS->WriteUChar( 0x00 ); //options
2272 pS->WriteUChar( 0x0B );
2274 if (nullptr != (pTemp = pNode->GetSubNode(RSUB+1)))
2276 pS->WriteUChar( LINE ); //line
2277 HandleNodes(pTemp,nLevel+1);
2278 pS->WriteUChar( END ); //line
2280 else
2281 pS->WriteUChar( LINE|0x10 );
2282 if (nullptr != (pTemp = pNode->GetSubNode(RSUP+1)))
2284 pS->WriteUChar( LINE ); //line
2285 HandleNodes(pTemp,nLevel+1);
2286 pS->WriteUChar( END ); //line
2288 else
2289 pS->WriteUChar( LINE|0x10 );
2290 pS->WriteUChar( END ); //line
2293 //After subscript mathtype will keep the size of
2294 //normal text at the subscript size, sigh.
2295 pS->WriteUChar( 0x0A );
2299 void MathType::HandleFractions(SmNode *pNode,int nLevel)
2301 SmNode *pTemp;
2302 pS->WriteUChar( TMPL ); //Template
2303 pS->WriteUChar( 0x0E ); //selector
2304 pS->WriteUChar( 0x00 ); //variation
2305 pS->WriteUChar( 0x00 ); //options
2307 pS->WriteUChar( 0x0A );
2308 pS->WriteUChar( LINE ); //line
2309 if (nullptr != (pTemp = pNode->GetSubNode(0)))
2310 HandleNodes(pTemp,nLevel+1);
2311 pS->WriteUChar( END );
2313 pS->WriteUChar( 0x0A );
2314 pS->WriteUChar( LINE ); //line
2315 if (nullptr != (pTemp = pNode->GetSubNode(2)))
2316 HandleNodes(pTemp,nLevel+1);
2317 pS->WriteUChar( END );
2319 pS->WriteUChar( END );
2323 void MathType::HandleBrace(SmNode *pNode,int nLevel)
2325 SmNode *pTemp;
2326 SmNode *pLeft=pNode->GetSubNode(0);
2327 SmNode *pRight=pNode->GetSubNode(2);
2329 pS->WriteUChar( TMPL ); //Template
2330 bIsReInterpBrace=false;
2331 sal_uInt8 nBSpec=0x10;
2332 auto nLoc = pS->Tell();
2333 if (pLeft)
2335 switch (pLeft->GetToken().eType)
2337 case TLANGLE:
2338 pS->WriteUChar( tmANGLE ); //selector
2339 pS->WriteUChar( 0 ); //variation
2340 pS->WriteUChar( 0 ); //options
2341 break;
2342 case TLBRACE:
2343 pS->WriteUChar( tmBRACE ); //selector
2344 pS->WriteUChar( 0 ); //variation
2345 pS->WriteUChar( 0 ); //options
2346 nBSpec+=3;
2347 break;
2348 case TLBRACKET:
2349 pS->WriteUChar( tmBRACK ); //selector
2350 pS->WriteUChar( 0 ); //variation
2351 pS->WriteUChar( 0 ); //options
2352 nBSpec+=3;
2353 break;
2354 case TLFLOOR:
2355 pS->WriteUChar( tmFLOOR ); //selector
2356 pS->WriteUChar( 0 ); //variation
2357 pS->WriteUChar( 0 ); //options
2358 break;
2359 case TLLINE:
2360 pS->WriteUChar( tmBAR ); //selector
2361 pS->WriteUChar( 0 ); //variation
2362 pS->WriteUChar( 0 ); //options
2363 nBSpec+=3;
2364 break;
2365 case TLDLINE:
2366 pS->WriteUChar( tmDBAR ); //selector
2367 pS->WriteUChar( 0 ); //variation
2368 pS->WriteUChar( 0 ); //options
2369 break;
2370 default:
2371 pS->WriteUChar( tmPAREN ); //selector
2372 pS->WriteUChar( 0 ); //variation
2373 pS->WriteUChar( 0 ); //options
2374 nBSpec+=3;
2375 break;
2379 if (nullptr != (pTemp = pNode->GetSubNode(1)))
2381 pS->WriteUChar( LINE ); //line
2382 HandleNodes(pTemp,nLevel+1);
2383 pS->WriteUChar( END ); //options
2385 nSpec=nBSpec;
2386 if (pLeft)
2387 HandleNodes(pLeft,nLevel+1);
2388 if (bIsReInterpBrace)
2390 auto nLoc2 = pS->Tell();
2391 pS->Seek(nLoc);
2392 pS->WriteUChar( 0x2D );
2393 pS->Seek(nLoc2);
2394 pS->WriteUChar( CHAR );
2395 pS->WriteUChar( 0x96 );
2396 pS->WriteUInt16( 0xEC07 );
2397 bIsReInterpBrace=false;
2399 if (pRight)
2400 HandleNodes(pRight,nLevel+1);
2401 nSpec=0x0;
2402 pS->WriteUChar( END );
2406 void MathType::HandleVerticalBrace(SmNode *pNode,int nLevel)
2408 SmNode *pTemp;
2409 pS->WriteUChar( TMPL ); //Template
2410 if (pNode->GetToken().eType == TUNDERBRACE)
2411 pS->WriteUChar( tmLHBRACE ); //selector
2412 else
2413 pS->WriteUChar( tmUHBRACE ); //selector
2414 pS->WriteUChar( 0 ); //variation
2415 pS->WriteUChar( 0 ); //options
2417 if (nullptr != (pTemp = pNode->GetSubNode(0)))
2419 pS->WriteUChar( LINE ); //line
2420 HandleNodes(pTemp,nLevel+1);
2421 pS->WriteUChar( END ); //options
2424 if (nullptr != (pTemp = pNode->GetSubNode(2)))
2426 pS->WriteUChar( LINE ); //line
2427 HandleNodes(pTemp,nLevel+1);
2428 pS->WriteUChar( END ); //options
2430 pS->WriteUChar( END );
2433 void MathType::HandleOperator(SmNode *pNode,int nLevel)
2435 if (HandleLim(pNode,nLevel))
2436 return;
2438 sal_uInt64 nPos;
2439 sal_uInt8 nVariation;
2441 switch (pNode->GetToken().eType)
2443 case TIINT:
2444 case TIIINT:
2445 case TLINT:
2446 case TLLINT:
2447 case TLLLINT:
2448 nVariation=HandleCScript(pNode->GetSubNode(0),
2449 pNode->GetSubNode(1),nLevel,&nPos,false);
2450 break;
2451 default:
2452 nVariation=HandleCScript(pNode->GetSubNode(0),
2453 pNode->GetSubNode(1),nLevel,&nPos);
2454 break;
2457 sal_uInt8 nOldVariation=nVariation;
2458 sal_uInt8 nIntVariation=nVariation;
2460 sal_uInt64 nPos2=0;
2461 if (nVariation != 0xff)
2463 nPos2 = pS->Tell();
2464 pS->Seek(nPos);
2465 if (nVariation == 2)
2467 nIntVariation=0;
2468 nVariation = 1;
2470 else if (nVariation == 0)
2471 nVariation = 1;
2472 else if (nVariation == 1)
2473 nVariation = 0;
2475 else
2477 nVariation = 2;
2478 nIntVariation=0;
2480 pS->WriteUChar( TMPL );
2481 switch(pNode->GetToken().eType)
2483 case TINT:
2484 case TINTD:
2485 if (nOldVariation != 0xff)
2486 pS->WriteUChar( 0x18 ); //selector
2487 else
2488 pS->WriteUChar( 0x15 ); //selector
2489 pS->WriteUChar( nIntVariation ); //variation
2490 break;
2491 case TIINT:
2492 if (nOldVariation != 0xff)
2494 pS->WriteUChar( 0x19 );
2495 pS->WriteUChar( 0x01 );
2497 else
2499 pS->WriteUChar( 0x16 );
2500 pS->WriteUChar( 0x00 );
2502 break;
2503 case TIIINT:
2504 if (nOldVariation != 0xff)
2506 pS->WriteUChar( 0x1a );
2507 pS->WriteUChar( 0x01 );
2509 else
2511 pS->WriteUChar( 0x17 );
2512 pS->WriteUChar( 0x00 );
2514 break;
2515 case TLINT:
2516 if (nOldVariation != 0xff)
2518 pS->WriteUChar( 0x18 );
2519 pS->WriteUChar( 0x02 );
2521 else
2523 pS->WriteUChar( 0x15 );
2524 pS->WriteUChar( 0x03 );
2526 break;
2527 case TLLINT:
2528 if (nOldVariation != 0xff)
2530 pS->WriteUChar( 0x19 );
2531 pS->WriteUChar( 0x00 );
2533 else
2535 pS->WriteUChar( 0x16 );
2536 pS->WriteUChar( 0x02 );
2538 break;
2539 case TLLLINT:
2540 if (nOldVariation != 0xff)
2542 pS->WriteUChar( 0x1a );
2543 pS->WriteUChar( 0x00 );
2545 else
2547 pS->WriteUChar( 0x17 );
2548 pS->WriteUChar( 0x02 );
2550 break;
2551 case TSUM:
2552 default:
2553 pS->WriteUChar( 0x1d );
2554 pS->WriteUChar( nVariation );
2555 break;
2556 case TPROD:
2557 pS->WriteUChar( 0x1f );
2558 pS->WriteUChar( nVariation );
2559 break;
2560 case TCOPROD:
2561 pS->WriteUChar( 0x21 );
2562 pS->WriteUChar( nVariation );
2563 break;
2565 pS->WriteUChar( 0 ); //options
2567 if (nPos2)
2568 pS->Seek(nPos2);
2569 else
2571 pS->WriteUChar( LINE ); //line
2572 HandleNodes(pNode->GetSubNode(1),nLevel+1);
2573 pS->WriteUChar( END ); //line
2574 pS->WriteUChar( LINE|0x10 );
2575 pS->WriteUChar( LINE|0x10 );
2578 pS->WriteUChar( 0x0D );
2579 switch(pNode->GetToken().eType)
2581 case TSUM:
2582 default:
2583 pS->WriteUChar( CHAR );
2584 pS->WriteUChar( 0x86 );
2585 pS->WriteUInt16( 0x2211 );
2586 break;
2587 case TPROD:
2588 pS->WriteUChar( CHAR );
2589 pS->WriteUChar( 0x86 );
2590 pS->WriteUInt16( 0x220F );
2591 break;
2592 case TCOPROD:
2593 pS->WriteUChar( CHAR );
2594 pS->WriteUChar( 0x8B );
2595 pS->WriteUInt16( 0x2210 );
2596 break;
2597 case TIIINT:
2598 case TLLLINT:
2599 pS->WriteUChar( CHAR );
2600 pS->WriteUChar( 0x86 );
2601 pS->WriteUInt16( 0x222B );
2602 [[fallthrough]];
2603 case TIINT:
2604 case TLLINT:
2605 pS->WriteUChar( CHAR );
2606 pS->WriteUChar( 0x86 );
2607 pS->WriteUInt16( 0x222B );
2608 [[fallthrough]];
2609 case TINT:
2610 case TINTD:
2611 case TLINT:
2612 pS->WriteUChar( CHAR );
2613 pS->WriteUChar( 0x86 );
2614 pS->WriteUInt16( 0x222B );
2615 break;
2617 pS->WriteUChar( END );
2618 pS->WriteUChar( 0x0A );
2622 bool MathType::HandlePile(int &rSetAlign, int nLevel, sal_uInt8 nSelector, sal_uInt8 nVariation)
2624 sal_uInt8 nVAlign;
2625 pS->ReadUChar( nHAlign );
2626 pS->ReadUChar( nVAlign );
2628 HandleAlign(nHAlign, rSetAlign);
2630 rRet.append(" stack {\n");
2631 bool bRet = HandleRecords( nLevel+1, nSelector, nVariation, -1, -1 );
2632 int nRemoveFrom = rRet.getLength() >= 3 ? rRet.getLength() - 3 : 0;
2633 rRet.remove(nRemoveFrom, 2);
2634 rRet.append("} ");
2636 while (rSetAlign)
2638 rRet.append("} ");
2639 rSetAlign--;
2641 return bRet;
2644 bool MathType::HandleMatrix(int nLevel, sal_uInt8 nSelector, sal_uInt8 nVariation)
2646 sal_uInt8 nH_just,nV_just,nRows,nCols,nVAlign;
2647 pS->ReadUChar( nVAlign );
2648 pS->ReadUChar( nH_just );
2649 pS->ReadUChar( nV_just );
2650 pS->ReadUChar( nRows );
2651 pS->ReadUChar( nCols );
2652 int nBytes = ((nRows+1)*2)/8;
2653 if (((nRows+1)*2)%8)
2654 nBytes++;
2655 pS->SeekRel(nBytes);
2656 nBytes = ((nCols+1)*2)/8;
2657 if (((nCols+1)*2)%8)
2658 nBytes++;
2659 pS->SeekRel(nBytes);
2660 rRet.append(" matrix {\n");
2661 bool bRet = HandleRecords( nLevel+1, nSelector, nVariation, nRows, nCols );
2663 sal_Int32 nI = rRet.lastIndexOf('#');
2664 if (nI > 0)
2665 if (rRet[nI-1] != '#') //missing column
2666 rRet.append("{}");
2668 rRet.append("\n} ");
2669 return bRet;
2672 bool MathType::HandleTemplate(int nLevel, sal_uInt8 &rSelector,
2673 sal_uInt8 &rVariation, sal_Int32 &rLastTemplateBracket)
2675 sal_uInt8 nOption; //This appears utterly unused
2676 pS->ReadUChar( rSelector );
2677 pS->ReadUChar( rVariation );
2678 pS->ReadUChar( nOption );
2679 OSL_ENSURE(rSelector < 48,"Selector out of range");
2680 if ((rSelector >= 21) && (rSelector <=26))
2682 OSL_ENSURE(nOption < 2,"Option out of range");
2684 else if (rSelector <= 12)
2686 OSL_ENSURE(nOption < 3,"Option out of range");
2689 //For the (broken) case where one subscript template ends, and there is
2690 //another one after it, mathtype handles it as if the second one was
2691 //inside the first one and renders it as sub of sub
2692 bool bRemove=false;
2693 if ( (rSelector == 0xf) && (rLastTemplateBracket != -1) )
2695 bRemove=true;
2696 for (sal_Int32 nI = rLastTemplateBracket+1; nI < rRet.getLength(); nI++ )
2697 if (rRet[nI] != ' ')
2699 bRemove=false;
2700 break;
2704 //suborderlist
2705 bool bRet = HandleRecords( nLevel+1, rSelector, rVariation );
2707 if (bRemove)
2709 if (rLastTemplateBracket < rRet.getLength())
2710 rRet.remove(rLastTemplateBracket, 1);
2711 rRet.append("} ");
2712 rLastTemplateBracket = -1;
2714 if (rSelector == 0xf)
2715 rLastTemplateBracket = rRet.lastIndexOf('}');
2716 else
2717 rLastTemplateBracket = -1;
2719 rSelector = sal::static_int_cast< sal_uInt8 >(-1);
2720 return bRet;
2723 void MathType::HandleEmblishments()
2725 sal_uInt8 nEmbel;
2728 pS->ReadUChar( nEmbel );
2729 if (!pS->good())
2730 break;
2731 switch (nEmbel)
2733 case 0x02:
2734 rRet.append(" dot ");
2735 break;
2736 case 0x03:
2737 rRet.append(" ddot ");
2738 break;
2739 case 0x04:
2740 rRet.append(" dddot ");
2741 break;
2742 case 0x05:
2743 if (!nPostSup)
2745 sPost.append(" sup {}");
2746 nPostSup = sPost.getLength();
2748 sPost.insert(nPostSup-1," ' ");
2749 nPostSup += 3;
2750 break;
2751 case 0x06:
2752 if (!nPostSup)
2754 sPost.append(" sup {}");
2755 nPostSup = sPost.getLength();
2757 sPost.insert(nPostSup-1," '' ");
2758 nPostSup += 4;
2759 break;
2760 case 0x07:
2761 if (!nPostlSup)
2763 sPost.append(" lsup {}");
2764 nPostlSup = sPost.getLength();
2766 sPost.insert(nPostlSup-1," ' ");
2767 nPostlSup += 3;
2768 break;
2769 case 0x08:
2770 rRet.append(" tilde ");
2771 break;
2772 case 0x09:
2773 rRet.append(" hat ");
2774 break;
2775 case 0x0b:
2776 rRet.append(" vec ");
2777 break;
2778 case 0x10:
2779 rRet.append(" overstrike ");
2780 break;
2781 case 0x11:
2782 rRet.append(" bar ");
2783 break;
2784 case 0x12:
2785 if (!nPostSup)
2787 sPost.append(" sup {}");
2788 nPostSup = sPost.getLength();
2790 sPost.insert(nPostSup-1," ''' ");
2791 nPostSup += 5;
2792 break;
2793 case 0x14:
2794 rRet.append(" breve ");
2795 break;
2796 default:
2797 OSL_ENSURE(nEmbel < 21,"Embel out of range");
2798 break;
2800 if (nVersion < 3)
2801 break;
2802 }while (nEmbel);
2805 void MathType::HandleSetSize()
2807 sal_uInt8 nTemp;
2808 pS->ReadUChar( nTemp );
2809 switch (nTemp)
2811 case 101:
2812 pS->ReadInt16( nLSize );
2813 nLSize = -nLSize;
2814 break;
2815 case 100:
2816 pS->ReadUChar( nTemp );
2817 nLSize = nTemp;
2818 pS->ReadInt16( nDSize );
2819 break;
2820 default:
2821 nLSize = nTemp;
2822 pS->ReadUChar( nTemp );
2823 nDSize = nTemp-128;
2824 break;
2828 bool MathType::HandleChar(sal_Int32 &rTextStart, int &rSetSize, int nLevel,
2829 sal_uInt8 nTag, sal_uInt8 nSelector, sal_uInt8 nVariation, bool bSilent)
2831 sal_Unicode nChar(0);
2832 bool bRet = true;
2834 if (xfAUTO(nTag))
2836 //This is a candidate for function recognition, whatever
2837 //that is!
2840 sal_uInt8 nOldTypeFace = nTypeFace;
2841 pS->ReadUChar( nTypeFace );
2842 if (nVersion < 3)
2844 sal_uInt8 nChar8(0);
2845 pS->ReadUChar( nChar8 );
2846 nChar = nChar8;
2848 else
2849 pS->ReadUtf16( nChar );
2852 bad character, old mathtype < 3 has these
2854 if (nChar < 0x20)
2855 return bRet;
2857 if (xfEMBELL(nTag))
2859 //A bit tricky, the character emblishments for
2860 //mathtype can all be listed after each other, in
2861 //starmath some must go before the character and some
2862 //must go after. In addition some of the emblishments
2863 //may repeated and in starmath some of these groups
2864 //must be gathered together. sPost is the portion that
2865 //follows the char and nPostSup and nPostlSup are the
2866 //indexes at which this class of emblishment is
2867 //collated together
2868 sPost = "";
2869 nPostSup = nPostlSup = 0;
2870 int nOriglen=rRet.getLength()-rTextStart;
2871 rRet.append(" {"); // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n"
2872 if ((!bSilent) && (nOriglen > 1))
2873 rRet.append("\"");
2874 bRet = HandleRecords( nLevel+1, nSelector, nVariation );
2875 if (!bSilent)
2877 if (nOriglen > 1)
2879 OUString aStr;
2880 TypeFaceToString(aStr,nOldTypeFace);
2881 aStr += "\"";
2882 rRet.insert(std::min(rTextStart, rRet.getLength()), aStr);
2884 aStr.clear();
2885 TypeFaceToString(aStr,nTypeFace);
2886 rRet.append(aStr).append("{");
2888 else
2889 rRet.append(" {");
2890 rTextStart = rRet.getLength();
2894 if (!bSilent)
2896 sal_Int32 nOldLen = rRet.getLength();
2897 if (
2898 HandleSize(nLSize,nDSize,rSetSize) ||
2899 (nOldTypeFace != nTypeFace)
2902 if ((nOldLen - rTextStart) > 1)
2904 rRet.insert(nOldLen, "\"");
2905 OUString aStr;
2906 TypeFaceToString(aStr,nOldTypeFace);
2907 aStr += "\"";
2908 rRet.insert(rTextStart,aStr);
2910 rTextStart = rRet.getLength();
2912 nOldLen = rRet.getLength();
2913 if (!LookupChar(nChar,rRet,nVersion,nTypeFace))
2915 if (nOldLen - rTextStart > 1)
2917 rRet.insert(nOldLen, "\"");
2918 OUString aStr;
2919 TypeFaceToString(aStr,nOldTypeFace);
2920 aStr += "\"";
2921 rRet.insert(rTextStart, aStr);
2923 rTextStart = rRet.getLength();
2925 lcl_PrependDummyTerm(rRet, rTextStart);
2928 if ((xfEMBELL(nTag)) && (!bSilent))
2930 rRet.append("}}").append(sPost); // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n"
2931 rTextStart = rRet.getLength();
2933 return bRet;
2936 bool MathType::HandleLim(SmNode *pNode,int nLevel)
2938 bool bRet=false;
2939 //Special case for the "lim" option in StarMath
2940 if ((pNode->GetToken().eType == TLIM)
2941 || (pNode->GetToken().eType == TLIMSUP)
2942 || (pNode->GetToken().eType == TLIMINF)
2945 if (pNode->GetSubNode(1))
2947 sal_uInt8 nVariation2=HandleCScript(pNode->GetSubNode(0),nullptr,
2948 nLevel);
2950 pS->WriteUChar( 0x0A );
2951 pS->WriteUChar( LINE ); //line
2952 pS->WriteUChar( CHAR|0x10 );
2953 pS->WriteUChar( 0x82 );
2954 pS->WriteUInt16( 'l' );
2955 pS->WriteUChar( CHAR|0x10 );
2956 pS->WriteUChar( 0x82 );
2957 pS->WriteUInt16( 'i' );
2958 pS->WriteUChar( CHAR|0x10 );
2959 pS->WriteUChar( 0x82 );
2960 pS->WriteUInt16( 'm' );
2962 if (pNode->GetToken().eType == TLIMSUP)
2964 pS->WriteUChar( CHAR ); //some space
2965 pS->WriteUChar( 0x98 );
2966 pS->WriteUInt16( 0xEB04 );
2968 pS->WriteUChar( CHAR|0x10 );
2969 pS->WriteUChar( 0x82 );
2970 pS->WriteUInt16( 's' );
2971 pS->WriteUChar( CHAR|0x10 );
2972 pS->WriteUChar( 0x82 );
2973 pS->WriteUInt16( 'u' );
2974 pS->WriteUChar( CHAR|0x10 );
2975 pS->WriteUChar( 0x82 );
2976 pS->WriteUInt16( 'p' );
2978 else if (pNode->GetToken().eType == TLIMINF)
2980 pS->WriteUChar( CHAR ); //some space
2981 pS->WriteUChar( 0x98 );
2982 pS->WriteUInt16( 0xEB04 );
2984 pS->WriteUChar( CHAR|0x10 );
2985 pS->WriteUChar( 0x82 );
2986 pS->WriteUInt16( 'i' );
2987 pS->WriteUChar( CHAR|0x10 );
2988 pS->WriteUChar( 0x82 );
2989 pS->WriteUInt16( 'n' );
2990 pS->WriteUChar( CHAR|0x10 );
2991 pS->WriteUChar( 0x82 );
2992 pS->WriteUInt16( 'f' );
2996 pS->WriteUChar( CHAR ); //some space
2997 pS->WriteUChar( 0x98 );
2998 pS->WriteUInt16( 0xEB04 );
3000 if (nVariation2 != 0xff)
3002 pS->WriteUChar( END );
3003 pS->WriteUChar( END );
3005 HandleNodes(pNode->GetSubNode(1),nLevel+1);
3006 bRet = true;
3009 return bRet;
3012 void MathType::HandleMAlign(SmNode *pNode,int nLevel)
3014 sal_uInt8 nPushedHAlign=nHAlign;
3015 switch(pNode->GetToken().eType)
3017 case TALIGNC:
3018 nHAlign=2;
3019 break;
3020 case TALIGNR:
3021 nHAlign=3;
3022 break;
3023 default:
3024 nHAlign=1;
3025 break;
3027 size_t nSize = pNode->GetNumSubNodes();
3028 for (size_t i = 0; i < nSize; ++i)
3030 if (SmNode *pTemp = pNode->GetSubNode(i))
3031 HandleNodes(pTemp,nLevel+1);
3033 nHAlign=nPushedHAlign;
3036 void MathType::HandleMath(SmNode *pNode)
3038 if (pNode->GetToken().eType == TMLINE)
3040 pS->WriteUChar( END );
3041 pS->WriteUChar( LINE );
3042 bIsReInterpBrace=true;
3043 return;
3045 SmMathSymbolNode *pTemp = static_cast<SmMathSymbolNode *>(pNode);
3046 for(sal_Int32 i=0;i<pTemp->GetText().getLength();i++)
3048 sal_Unicode nArse = SmTextNode::ConvertSymbolToUnicode(pTemp->GetText()[i]);
3049 if ((nArse == 0x2224) || (nArse == 0x2288) || (nArse == 0x2285) ||
3050 (nArse == 0x2289))
3052 pS->WriteUChar( CHAR|0x20 );
3054 else if (nPendingAttributes &&
3055 (i == ((pTemp->GetText().getLength()+1)/2)-1))
3057 pS->WriteUChar( 0x22 );
3059 else
3060 pS->WriteUChar( CHAR ); //char without formula recognition
3061 //The typeface seems to be MTEXTRA for unicode characters,
3062 //though how to determine when mathtype chooses one over
3063 //the other is unknown. This should do the trick
3064 //nevertheless.
3065 sal_uInt8 nBias;
3066 if ( (nArse == 0x2213) || (nArse == 0x2218) ||
3067 (nArse == 0x210F) || (
3068 (nArse >= 0x22EE) && (nArse <= 0x22FF)
3071 nBias = 0xB; //typeface
3073 else if ((nArse == 0x2F) || (nArse == 0x2225))
3074 nBias = 0x2; //typeface
3075 else if ((nArse > 0x2000) || (nArse == 0x00D7))
3076 nBias = 0x6; //typeface
3077 else if (nArse == 0x3d1)
3078 nBias = 0x4;
3079 else if ((nArse > 0xFF) && ((nArse < 0x393) || (nArse > 0x3c9)))
3080 nBias = 0xB; //typeface
3081 else
3082 nBias = 0x3; //typeface
3084 pS->WriteUChar( nSpec+nBias+128 ); //typeface
3086 if (nArse == 0x2224)
3088 pS->WriteUInt16( 0x7C );
3089 pS->WriteUChar( EMBEL );
3090 pS->WriteUChar( 0x0A );
3091 pS->WriteUChar( END ); //end embel
3092 pS->WriteUChar( END ); //end embel
3094 else if (nArse == 0x2225)
3095 pS->WriteUInt16( 0xEC09 );
3096 else if (nArse == 0xE421)
3097 pS->WriteUInt16( 0x2265 );
3098 else if (nArse == 0x230A)
3099 pS->WriteUInt16( 0xF8F0 );
3100 else if (nArse == 0x230B)
3101 pS->WriteUInt16( 0xF8FB );
3102 else if (nArse == 0xE425)
3103 pS->WriteUInt16( 0x2264 );
3104 else if (nArse == 0x226A)
3106 pS->WriteUInt16( 0x3C );
3107 pS->WriteUChar( CHAR );
3108 pS->WriteUChar( 0x98 );
3109 pS->WriteUInt16( 0xEB01 );
3110 pS->WriteUChar( CHAR );
3111 pS->WriteUChar( 0x86 );
3112 pS->WriteUInt16( 0x3c );
3114 else if (nArse == 0x2288)
3116 pS->WriteUInt16( 0x2286 );
3117 pS->WriteUChar( EMBEL );
3118 pS->WriteUChar( 0x0A );
3119 pS->WriteUChar( END ); //end embel
3120 pS->WriteUChar( END ); //end embel
3122 else if (nArse == 0x2289)
3124 pS->WriteUInt16( 0x2287 );
3125 pS->WriteUChar( EMBEL );
3126 pS->WriteUChar( 0x0A );
3127 pS->WriteUChar( END ); //end embel
3128 pS->WriteUChar( END ); //end embel
3130 else if (nArse == 0x2285)
3132 pS->WriteUInt16( 0x2283 );
3133 pS->WriteUChar( EMBEL );
3134 pS->WriteUChar( 0x0A );
3135 pS->WriteUChar( END ); //end embel
3136 pS->WriteUChar( END ); //end embel
3138 else
3139 pS->WriteUInt16( nArse );
3141 nPendingAttributes = 0;
3144 void MathType::HandleAttributes(SmNode *pNode,int nLevel)
3146 int nOldPending = 0;
3147 SmNode *pTemp = nullptr;
3148 SmTextNode *pIsText = nullptr;
3150 if (nullptr != (pTemp = pNode->GetSubNode(0)))
3152 pIsText = static_cast<SmTextNode *>(pNode->GetSubNode(1));
3154 switch (pTemp->GetToken().eType)
3156 case TWIDEVEC:
3157 //there's just no way we can now handle any character
3158 //attributes (from mathtypes perspective) centered
3159 //over an expression but above template attributes
3160 //such as widevec and similar constructs
3161 //we have to drop them
3162 nOldPending = StartTemplate(0x2f,0x01);
3163 break;
3164 case TCHECK: //Not Exportable
3165 case TACUTE: //Not Exportable
3166 case TGRAVE: //Not Exportable
3167 case TCIRCLE: //Not Exportable
3168 case TWIDEHARPOON: //Not Exportable
3169 case TWIDETILDE: //Not Exportable
3170 case TWIDEHAT: //Not Exportable
3171 break;
3172 case TUNDERLINE:
3173 nOldPending = StartTemplate(0x10);
3174 break;
3175 case TOVERLINE: //If the next node is not text
3176 //or text with more than one char
3177 if ((pIsText->GetToken().eType != TTEXT) ||
3178 (pIsText->GetText().getLength() > 1))
3179 nOldPending = StartTemplate(0x11);
3180 break;
3181 default:
3182 nPendingAttributes++;
3183 break;
3187 if (pIsText)
3188 HandleNodes(pIsText,nLevel+1);
3190 switch (pTemp->GetToken().eType)
3192 case TWIDEVEC:
3193 case TUNDERLINE:
3194 EndTemplate(nOldPending);
3195 break;
3196 case TOVERLINE:
3197 if ((pIsText->GetToken().eType != TTEXT) ||
3198 (pIsText->GetText().getLength() > 1))
3199 EndTemplate(nOldPending);
3200 break;
3201 default:
3202 break;
3205 //if there was no suitable place to put the attribute,
3206 //then we have to just give up on it
3207 if (nPendingAttributes)
3208 nPendingAttributes--;
3209 else
3211 if ((nInsertion != 0) && nullptr != (pTemp = pNode->GetSubNode(0)))
3213 auto nPos = pS->Tell();
3214 nInsertion--;
3215 pS->Seek(nInsertion);
3216 switch(pTemp->GetToken().eType)
3218 case TACUTE: //Not Exportable
3219 case TGRAVE: //Not Exportable
3220 case TCIRCLE: //Not Exportable
3221 break;
3222 case TCDOT:
3223 pS->WriteUChar( 2 );
3224 break;
3225 case TDDOT:
3226 pS->WriteUChar( 3 );
3227 break;
3228 case TDDDOT:
3229 pS->WriteUChar( 4 );
3230 break;
3231 case TTILDE:
3232 pS->WriteUChar( 8 );
3233 break;
3234 case THAT:
3235 pS->WriteUChar( 9 );
3236 break;
3237 case TVEC:
3238 pS->WriteUChar( 11 );
3239 break;
3240 case TOVERSTRIKE:
3241 pS->WriteUChar( 16 );
3242 break;
3243 case TOVERLINE:
3244 if ((pIsText->GetToken().eType == TTEXT) &&
3245 (pIsText->GetText().getLength() == 1))
3246 pS->WriteUChar( 17 );
3247 break;
3248 case TBREVE:
3249 pS->WriteUChar( 20 );
3250 break;
3251 case TWIDEVEC:
3252 case TWIDEHARPOON:
3253 case TUNDERLINE:
3254 case TWIDETILDE:
3255 case TWIDEHAT:
3256 break;
3257 case TBAR:
3258 pS->WriteUChar( 17 );
3259 break;
3260 default:
3261 pS->WriteUChar( 2 );
3262 break;
3264 pS->Seek(nPos);
3269 void MathType::HandleText(SmNode *pNode)
3271 SmTextNode *pTemp = static_cast<SmTextNode *>(pNode);
3272 for(sal_Int32 i=0;i<pTemp->GetText().getLength();i++)
3274 if (nPendingAttributes &&
3275 (i == ((pTemp->GetText().getLength()+1)/2)-1))
3277 pS->WriteUChar( 0x22 ); //char, with attributes right
3278 //after the character
3280 else
3281 pS->WriteUChar( CHAR );
3283 sal_uInt8 nFace = 0x1;
3284 if (pNode->GetFont().GetItalic() == ITALIC_NORMAL)
3285 nFace = 0x3;
3286 else if (pNode->GetFont().GetWeight() == WEIGHT_BOLD)
3287 nFace = 0x7;
3288 pS->WriteUChar( nFace+128 ); //typeface
3289 sal_uInt16 nChar = pTemp->GetText()[i];
3290 pS->WriteUInt16( SmTextNode::ConvertSymbolToUnicode(nChar) );
3292 //Mathtype can only have these sort of character
3293 //attributes on a single character, starmath can put them
3294 //anywhere, when the entity involved is a text run this is
3295 //a large effort to place the character attribute on the
3296 //central mathtype character so that it does pretty much
3297 //what the user probably has in mind. The attributes
3298 //filled in here are dummy ones which are replaced in the
3299 //ATTRIBUT handler if a suitable location for the
3300 //attributes was found here. Unfortunately it is
3301 //possible for starmath to place character attributes on
3302 //entities which cannot occur in mathtype e.g. a Summation
3303 //symbol so these attributes may be lost
3304 if (nPendingAttributes &&
3305 (i == ((pTemp->GetText().getLength()+1)/2)-1))
3307 pS->WriteUChar( EMBEL );
3308 while (nPendingAttributes)
3310 pS->WriteUChar( 2 );
3311 //wedge the attributes in here and clear
3312 //the pending stack
3313 nPendingAttributes--;
3315 nInsertion=pS->Tell();
3316 pS->WriteUChar( END ); //end embel
3317 pS->WriteUChar( END ); //end embel
3322 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportMathType(SvStream &rStream)
3324 OUStringBuffer sText;
3325 MathType aEquation(sText);
3326 bool bRet = false;
3329 bRet = aEquation.Parse(&rStream);
3331 catch (const std::out_of_range&)
3334 return bRet;
3337 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */