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