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