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