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