/Users/ericb/Desktop/SRC680_m247/starmath/source/mathtype.cxx

Go to the documentation of this file.
00001 /*************************************************************************
00002  *
00003  *  OpenOffice.org - a multi-platform office productivity suite
00004  *
00005  *  $RCSfile: mathtype.cxx,v $
00006  *
00007  *  $Revision: 1.39 $
00008  *
00009  *  last change: $Author: hr $ $Date: 2007/06/27 12:40:16 $
00010  *
00011  *  The Contents of this file are made available subject to
00012  *  the terms of GNU Lesser General Public License Version 2.1.
00013  *
00014  *
00015  *    GNU Lesser General Public License Version 2.1
00016  *    =============================================
00017  *    Copyright 2005 by Sun Microsystems, Inc.
00018  *    901 San Antonio Road, Palo Alto, CA 94303, USA
00019  *
00020  *    This library is free software; you can redistribute it and/or
00021  *    modify it under the terms of the GNU Lesser General Public
00022  *    License version 2.1, as published by the Free Software Foundation.
00023  *
00024  *    This library is distributed in the hope that it will be useful,
00025  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00026  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00027  *    Lesser General Public License for more details.
00028  *
00029  *    You should have received a copy of the GNU Lesser General Public
00030  *    License along with this library; if not, write to the Free Software
00031  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00032  *    MA  02111-1307  USA
00033  *
00034  ************************************************************************/
00035 
00036 // MARKER(update_precomp.py): autogen include statement, do not remove
00037 #include "precompiled_starmath.hxx"
00038 
00039 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
00040 
00041 #ifndef MATHTYPE_HXX
00042 #include <mathtype.hxx>
00043 #endif
00044 
00045 #ifndef _TOOLS_DEBUG_H
00046 #include <tools/debug.hxx>
00047 #endif
00048 
00049 #include <sfx2/docfile.hxx>
00050 
00051 #define APPEND(str,ascii) str.AppendAscii(RTL_CONSTASCII_STRINGPARAM(ascii))
00052 
00053 #if 0
00054 String aEmbelList[21] =
00055 {
00056         " ",
00057         " ",
00058     "single dot",
00059     "double dot",
00060     "triple dot",
00061     "single prime",
00062     "double prime",
00063     "backwards prime (left of character)",
00064     "tilde",
00065     "hat (circumflex)",
00066     "diagonal slash through character",
00067     "right arrow",
00068     "left arrow",
00069     "double-headed arrow",
00070     "right single-barbed arrow",
00071     "left single-barbed arrow",
00072     "mid-height horizontal bar",
00073     "over-bar",
00074     "triple prime",
00075     "over-arc, concave downward",
00076     "over-arc, concave upward"
00077 };
00078 
00079 String aSelectorList[49] =
00080 {
00081         "angle brackets",
00082         "parentheses",
00083         "braces (curly brackets)",
00084         "square brackets",
00085         "vertical bars",
00086         "double vertical bars",
00087         "floor brackets",
00088         "ceiling brackets",
00089         "left brace, left brace",
00090         "right brace, right brace",
00091         "right brace, left brace",
00092         "left brace, right parenthesis",
00093         "left parenthesis, right brace",
00094         "radical",
00095         "fractions",
00096         "subscript/superscript",
00097         "underbar",
00098         "overbar",
00099         "left-pointing arrow",
00100         "right-pointing arrow",
00101         "left- and right-pointing arrow",
00102         "single integral",
00103         "double integral",
00104         "triple integral",
00105         "single summation-style integral",
00106         "double summation-style integral",
00107         "triple summation-style integral",
00108         "upper horizontal brace",
00109         "lower horizontal brace",
00110         "summation",
00111         "summation (integral-style limits)",
00112         "product",
00113         "product (integral-style limits)",
00114         "coproduct",
00115         "coproduct (integral-style limits)",
00116         "union",
00117         "union (integral-style limits)",
00118         "intersection",
00119         "intersection (integral-style limits)",
00120         "limit",
00121         "long division",
00122         "slash fractions",
00123         "big integral-style operators",
00124         "big summation-style operators",
00125         "leading sub- and superscripts",
00126         "Dirac delta",
00127         "under arrow",
00128         "over arrow",
00129         "over arc"
00130 };
00131 
00132 String aIntegralOpt[2] =
00133 {
00134         "fixed-size integral",
00135         "integral expands vertically to fit its contents"
00136 };
00137 
00138 String aFenceOpt[3] =
00139 {
00140         "center fence on math axis",
00141         "center fence on contents, place math axis of contents on math axis of containing line",
00142         "center fence on contents, center contents on math axis of containing line"
00143 };
00144 
00145 String aTypeFaces[12] =
00146 {
00147         "",
00148         "fnTEXT",
00149         "fnFUNCTION",
00150         "fnVARIABLE",
00151         "fnLCGREEK",
00152         "fnUCGREEK",
00153         "fnSYMBOL",
00154         "fnVECTOR",
00155         "fnNUMBER",
00156         "fnUSER1",
00157         "fnUSER2",
00158         "fnMTEXTRA"
00159 };
00160 
00161 String aSizes[7] =
00162 {
00163         "full",
00164         "subscript",
00165         "sub-subscript",
00166         "symbol",
00167         "sub-symbol",
00168         "user 1",
00169         "user 2"
00170 };
00171 #endif
00172 
00173 static sal_Unicode Convert(sal_Unicode nIn)
00174 {
00175     //Find the best match in accepted unicode for our private area symbols
00176     static sal_Unicode aStarMathPrivateToUnicode[] =
00177     {
00178                 0x2030, 0xF613, 0xF612, 0x002B, 0x003C, 0x003E, 0xE425, 0xE421, 0xE088, 0x2208,
00179                 0x0192, 0x2026, 0x2192, 0x221A, 0x221A, 0x221A, 0xE090, 0x005E, 0x02C7, 0x02D8,
00180                 0x00B4, 0x0060, 0x02DC, 0x00AF, 0x0362, 0xE099, 0xE09A, 0x20DB, 0xE09C, 0xE09D,
00181                 0x0028, 0x0029, 0x2220, 0x22AF, 0xE0A2, 0xE0A3, 0xE0A4, 0xE0A5, 0xE0A6, 0xE0A7,
00182                 0x002F, 0x005C, 0x274F, 0xE0AB, 0x0393, 0x0394, 0x0398, 0x039b, 0x039e, 0x03A0,
00183                 0x03a3, 0x03a5, 0x03a6, 0x03a8, 0x03A9, 0x03B1, 0x03B2, 0x03b3, 0x03b4, 0x03b5,
00184                 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
00185                 0x03c0, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03b5,
00186                 0x03d1, 0x03d6, 0xE0D2, 0x03db, 0x2118, 0x2202, 0x2129, 0xE0D7, 0xE0D8, 0x22A4,
00187                 0xE0DA, 0x2190, 0x2191, 0x2193
00188     };
00189     if ((nIn >= 0xE080) && (nIn <= 0xE0DD))
00190         nIn = aStarMathPrivateToUnicode[nIn-0xE080];
00191 
00192     //For whatever unicode glyph that equation editor doesn't ship with that
00193     //we have a possible match we can munge it to.
00194     switch (nIn)
00195     {
00196         case 0x2223:
00197             nIn = '|';
00198             break;
00199         default:
00200             break;
00201     }
00202 
00203     return nIn;
00204 }
00205 
00206 void MathType::Init()
00207 {
00208         //These are the default MathType sizes
00209         aSizeTable[0]=12;
00210         aSizeTable[1]=8;
00211         aSizeTable[2]=6;
00212         aSizeTable[3]=24;
00213         aSizeTable[4]=10;
00214         aSizeTable[5]=12;
00215         aSizeTable[6]=12;
00216 
00217         /*
00218         These are the default MathType italic/bold settings If mathtype is changed
00219         from its defaults, there is nothing we can do, as this information is not
00220         stored in the document
00221         */
00222         MathTypeFont aFont;
00223         for(sal_uInt8 i=1;i<=11;i++)
00224         {
00225                 aFont.nTface = i+128;
00226                 switch (i)
00227                 {
00228                         default:
00229                                 aFont.nStyle=0;
00230                                 break;
00231                         case 3:
00232                         case 4:
00233                                 aFont.nStyle=1;
00234                                 break;
00235                         case 7:
00236                                 aFont.nStyle=2;
00237                                 break;
00238                 }
00239                 aUserStyles.insert(aFont);
00240         }
00241 }
00242 
00243 
00244 /*ToDo replace with table rather than switch, returns
00245  TRUE in the case that the char is just a char, and
00246  FALSE if the character is an operator which must not be
00247  placed inside the quote sequence designed to protect
00248  against being parsed as a keyword
00249 
00250  General solution required to force starmath to handle
00251  unicode math chars the way it handles its own math
00252  chars rathar than handle them as text as it will do
00253  for the default case below, i.e. incorrect spacing
00254  between math symbols and ordinary text e.g. 1=2 rather
00255  than 1 = 2
00256  */
00257 sal_Bool MathType::LookupChar(sal_Unicode nChar,String &rRet,sal_uInt8 nVersion,
00258         sal_uInt8 nTypeFace)
00259 {
00260         sal_Bool bRet=FALSE;
00261         const char *pC = NULL;
00262         switch(nChar)
00263         {
00264                 case 0x0000:
00265                         pC = " none ";
00266                         break;
00267                 case 0x00ac:
00268                         pC = " neg ";
00269                         break;
00270                 case 0x00b1:
00271                         pC = " +- ";
00272                         break;
00273         case '(':
00274                         pC = " \\( ";
00275                         break;
00276         case ')':
00277                         pC = " \\) ";
00278                         break;
00279         case '[':
00280                         pC = " \\[ ";
00281                         break;
00282         case ']':
00283                         pC = " \\] ";
00284                         break;
00285         case '.':
00286                         pC = " \".\" ";
00287             break;
00288         case 0xae:
00289             if ((nVersion < 3) && (nTypeFace == 0x86))
00290                             pC = " rightarrow ";
00291             else
00292             {
00293                 rRet.Append(nChar);
00294                             bRet=TRUE;
00295             }
00296                         break;
00297         case 0x00fb:
00298                         if ((nVersion < 3) && (nTypeFace == 0x81))
00299                                 nChar = 0xDF;
00300                         rRet.Append(nChar);
00301                         bRet=TRUE;
00302             break;
00303         case 'a':
00304                         if ((nVersion < 3) && (nTypeFace == 0x84))
00305                                 nChar = 0x3b1;
00306                         rRet.Append(nChar);
00307                         bRet=TRUE;
00308             break;
00309         case 'b':
00310                         if ((nVersion < 3) && (nTypeFace == 0x84))
00311                                 nChar = 0x3b2;
00312                         rRet.Append(nChar);
00313                         bRet=TRUE;
00314             break;
00315         case 'l':
00316                         if ((nVersion < 3) && (nTypeFace == 0x84))
00317                                 nChar = 0x3bb;
00318                         rRet.Append(nChar);
00319                         bRet=TRUE;
00320             break;
00321         case 'n':
00322                         if ((nVersion < 3) && (nTypeFace == 0x84))
00323                                 nChar = 0x3bd;
00324                         rRet.Append(nChar);
00325                         bRet=TRUE;
00326             break;
00327         case 'r':
00328                         if ((nVersion < 3) && (nTypeFace == 0x84))
00329                                 nChar = 0x3c1;
00330                         rRet.Append(nChar);
00331                         bRet=TRUE;
00332             break;
00333         case 'D':
00334                         if ((nVersion < 3) && (nTypeFace == 0x84))
00335                                 nChar = 0x394;
00336                         rRet.Append(nChar);
00337                         bRet=TRUE;
00338             break;
00339         case 0xa9:
00340                         if ((nVersion < 3) && (nTypeFace == 0x82))
00341                                 nChar = '\'';
00342                         rRet.Append(nChar);
00343                         bRet=TRUE;
00344             break;
00345         case 0x00f1:
00346                         if ((nVersion < 3) && (nTypeFace == 0x86))
00347                                 pC = " \\rangle ";
00348             else
00349             {
00350                             rRet.Append(nChar);
00351                             bRet=TRUE;
00352             }
00353             break;
00354         case 0x00a3:
00355                         if ((nVersion < 3) && (nTypeFace == 0x86))
00356                                 pC = " <= ";
00357             else
00358             {
00359                             rRet.Append(nChar);
00360                             bRet=TRUE;
00361             }
00362             break;
00363         case 0x00de:
00364                         if ((nVersion < 3) && (nTypeFace == 0x86))
00365                                 pC = " drarrow ";
00366                         else
00367                         {
00368                                 rRet.Append(nChar);
00369                                 bRet=TRUE;
00370                         }
00371             break;
00372                 case 0x0057:
00373                         if ((nVersion < 3) && (nTypeFace == 0x85))
00374                                 pC = " %OMEGA ";
00375                         else
00376                         {
00377                                 rRet.Append(nChar);
00378                                 bRet=TRUE;
00379                         }
00380                         break;
00381                 case 0x007b:
00382                         pC = " lbrace ";
00383                         break;
00384                 case 0x007c:
00385                         pC = " \\lline ";
00386                         break;
00387                 case 0x007d:
00388                         pC = " rbrace ";
00389                         break;
00390                 case 0x007e:
00391                         pC = " \"~\" ";
00392                         break;
00393                 case 0x2224:
00394                         pC = " ndivides ";
00395                         break;
00396                 case 0x2225:
00397                         pC = " parallel ";
00398                         break;
00399                 case 0x00d7:
00400                         if (nVersion < 3)
00401                                 pC = " cdot ";
00402                         else
00403                                 pC = " times ";
00404                         break;
00405                 case 0x00f7:
00406                         pC = " div ";
00407                         break;
00408                 case 0x019b:
00409                         pC = " lambdabar ";
00410                         break;
00411                 case 0x2026:
00412                         pC = " dotslow ";
00413                         break;
00414                 case 0x2022:
00415                         pC = " cdot ";
00416                         break;
00417                 case 0x2102:
00418                         pC = " setC ";
00419                         break;
00420                 case 0x210f:
00421                         pC = " hbar ";
00422                         break;
00423                 case 0x2111:
00424                         pC = " Im ";
00425                         break;
00426                 case 0x2115:
00427                         pC = " setN ";
00428                         break;
00429                 case 0x2118:
00430                         pC = " wp ";
00431                         break;
00432                 case 0x211a:
00433                         pC = " setQ ";
00434                         break;
00435                 case 0x211c:
00436                         pC = " Re ";
00437                         break;
00438                 case 0x211d:
00439                         pC = " setR ";
00440                         break;
00441                 case 0x2124:
00442                         pC = " setZ ";
00443                         break;
00444                 case 0x2135:
00445                         pC = " aleph ";
00446                         break;
00447                 case 0x2190:
00448                         pC = " leftarrow ";
00449                         break;
00450                 case 0x2191:
00451                         pC = " uparrow ";
00452                         break;
00453                 case 0x2192:
00454                         pC = " rightarrow ";
00455                         break;
00456                 case 0x0362:
00457                         pC = " widevec ";
00458                         break;
00459                 case 0x2193:
00460                         pC = " downarrow ";
00461                         break;
00462                 case 0x21d0:
00463                         pC = " dlarrow ";
00464                         break;
00465                 case 0x21d2:
00466                         pC = " drarrow ";
00467                         break;
00468                 case 0x21d4:
00469                         pC = " dlrarrow ";
00470                         break;
00471                 case 0x2200:
00472                         pC = " forall ";
00473                         break;
00474                 case 0x2202:
00475                         pC = " partial ";
00476                         break;
00477                 case 0x2203:
00478                         pC = " exists ";
00479                         break;
00480                 case 0x2205:
00481                         pC = " emptyset ";
00482                         break;
00483                 case 0x2207:
00484                         pC = " nabla ";
00485                         break;
00486                 case 0x2208:
00487                         pC = " in ";
00488                         break;
00489                 case 0x2209:
00490                         pC = " notin ";
00491                         break;
00492                 case 0x220d:
00493                         pC = " owns ";
00494                         break;
00495                 case 0x220f:
00496                         pC = " prod ";
00497                         break;
00498                 case 0x2210:
00499                         pC = " coprod ";
00500                         break;
00501                 case 0x2211:
00502                         pC = " sum ";
00503                         break;
00504                 case 0x2212:
00505                         pC = " - ";
00506                         break;
00507                 case 0x2213:
00508                         pC = " -+ ";
00509                         break;
00510                 case 0x2217:
00511                         pC = " * ";
00512                         break;
00513                 case 0x2218:
00514                         pC = " circ ";
00515                         break;
00516                 case 0x221d:
00517                         pC = " prop ";
00518                         break;
00519                 case 0x221e:
00520                         pC = " infinity ";
00521                         break;
00522                 case 0x2227:
00523                         pC = " and ";
00524                         break;
00525                 case 0x2228:
00526                         pC = " or ";
00527                         break;
00528                 case 0x2229:
00529                         pC = " intersection ";
00530                         break;
00531                 case 0x222a:
00532                         pC = " union ";
00533                         break;
00534                 case 0x222b:
00535                         pC = " int ";
00536                         break;
00537                 case 0x222c:
00538                         pC = " iint ";
00539                         break;
00540                 case 0x222d:
00541                         pC = " iiint ";
00542                         break;
00543         case 0x222e:
00544                         pC = " lint ";
00545             break;
00546         case 0x222f:
00547                         pC = " llint ";
00548             break;
00549         case 0x2230:
00550                         pC = " lllint ";
00551             break;
00552                 case 0x2245:
00553                         pC = " simeq ";
00554                         break;
00555                 case 0x2248:
00556                         pC = " approx ";
00557                         break;
00558                 case 0x2260:
00559                         pC = " <> ";
00560                         break;
00561                 case 0x2261:
00562                         pC = " equiv ";
00563                         break;
00564                 case 0x2264:
00565                         pC = " <= ";
00566                         break;
00567                 case 0x2265:
00568                         pC = " >= ";
00569                         break;
00570                 case 0x2282:
00571                         pC = " subset ";
00572                         break;
00573                 case 0x2283:
00574                         pC = " supset ";
00575                         break;
00576                 case 0x2284:
00577                         pC = " nsubset ";
00578                         break;
00579                 case 0x2285:
00580                         pC = " nsupset ";
00581                         break;
00582                 case 0x2286:
00583                         pC = " subseteq ";
00584                         break;
00585                 case 0x2287:
00586                         pC = " supseteq ";
00587                         break;
00588                 case 0x2288:
00589                         pC = " nsubseteq ";
00590                         break;
00591                 case 0x2289:
00592                         pC = " nsupseteq ";
00593                         break;
00594                 case 0x227a:
00595                 case 0x227b:
00596                 case 0x22b2:
00597                 case 0x22b3:
00598                         rRet += ' ';
00599                         rRet.Append(nChar);
00600                         rRet += ' ';
00601                         break;
00602                 case 0x22a5:
00603                         pC = " ortho ";
00604                         break;
00605                 case 0x22c5:
00606                         pC = " cdot ";
00607                         break;
00608                 case 0x22ee:
00609                         pC = " dotsvert ";
00610                         break;
00611                 case 0x22ef:
00612                         pC = " dotsaxis ";
00613                         break;
00614                 case 0x22f0:
00615                         pC = " dotsup ";
00616                         break;
00617                 case 0x22f1:
00618                         pC = " dotsdown ";
00619                         break;
00620                 case 0x2329:
00621                         pC = " langle ";
00622                         break;
00623                 case 0x232a:
00624                         pC = " rangle ";
00625                         break;
00626                 case 0x301a:
00627                         pC = " ldbracket ";
00628                         break;
00629                 case 0x301b:
00630                         pC = " rdbracket ";
00631                         break;
00632         case 0xe083:
00633                         rRet.Append('+');
00634             bRet=TRUE;
00635             break;
00636         case '^':
00637         case 0xe091:
00638             pC = " widehat ";
00639             break;
00640         case 0xe096:
00641             pC = " widetilde ";
00642             break;
00643         case 0xe098:
00644             pC = " widevec ";
00645             break;
00646                 case 0xE421:
00647                         pC = " geslant ";
00648                         break;
00649                 case 0xE425:
00650                         pC = " leslant ";
00651                         break;
00652                 case 0xeb01:    //no space
00653                 case 0xeb08:    //normal space
00654                         bRet=TRUE;
00655                         break;
00656         case 0xef04:    //tiny space
00657                 case 0xef05:    //tiny space
00658                 case 0xeb02:    //small space
00659                 case 0xeb04:    //medium space
00660                         rRet.Append('`');
00661                         break;
00662                 case 0xeb05:    //large space
00663                         rRet.Append('~');
00664                         break;
00665                 case 0x3a9:
00666                         pC = " %OMEGA ";
00667                         break;
00668                 default:
00669                         rRet.Append(nChar);
00670                         bRet=TRUE;
00671                         break;
00672         }
00673         if (pC)
00674                 rRet.AppendAscii(pC);
00675         return bRet;
00676 }
00677 
00678 void MathTypeFont::AppendStyleToText(String &rRet)
00679 {
00680         const char *pC = NULL;
00681         switch (nStyle)
00682         {
00683                 default:
00684                 case 0:
00685                         break;
00686                 case 1:
00687                         pC = " ital ";
00688                         break;
00689                 case 2:
00690                         pC = " bold ";
00691                         break;
00692                 case 3:
00693                         pC = " bold italic";
00694                         break;
00695         }
00696         if (pC)
00697                 rRet.AppendAscii(pC);
00698 }
00699 
00700 void MathType::TypeFaceToString(String &rTxt,sal_uInt8 nFace)
00701 {
00702         MathTypeFont aFont(nFace);
00703         MathTypeFontSet::iterator aItr = aUserStyles.find(aFont);
00704         if (aItr != aUserStyles.end())
00705                 aFont.nStyle = aItr->nStyle;
00706     aFont.AppendStyleToText(rTxt);
00707 }
00708 
00709 int MathType::Parse(SotStorage *pStor)
00710 {
00711     SvStorageStreamRef xSrc = pStor->OpenSotStream(
00712                 String::CreateFromAscii("Equation Native"),
00713                 STREAM_STD_READ | STREAM_NOCREATE);
00714         if ( (!xSrc.Is()) || (SVSTREAM_OK != xSrc->GetError()))
00715         return 0;
00716         pS = &xSrc;
00717         pS->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
00718 
00719         EQNOLEFILEHDR aHdr;
00720         aHdr.Read(pS);
00721         *pS >> nVersion;
00722         *pS >> nPlatform;
00723         *pS >> nProduct;
00724         *pS >> nProdVersion;
00725         *pS >> nProdSubVersion;
00726 
00727     if (nVersion > 3)   // allow only supported versions of MathType to be parsed
00728         return 0;
00729 
00730 #ifdef STANDALONE
00731         *pOut << "Format Version is " << int(nVersion) << endl;
00732         *pOut << "Generating Platform is " << (nPlatform ? "Windows"
00733                 : "Mac") << endl;
00734         *pOut << "Generating Product is " << (nPlatform ? "Equation Editor"
00735                 : "Equation Editor") << endl;
00736         *pOut << "Prod Version is " << int(nProdVersion) << "." <<
00737                 int(nProdSubVersion) << endl << endl;
00738 #endif
00739 
00740         int nRet = HandleRecords();
00741         //little crude hack to close ocassionally open expressions
00742         //a sophisticated system to determine what expressions are
00743         //opened is required, but this is as much work as rewriting
00744         //starmaths internals.
00745         APPEND(rRet,"{}");
00746 
00747 #if OSL_DEBUG_LEVEL > 1
00748 #       ifdef CAOLAN
00749         //sanity check
00750 
00751         //sigh, theres no point! MathType (in some bizarre subvarient) pads
00752         //the end of the formula with ENDs (0)'s
00753         ULONG nEnd = pS->Tell();
00754         DBG_ASSERT(nEnd == pS->Seek(STREAM_SEEK_TO_END),
00755                 "Possibly unfully parsed formula")
00756 #       endif
00757 #endif
00758         return nRet;
00759 }
00760 
00761 static void lcl_PrependDummyTerm(String &rRet, xub_StrLen &rTextStart)
00762 {
00763         if ((rRet.GetChar(rTextStart) == '=') &&
00764                 ((rTextStart == 0) ||
00765                 (rRet.GetChar(rTextStart-1) == '{'))
00766            )
00767         {
00768                 rRet.InsertAscii(" {}",rTextStart);
00769         rTextStart+=3;
00770         }
00771 }
00772 
00773 static void lcl_AppendDummyTerm(String &rRet)
00774 {
00775     sal_Bool bOk=sal_False;
00776     for(int nI=rRet.Len()-1;nI >= 0; nI--)
00777     {
00778         xub_StrLen nIdx = sal::static_int_cast< xub_StrLen >(nI);
00779         sal_Unicode nChar = rRet.GetChar(nIdx);
00780         if (nChar == ' ')
00781             continue;
00782         if (rRet.GetChar(nIdx) != '{')
00783             bOk=sal_True;
00784         break;
00785     }
00786     if (!bOk)   //No term, use dummy
00787         APPEND(rRet," {}");
00788 }
00789 
00790 void MathType::HandleNudge()
00791 {
00792     sal_uInt8 nXNudge;
00793     *pS >> nXNudge;
00794     sal_uInt8 nYNudge;
00795     *pS >> nYNudge;
00796     if (nXNudge == 128 && nYNudge == 128)
00797     {
00798         sal_uInt16 nXLongNudge;
00799         sal_uInt16 nYLongNudge;
00800         *pS >> nXLongNudge;
00801         *pS >> nYLongNudge;
00802     }
00803 }
00804 /*Fabously complicated as many tokens have to be reordered and generally
00805  *moved around from mathtypes paradigm to starmaths.*/
00806 int MathType::HandleRecords(int nLevel,sal_uInt8 nSelector,
00807         sal_uInt8 nVariation, int nMatrixRows,int nMatrixCols)
00808 {
00809         sal_uInt8 nTag,nRecord;
00810         sal_uInt8 nTabType,nTabStops;
00811         sal_uInt16 nTabOffset;
00812         sal_Char nChar8;
00813         String sFontName;
00814         int i,nRet=1,newline=0;
00815     sal_Bool bSilent=FALSE;
00816         int nPart=0;
00817         String sPush,sMainTerm;
00818         int nSetSize=0,nSetAlign=0;
00819         int nCurRow=0,nCurCol=0;
00820         sal_Bool bOpenString=FALSE;
00821     xub_StrLen nTextStart = 0;
00822     xub_StrLen nSubSupStartPos = 0;
00823     xub_StrLen nLastTemplateBracket=STRING_NOTFOUND;
00824 
00825         do
00826         {
00827                 *pS >> nTag;
00828                 nRecord = nTag&0x0F;
00829 
00830                 /*MathType strings can of course include words which
00831                  *are StarMath keywords, the simplest solution is
00832                  to escape strings of greater than len 1 with double
00833                  quotes to avoid scanning the TokenTable for matches
00834 
00835                  Unfortunately it may turn out that the string gets
00836                  split during the handling of a character emblishment
00837                  so this special case must be handled in the
00838                  character handler case 2:
00839                  */
00840         if ((nRecord == CHAR) && (!bIsSilent) && (!bOpenString))
00841                 {
00842                         bOpenString=TRUE;
00843                         nTextStart = rRet.Len();
00844                 }
00845                 else if ((nRecord != CHAR) && (bOpenString))
00846                 {
00847                         bOpenString=FALSE;
00848                         if ((rRet.Len() - nTextStart) > 1)
00849                         {
00850                                 String aStr;
00851                                 TypeFaceToString(aStr,nTypeFace);
00852                                 aStr += '\"';
00853                                 rRet.Insert(aStr,nTextStart);
00854                                 rRet += '\"';
00855                         }
00856                         else
00857                         {
00858                                 if (nRecord == END)
00859                                 {
00860                     sal_Unicode cChar = 0;
00861                     xub_StrLen nI = rRet.Len()-1;
00862                     while (nI && ((cChar = rRet.GetChar(nI)) == ' '))
00863                         --nI;
00864                                         if ((cChar == '=') || (cChar == '+') || (cChar == '-'))
00865                                                 APPEND(rRet,"{}");
00866                                 }
00867                         }
00868                 }
00869 
00870                 switch(nRecord)
00871                 {
00872                         case LINE:
00873                                 {
00874                                         if (xfLMOVE(nTag))
00875                         HandleNudge();
00876                                         //if (xfLSPACE(nTag))
00877                                         //if (xfRULER(nTag))
00878 
00879                                         if (newline>0)
00880                                                 APPEND(rRet,"\nnewline\n");
00881                                         if (!(xfNULL(nTag)))
00882                                         {
00883                                                 switch (nSelector)
00884                                                 {
00885                                                 case 0x0:
00886                                                         if (nVariation==0)
00887                                                                 APPEND(rRet," langle ");
00888                                                         else if (nVariation==1)
00889                                                                 APPEND(rRet," \\langle ");
00890                                                         break;
00891                                                 case 0x1:
00892                                                         if (nVariation==0)
00893                                                                 APPEND(rRet," left (");
00894                                                         else if (nVariation==1)
00895                                                                 APPEND(rRet,"\\(");
00896                                                         break;
00897                                                 case 0x2:
00898                                                         if ((nVariation==0) || (nVariation==1))
00899                                                                 APPEND(rRet," left lbrace ");
00900                             else
00901                                 APPEND(rRet," left none ");
00902                                                         break;
00903                                                 case 0x3:
00904                                                         if (nVariation==0)
00905                                                                 APPEND(rRet," left [");
00906                                                         else if (nVariation==1)
00907                                                                 APPEND(rRet,"\\[");
00908                                                         break;
00909                                                 case 0x8:
00910                                                 case 0xb:
00911                                                         APPEND(rRet," \\[");
00912                                                         break;
00913                                                 case 0x4:
00914                                                         if (nVariation==0)
00915                                                                 APPEND(rRet," lline ");
00916                                                         else if (nVariation==1)
00917                                                                 APPEND(rRet," \\lline ");
00918                                                         break;
00919                                                 case 0x5:
00920                                                         if (nVariation==0)
00921                                                                 APPEND(rRet," ldline ");
00922                                                         else if (nVariation==1)
00923                                                                 APPEND(rRet," \\ldline ");
00924                                                         break;
00925                                                 case 0x6:
00926                                                         if (nVariation == 0 || nVariation == 1)
00927                                                                 APPEND(rRet," left lfloor ");
00928                                                         else if (nVariation==1)
00929                                                                 APPEND(rRet," left none ");
00930                                                         break;
00931                                                 case 0x7:
00932                                                         if (nVariation==0)
00933                                                                 APPEND(rRet," lceil ");
00934                                                         else if (nVariation==1)
00935                                                                 APPEND(rRet," \\lceil ");
00936                                                         break;
00937                                                 case 0x9:
00938                                                 case 0xa:
00939                                                         APPEND(rRet," \\]");
00940                                                         break;
00941                                                 case 0xc:
00942                                                         APPEND(rRet," \\(");
00943                                                         break;
00944                                                 case 0xd:
00945                                                         if (nPart == 0)
00946                                                         {
00947                                                                 if (nVariation == 0)
00948                                                                         APPEND(rRet," sqrt");
00949                                                                 else
00950                                                                 {
00951                                                                         APPEND(rRet," nroot");
00952                                                                         sPush = rRet;
00953                                                                         rRet.Erase();
00954                                                                 }
00955                                                         }
00956                                                         APPEND(rRet," {");
00957                                                         break;
00958                                                 case 0xe:
00959                                                         if (nPart == 0)
00960                                                                 APPEND(rRet," { ");
00961 
00962 
00963                                                         if (nPart == 1)
00964                                                                 APPEND(rRet," over ");
00965                                                         APPEND(rRet," {");
00966                                                         break;
00967                                                 case 0xf:
00968                             nSubSupStartPos = rRet.Len();
00969                                                         if ((nVariation == 0) ||
00970                                                                         ((nVariation == 2) && (nPart==1)))
00971                             {
00972                                 lcl_AppendDummyTerm(rRet);
00973                                                                 APPEND(rRet," rSup");
00974                             }
00975                                                         else if ((nVariation == 1) ||
00976                                                                         ((nVariation == 2) && (nPart==0)))
00977                             {
00978                                 lcl_AppendDummyTerm(rRet);
00979                                                                 APPEND(rRet," rSub");
00980                             }
00981                                                         APPEND(rRet," {");
00982                                                         break;
00983                                                 case 0x10:
00984                                                         if (nVariation == 0)
00985                                                                 APPEND(rRet," {underline ");
00986                                                         else if (nVariation == 1)
00987                                                                 APPEND(rRet," {underline underline ");
00988                                                         APPEND(rRet," {");
00989                                                         break;
00990                                                 case 0x11:
00991                                                         if (nVariation == 0)
00992                                                                 APPEND(rRet," {overline ");
00993                                                         else if (nVariation == 1)
00994                                                                 APPEND(rRet," {overline overline ");
00995                                                         APPEND(rRet," {");
00996                                                         break;
00997                                                 case 0x12:
00998                                                         if (nPart == 0)
00999                                                         {
01000                                                                 if (nVariation == 0)
01001                                                                         APPEND(rRet," widevec ");//left arrow above
01002                                                                 else if (nVariation == 1)
01003                                                                         APPEND(rRet," widevec ");//left arrow below
01004                                                                 APPEND(rRet," {");
01005                                                         }
01006                                                         break;
01007                                                 case 0x13:
01008                                                         if (nPart == 0)
01009                                                         {
01010                                                                 if (nVariation == 0)
01011                                                                         APPEND(rRet," widevec ");//right arrow above
01012                                                                 else if (nVariation == 1)
01013                                                                         APPEND(rRet," widevec ");//right arrow below
01014                                                                 APPEND(rRet," {");
01015                                                         }
01016                                                         break;
01017                                                 case 0x14:
01018                                                         if (nPart == 0)
01019                                                         {
01020                                                                 if (nVariation == 0)
01021                                                                         APPEND(rRet," widevec ");//double arrow above
01022                                                                 else if (nVariation == 1)
01023                                                                         APPEND(rRet," widevec ");//double arrow below
01024                                                                 APPEND(rRet," {");
01025                                                         }
01026                                                         break;
01027                                                 case 0x15:
01028                                                         if (nPart == 0)
01029                                                         {
01030                                                                 if ((nVariation == 3) || (nVariation == 4))
01031                                                                         APPEND(rRet," lInt");
01032                                                                 else
01033                                                                         APPEND(rRet," Int");
01034                                                                 if ( (nVariation != 0) && (nVariation != 3))
01035                                                                 {
01036                                                                         sPush = rRet;
01037                                                                         rRet.Erase();
01038                                                                 }
01039                                                         }
01040                                                         if (((nVariation == 1) ||
01041                                                                         (nVariation == 4)) && (nPart==1))
01042                                                                 APPEND(rRet," rSub");
01043                                                         else if ((nVariation == 2) && (nPart==2))
01044                                                                 APPEND(rRet," rSup");
01045                                                         else if ((nVariation == 2) && (nPart==1))
01046                                                                 APPEND(rRet," rSub");
01047                                                         APPEND(rRet," {");
01048                                                         break;
01049                                                 case 0x16:
01050                                                         if (nPart == 0)
01051                                                         {
01052                                                                 if ((nVariation == 2) || (nVariation == 3))
01053                                                                         APPEND(rRet," llInt");
01054                                                                 else
01055                                                                         APPEND(rRet," iInt");
01056                                                                 if ( (nVariation != 0) && (nVariation != 2))
01057                                                                 {
01058                                                                         sPush = rRet;
01059                                                                         rRet.Erase();
01060                                                                 }
01061                                                         }
01062                                                         if (((nVariation == 1) ||
01063                                                                         (nVariation == 3)) && (nPart==1))
01064                                                                 APPEND(rRet," rSub");
01065                                                         APPEND(rRet," {");
01066                                                         break;
01067                                                 case 0x17:
01068                                                         if (nPart == 0)
01069                                                         {
01070                                                                 if ((nVariation == 2) || (nVariation == 3))
01071                                                                         APPEND(rRet," lllInt");
01072                                                                 else
01073                                                                         APPEND(rRet," iiInt");
01074                                                                 if ( (nVariation != 0) && (nVariation != 2))
01075                                                                 {
01076                                                                         sPush = rRet;
01077                                                                         rRet.Erase();
01078                                                                 }
01079                                                         }
01080                                                         if (((nVariation == 1) ||
01081                                                                         (nVariation == 3)) && (nPart==1))
01082                                                                 APPEND(rRet," rSub");
01083                                                         APPEND(rRet," {");
01084                                                         break;
01085                                                 case 0x18:
01086                                                         if (nPart == 0)
01087                                                         {
01088                                                                 if (nVariation == 2)
01089                                                                         APPEND(rRet," lInt");
01090                                                                 else
01091                                                                         APPEND(rRet," Int");
01092                                                                 sPush = rRet;
01093                                                                 rRet.Erase();
01094                                                         }
01095                                                         if (((nVariation == 1) ||
01096                                                                         (nVariation == 2)) && (nPart==1))
01097                                                                 APPEND(rRet," cSub");
01098                                                         else if ((nVariation == 0) && (nPart==2))
01099                                                                 APPEND(rRet," cSup");
01100                                                         else if ((nVariation == 0) && (nPart==1))
01101                                                                 APPEND(rRet," cSub");
01102                                                         APPEND(rRet," {");
01103                                                         break;
01104                                                 case 0x19:
01105                                                         if (nPart == 0)
01106                                                         {
01107                                                                 if (nVariation == 0)
01108                                                                         APPEND(rRet," llInt");
01109                                                                 else
01110                                                                         APPEND(rRet," iInt");
01111                                                                 sPush = rRet;
01112                                                                 rRet.Erase();
01113                                                         }
01114                                                         if (nPart==1)
01115                                                                 APPEND(rRet," cSub");
01116                                                         APPEND(rRet," {");
01117                                                         break;
01118                                                 case 0x1a:
01119                                                         if (nPart == 0)
01120                                                         {
01121                                                                 if (nVariation == 0)
01122                                                                         APPEND(rRet," lllInt");
01123                                                                 else
01124                                                                         APPEND(rRet," iiInt");
01125                                                                 sPush = rRet;
01126                                                                 rRet.Erase();
01127                                                         }
01128                                                         if (nPart==1)
01129                                                                 APPEND(rRet," cSub");
01130                                                         APPEND(rRet," {");
01131                                                         break;
01132                                                 case 0x1b:
01133                                                 case 0x1c:
01134                                                         APPEND(rRet," {");
01135                                                         break;
01136                                                 case 0x1d:
01137                                                         if (nPart == 0)
01138                                                         {
01139                                                                 APPEND(rRet," Sum");
01140                                                                 if (nVariation != 2)
01141                                                                 {
01142                                                                         sPush = rRet;
01143                                                                         rRet.Erase();
01144                                                                 }
01145                                                         }
01146                                                         if ((nVariation == 0) && (nPart==1))
01147                                                                 APPEND(rRet," cSub");
01148                                                         else if ((nVariation == 1) && (nPart==2))
01149                                                                 APPEND(rRet," cSup");
01150                                                         else if ((nVariation == 1) && (nPart==1))
01151                                                                 APPEND(rRet," cSub");
01152                                                         APPEND(rRet," {");
01153                                                         break;
01154                                                 case 0x1e:
01155                                                         if (nPart == 0)
01156                                                         {
01157                                                                 APPEND(rRet," Sum");
01158                                                                 sPush = rRet;
01159                                                                 rRet.Erase();
01160                                                         }
01161                                                         if ((nVariation == 0) && (nPart==1))
01162                                                                 APPEND(rRet," rSub");
01163                                                         else if ((nVariation == 1) && (nPart==2))
01164                                                                 APPEND(rRet," rSup");
01165                                                         else if ((nVariation == 1) && (nPart==1))
01166                                                                 APPEND(rRet," rSub");
01167                                                         APPEND(rRet," {");
01168                                                         break;
01169                                                 case 0x1f:
01170                                                         if (nPart == 0)
01171                                                         {
01172                                                                 APPEND(rRet," Prod");
01173                                                                 if (nVariation != 2)
01174                                                                 {
01175                                                                         sPush = rRet;
01176                                                                         rRet.Erase();
01177                                                                 }
01178                                                         }
01179                                                         if ((nVariation == 0) && (nPart==1))
01180                                                                 APPEND(rRet," cSub");
01181                                                         else if ((nVariation == 1) && (nPart==2))
01182                                                                 APPEND(rRet," cSup");
01183                                                         else if ((nVariation == 1) && (nPart==1))
01184                                                                 APPEND(rRet," cSub");
01185                                                         APPEND(rRet," {");
01186                                                         break;
01187                                                 case 0x20:
01188                                                         if (nPart == 0)
01189                                                         {
01190                                                                 APPEND(rRet," Prod");
01191                                                                 sPush = rRet;
01192                                                                 rRet.Erase();
01193                                                         }
01194                                                         if ((nVariation == 0) && (nPart==1))
01195                                                                 APPEND(rRet," rSub");
01196                                                         else if ((nVariation == 1) && (nPart==2))
01197                                                                 APPEND(rRet," rSup");
01198                                                         else if ((nVariation == 1) && (nPart==1))
01199                                                                 APPEND(rRet," rSub");
01200                                                         APPEND(rRet," {");
01201                                                         break;
01202                                                 case 0x21:
01203                                                         if (nPart == 0)
01204                                                         {
01205                                                                 APPEND(rRet," coProd");
01206                                                                 if (nVariation != 2)
01207                                                                 {
01208                                                                         sPush = rRet;
01209                                                                         rRet.Erase();
01210                                                                 }
01211                                                         }
01212                                                         if ((nVariation == 0) && (nPart==1))
01213                                                                 APPEND(rRet," cSub");
01214                                                         else if ((nVariation == 1) && (nPart==2))
01215                                                                 APPEND(rRet," cSup");
01216                                                         else if ((nVariation == 1) && (nPart==1))
01217                                                                 APPEND(rRet," cSub");
01218                                                         APPEND(rRet," {");
01219                                                         break;
01220                                                 case 0x22:
01221                                                         if (nPart == 0)
01222                                                         {
01223                                                                 APPEND(rRet," coProd");
01224                                                                 sPush = rRet;
01225                                                                 rRet.Erase();
01226                                                         }
01227                                                         if ((nVariation == 0) && (nPart==1))
01228                                                                 APPEND(rRet," rSub");
01229                                                         else if ((nVariation == 1) && (nPart==2))
01230                                                                 APPEND(rRet," rSup");
01231                                                         else if ((nVariation == 1) && (nPart==1))
01232                                                                 APPEND(rRet," rSub");
01233                                                         APPEND(rRet," {");
01234                                                         break;
01235                                                 case 0x23:
01236                                                         if (nPart == 0)
01237                                                         {
01238                                                                 APPEND(rRet," union"); //union
01239                                                                 if (nVariation != 2)
01240                                                                 {
01241                                                                         sPush = rRet;
01242                                                                         rRet.Erase();
01243                                                                 }
01244                                                         }
01245                                                         if ((nVariation == 0) && (nPart==1))
01246                                                                 APPEND(rRet," cSub");
01247                                                         else if ((nVariation == 1) && (nPart==2))
01248                                                                 APPEND(rRet," cSup");
01249                                                         else if ((nVariation == 1) && (nPart==1))
01250                                                                 APPEND(rRet," cSub");
01251                                                         APPEND(rRet," {");
01252                                                         break;
01253                                                 case 0x24:
01254                                                         if (nPart == 0)
01255                                                         {
01256                                                                 APPEND(rRet," union"); //union
01257                                                                 sPush = rRet;
01258                                                                 rRet.Erase();
01259                                                         }
01260                                                         if ((nVariation == 0) && (nPart==1))
01261                                                                 APPEND(rRet," rSub");
01262                                                         else if ((nVariation == 1) && (nPart==2))
01263                                                                 APPEND(rRet," rSup");
01264                                                         else if ((nVariation == 1) && (nPart==1))
01265                                                                 APPEND(rRet," rSub");
01266                                                         APPEND(rRet," {");
01267                                                         break;
01268                                                 case 0x25:
01269                                                         if (nPart == 0)
01270                                                         {
01271                                                                 APPEND(rRet," intersect"); //intersect
01272                                                                 if (nVariation != 2)
01273                                                                 {
01274                                                                         sPush = rRet;
01275                                                                         rRet.Erase();
01276                                                                 }
01277                                                         }
01278                                                         if ((nVariation == 0) && (nPart==1))
01279                                                                 APPEND(rRet," cSub");
01280                                                         else if ((nVariation == 1) && (nPart==2))
01281                                                                 APPEND(rRet," cSup");
01282                                                         else if ((nVariation == 1) && (nPart==1))
01283                                                                 APPEND(rRet," cSub");
01284                                                         APPEND(rRet," {");
01285                                                         break;
01286                                                 case 0x26:
01287                                                         if (nPart == 0)
01288                                                         {
01289                                                                 APPEND(rRet," intersect"); //intersect
01290                                                                 sPush = rRet;
01291                                                                 rRet.Erase();
01292                                                         }
01293                                                         if ((nVariation == 0) && (nPart==1))
01294                                                                 APPEND(rRet," rSub");
01295                                                         else if ((nVariation == 1) && (nPart==2))
01296                                                                 APPEND(rRet," rSup");
01297                                                         else if ((nVariation == 1) && (nPart==1))
01298                                                                 APPEND(rRet," rSub");
01299                                                         APPEND(rRet," {");
01300                                                         break;
01301                                                 case 0x27:
01302                                                         if ((nVariation == 0) && (nPart==1))
01303                                                                 APPEND(rRet," cSup");
01304                                                         else if ((nVariation == 1) && (nPart==1))
01305                                                                 APPEND(rRet," cSub");
01306                                                         else if ((nVariation == 2) && (nPart==1))
01307                                                                 APPEND(rRet," cSub");
01308                                                         else if ((nVariation == 2) && (nPart==2))
01309                                                                 APPEND(rRet," cSup");
01310                                                         APPEND(rRet," {");
01311                                                         break;
01312                                                 case 0x28:
01313                                                         if (nVariation == 0)
01314                                                         {
01315                                                                 if (nPart == 0)
01316                                                                 {
01317                                                                         sPush = rRet;
01318                                                                         rRet.Erase();
01319                                                                 }
01320                                                         }
01321                                                         APPEND(rRet," {");
01322                                                         if (nVariation == 0)
01323                                                         {
01324                                                                 if (nPart == 1)
01325                                                                         APPEND(rRet,"alignr ");
01326                                                         }
01327                                                         if (nPart == 0)
01328                                                                 APPEND(rRet,"\\lline ");
01329                                                         if (nVariation == 1)
01330                                                                 APPEND(rRet,"overline ");
01331                                                         break;
01332                                                 case 0x29:
01333                                                         APPEND(rRet," {");
01334                                                         break;
01335                                                 case 0x2a:
01336                                                         if (nPart == 0)
01337                                                         {
01338                                                                 sPush = rRet;
01339                                                                 rRet.Erase();
01340                                                         }
01341                                                         if ((nVariation == 0) && (nPart==0))
01342                                                                 APPEND(rRet," rSup");
01343                                                         else if ((nVariation == 2) && (nPart==1))
01344                                                                 APPEND(rRet," rSup");
01345                                                         else if ((nVariation == 1) && (nPart==0))
01346                                                                 APPEND(rRet," rSub");
01347                                                         else if ((nVariation == 2) && (nPart==0))
01348                                                                 APPEND(rRet," rSub");
01349                                                         APPEND(rRet," {");
01350                                                         break;
01351                                                 case 0x2b:
01352                                                         if (nPart == 0)
01353                                                         {
01354                                                                 sPush = rRet;
01355                                                                 rRet.Erase();
01356                                                         }
01357                                                         if ((nVariation == 0) && (nPart==0))
01358                                                                 APPEND(rRet," cSup");
01359                                                         else if ((nVariation == 2) && (nPart==1))
01360                                                                 APPEND(rRet," cSup");
01361                                                         else if ((nVariation == 1) && (nPart==0))
01362                                                                 APPEND(rRet," cSub");
01363                                                         else if ((nVariation == 2) && (nPart==0))
01364                                                                 APPEND(rRet," cSub");
01365                                                         APPEND(rRet," {");
01366                                                         break;
01367                                                 case 0x2c:
01368                                                         if (nPart == 0)
01369                                                                 APPEND(rRet,"\"\"");
01370                                                         if ((nVariation == 0)
01371                                                                         || ((nVariation == 2) && (nPart==1)))
01372                                                                 APPEND(rRet," lSup");
01373                                                         else if ((nVariation == 1)
01374                                                                         || ((nVariation == 2) && (nPart==0)))
01375                                                                 APPEND(rRet," lSub");
01376                                                         APPEND(rRet," {");
01377                                                         break;
01378                                                 case 0x2d:
01379                                                         if (nVariation==0)
01380                                                         {
01381                                                                 if (nPart == 0)
01382                                                                         APPEND(rRet," langle ");
01383                                                         }
01384                                                         else if (nVariation==1)
01385                                                         {
01386                                                                 APPEND(rRet," \\langle ");
01387                                                                 newline--;
01388                                                         }
01389                                                         else if (nVariation==2)
01390                                                         {
01391                                                                 APPEND(rRet," \\lline ");
01392                                                                 newline--;
01393                                                         }
01394                                                         break;
01395                                                 case 0x2e:
01396                                                         if (nVariation == 0)
01397                                                                 APPEND(rRet," widevec ");//left below
01398                                                         else if (nVariation == 1)
01399                                                                 APPEND(rRet," widevec ");//right below
01400                                                         else if (nVariation == 2)
01401                                                                 APPEND(rRet," widevec ");//double headed below
01402                                                         APPEND(rRet," {");
01403                                                         break;
01404                                                 case 0x2f:
01405                                                         if (nVariation == 0)
01406                                                                 APPEND(rRet," widevec ");//left above
01407                                                         else if (nVariation == 1)
01408                                                                 APPEND(rRet," widevec ");//right above
01409                                                         else if (nVariation == 2)
01410                                                                 APPEND(rRet," widevec ");//double headed above
01411                                                         APPEND(rRet," {");
01412                                                         break;
01413                                                 default:
01414                                                         break;
01415                                                 }
01416                         sal_Int16 nOldCurSize=nCurSize;
01417                         xub_StrLen nSizeStartPos = rRet.Len();
01418                                                 HandleSize(nLSize,nDSize,nSetSize);
01419                                                 nRet = HandleRecords(nLevel+1);
01420                                                 while (nSetSize)
01421                                                 {
01422                             sal_Bool bOk=sal_False;
01423                             xub_StrLen nI = rRet.SearchBackward('{');
01424                             if (nI != STRING_NOTFOUND)
01425                             {
01426                                 for(nI=nI+1;nI<rRet.Len();nI++)
01427                                     if (rRet.GetChar(nI) != ' ')
01428                                     {
01429                                         bOk=sal_True;
01430                                         break;
01431                                     }
01432                             }
01433                             else
01434                                 bOk=sal_True;
01435 
01436                             if (bOk)
01437                                                             APPEND(rRet,"} ");
01438                             else
01439                                 rRet.Erase(nSizeStartPos);
01440                                                         nSetSize--;
01441                                                         nCurSize=nOldCurSize;
01442                                                 }
01443 
01444 
01445                                                 HandleMatrixSeperator(nMatrixRows,nMatrixCols,
01446                                                         nCurCol,nCurRow);
01447 
01448                                                 switch (nSelector)
01449                                                 {
01450                                                 case 0x0:
01451                                                         if (nVariation==0)
01452                                                                 APPEND(rRet," rangle ");
01453                                                         else if (nVariation==2)
01454                                                                 APPEND(rRet," \\rangle ");
01455                                                         break;
01456                                                 case 0x1:
01457                                                         if (nVariation==0)
01458                                                                 APPEND(rRet," right )");
01459                                                         else if (nVariation==2)
01460                                                                 APPEND(rRet,"\\)");
01461                                                         break;
01462                                                 case 0x2:
01463                                                         if ((nVariation==0) || (nVariation==2))
01464                                                                 APPEND(rRet," right rbrace ");
01465                                                         else
01466                                                                 APPEND(rRet," right none ");
01467                                                         break;
01468                                                 case 0x3:
01469                                                         if (nVariation==0)
01470                                                                 APPEND(rRet," right ]");
01471                                                         else if (nVariation==2)
01472                                                                 APPEND(rRet,"\\]");
01473                                                         break;
01474                                                 case 0x4:
01475                                                         if (nVariation==0)
01476                                                                 APPEND(rRet," rline ");
01477                                                         else if (nVariation==2)
01478                                                                 APPEND(rRet," \\rline ");
01479                                                         break;
01480                                                 case 0x5:
01481                                                         if (nVariation==0)
01482                                                                 APPEND(rRet," rdline ");
01483                                                         else if (nVariation==2)
01484                                                                 APPEND(rRet," \\rdline ");
01485                                                         break;
01486                                                 case 0x6:
01487                                                         if (nVariation == 0 || nVariation == 2)
01488                                                                 APPEND(rRet," right rfloor ");
01489                                                         else if (nVariation==2)
01490                                                                 APPEND(rRet," right none ");
01491                                                         break;
01492                                                 case 0x7:
01493                                                         if (nVariation==0)
01494                                                                 APPEND(rRet," rceil ");
01495                                                         else if (nVariation==2)
01496                                                                 APPEND(rRet," \\rceil ");
01497                                                         break;
01498                                                 case 0x8:
01499                                                 case 0xa:
01500                                                         APPEND(rRet,"\\[");
01501                                                         break;
01502                                                 case 0x9:
01503                                                 case 0xc:
01504                                                         APPEND(rRet,"\\]");
01505                                                         break;
01506                                                 case 0xd:
01507                                                         APPEND(rRet,"} ");
01508                                                         if (nVariation == 1)
01509                                                         {
01510                                                                 if (nPart == 0)
01511                                                                 {
01512                                                                         newline--;
01513                                                                         sMainTerm = rRet;
01514                                                                         rRet.Erase();
01515                                                                 }
01516                                                                 else
01517                                                                 {
01518                                                                         sPush += rRet;
01519                                                                         rRet = sPush;
01520                                                                         rRet += sMainTerm;
01521                                                                 }
01522                                                         }
01523                                                         else
01524                                                         {
01525                                                                 if (nPart == 0)
01526                                                                         newline--;
01527                                                         }
01528                                                         nPart++;
01529                                                         break;
01530                                                 case 0xb:
01531                                                         APPEND(rRet,"\\)");
01532                                                         break;
01533                                                 case 0xe:
01534                                                         APPEND(rRet,"} ");
01535                                                         if (nPart == 0)
01536                                                                 newline--;
01537                                                         else
01538                                                                 APPEND(rRet,"} ");
01539                                                         nPart++;
01540                                                         break;
01541                                                 case 0xf:
01542                             {
01543                             if ((nPart == 0) &&
01544                                                                         ((nVariation == 2) || (nVariation == 1)))
01545                                                                 newline--;
01546 
01547                             sal_Bool bOk=sal_False;
01548                             xub_StrLen nI = rRet.SearchBackward('{');
01549                             if (nI != STRING_NOTFOUND)
01550                             {
01551                                 for(nI=nI+1;nI<rRet.Len();nI++)
01552                                     if (rRet.GetChar(nI) != ' ')
01553                                     {
01554                                         bOk=sal_True;
01555                                         break;
01556                                     }
01557                             }
01558                             else
01559                                 bOk=sal_True;
01560 
01561                             if (bOk)
01562                                                             APPEND(rRet,"} ");
01563                             else
01564                                 rRet.Erase(nSubSupStartPos);
01565                                                         nPart++;
01566                             }
01567                                                         break;
01568                                                 case 0x2c:
01569                                                         if ((nPart == 0) &&
01570                                                                         ((nVariation == 2) || (nVariation == 1)))
01571                                                                 newline--;
01572                                                         APPEND(rRet,"} ");
01573                                                         nPart++;
01574                                                         break;
01575                                                 case 0x2e:
01576                                                 case 0x2f:
01577                                                         APPEND(rRet,"} ");
01578                                                         break;
01579                         case 0x10:
01580                         case 0x11:
01581                             APPEND(rRet,"}} ");
01582                             break;
01583                                                 case 0x12:
01584                                                 case 0x13:
01585                                                 case 0x14:
01586                                                         if (nPart == 0)
01587                                                         {
01588                                                                 newline--;
01589                                                                 APPEND(rRet,"} ");
01590                                                         }
01591                                                         nPart++;
01592                                                         break;
01593                                                 case 0x1b:
01594                                                         APPEND(rRet,"} ");
01595                                                         if (nPart == 0)
01596                                                         {
01597                                                                 newline--;
01598                                                                 APPEND(rRet,"overbrace");
01599                                                         }
01600                                                         nPart++;
01601                                                         break;
01602                                                 case 0x1c:
01603                                                         APPEND(rRet,"} ");
01604                                                         if (nPart == 0)
01605                                                         {
01606                                                                 newline--;
01607                                                                 APPEND(rRet,"underbrace");
01608                                                         }
01609                                                         nPart++;
01610                                                         break;
01611                                                 case 0x27:
01612                                                         if (nPart==0)
01613                                                                 newline--;
01614                                                         else if ((nPart==1) &&
01615                                                                         ((nVariation == 2) || (nVariation == 1)))
01616                                                                 newline--;
01617                                                         APPEND(rRet,"} ");
01618                                                         nPart++;
01619                                                         break;
01620                                                 case 0x28:
01621                                                         APPEND(rRet,"} ");
01622                                                         if (nVariation == 0)
01623                                                         {
01624                                                                 if (nPart == 0)
01625                                                                 {
01626                                                                         sMainTerm = rRet;
01627                                                                         rRet.Erase();
01628                                                                 }
01629                                                                 else
01630                                                                 {
01631                                                                         sPush += rRet;
01632                                                                         rRet = sPush;
01633                                                                         APPEND(rRet," over ");
01634                                                                         rRet += sMainTerm;
01635                                                                 }
01636                                                         }
01637                                                         if (nPart == 0)
01638                                                                 newline--;
01639                                                         nPart++;
01640                                                         break;
01641                                                 case 0x29:
01642                                                         APPEND(rRet,"} ");
01643                                                         if (nPart == 0)
01644                                                         {
01645                                                                 newline--;
01646                                                                 switch (nVariation)
01647                                                                 {
01648                                                                 case 1:
01649                                                                         APPEND(rRet,"slash");
01650                                                                         break;
01651                                                                 default:
01652                                                                         APPEND(rRet,"wideslash");
01653                                                                         break;
01654                                                                 }
01655                                                         }
01656                                                         nPart++;
01657                                                         break;
01658                                                 case 0x1d:
01659                                                 case 0x1e:
01660                                                 case 0x1f:
01661                                                 case 0x20:
01662                                                 case 0x21:
01663                                                 case 0x22:
01664                                                 case 0x23:
01665                                                 case 0x24:
01666                                                 case 0x25:
01667                                                 case 0x26:
01668                                                         APPEND(rRet,"} ");
01669                                                         if (nPart == 0)
01670                                                         {
01671                                                                 if (nVariation != 2)
01672                                                                 {
01673                                                                         sMainTerm = rRet;
01674                                                                         rRet.Erase();
01675                                                                 }
01676                                                                 newline--;
01677                                                         }
01678                                                         else if ((nPart == 1) && (nVariation == 0))
01679                                                         {
01680                                                                 sPush += rRet;
01681                                                                 rRet = sPush;
01682                                                                 rRet += sMainTerm;
01683                                                                 newline--;
01684                                                         }
01685                                                         else if ((nPart == 1) && (nVariation == 1))
01686                                                                 newline--;
01687                                                         else if ((nPart == 2) && (nVariation == 1))
01688                                                         {
01689                                                                 sPush += rRet;
01690                                                                 rRet = sPush;
01691                                                                 rRet += sMainTerm;
01692                                                                 newline--;
01693                                                         }
01694                                                         nPart++;
01695                                                         break;
01696                                                 case 0x15:
01697                                                         APPEND(rRet,"} ");
01698                                                         if (nPart == 0)
01699                                                         {
01700                                                                 if ((nVariation != 0) && (nVariation != 3))
01701                                                                 {
01702                                                                         sMainTerm = rRet;
01703                                                                         rRet.Erase();
01704                                                                 }
01705                                                                 newline--;
01706                                                         }
01707                                                         else if ((nPart == 1) &&
01708                                                                         ((nVariation == 1) || (nVariation==4)))
01709                                                         {
01710                                                                 sPush += rRet;
01711                                                                 rRet = sPush;
01712                                                                 rRet += sMainTerm;
01713                                                                 newline--;
01714                                                         }
01715                                                         else if ((nPart == 1) && (nVariation == 2))
01716                                                                 newline--;
01717                                                         else if ((nPart == 2) && (nVariation == 2))
01718                                                         {
01719                                                                 sPush += rRet;
01720                                                                 rRet = sPush;
01721                                                                 rRet += sMainTerm;
01722                                                                 newline--;
01723                                                         }
01724                                                         nPart++;
01725                                                         break;
01726                                                 case 0x16:
01727                                                 case 0x17:
01728                                                         APPEND(rRet,"} ");
01729                                                         if (nPart == 0)
01730                                                         {
01731                                                                 if ((nVariation != 0) && (nVariation != 2))
01732                                                                 {
01733                                                                         sMainTerm = rRet;
01734                                                                         rRet.Erase();
01735                                                                 }
01736                                                                 newline--;
01737                                                         }
01738                                                         else if ((nPart == 1) &&
01739                                                                         ((nVariation == 1) || (nVariation==3)))
01740                                                         {
01741                                                                 sPush += rRet;
01742                                                                 rRet = sPush;
01743                                                                 rRet += sMainTerm;
01744                                                                 newline--;
01745                                                         }
01746                                                         nPart++;
01747                                                         break;
01748                                                 case 0x18:
01749                                                         APPEND(rRet,"} ");
01750                                                         if (nPart == 0)
01751                                                         {
01752                                                                 sMainTerm = rRet;
01753                                                                 rRet.Erase();
01754                                                                 newline--;
01755                                                         }
01756                                                         else if ((nPart == 1) &&
01757                                                                         ((nVariation == 1) || (nVariation==2)))
01758                                                         {
01759                                                                 sPush += rRet;
01760                                                                 rRet = sPush;
01761                                                                 rRet += sMainTerm;
01762                                                                 newline--;
01763                                                         }
01764                                                         else if ((nPart == 1) && (nVariation == 0))
01765                                                                 newline--;
01766                                                         else if ((nPart == 2) && (nVariation == 0))
01767                                                         {
01768                                                                 sPush += rRet;
01769                                                                 rRet = sPush;
01770                                                                 rRet += sMainTerm;
01771                                                                 newline--;
01772                                                         }
01773                                                         nPart++;
01774                                                         break;
01775                                                 case 0x19:
01776                                                 case 0x1a:
01777                                                         APPEND(rRet,"} ");
01778                                                         if (nPart == 0)
01779                                                         {
01780                                                                 sMainTerm = rRet;
01781                                                                 rRet.Erase();
01782                                                                 newline--;
01783                                                         }
01784                                                         else if (nPart == 1)
01785                                                         {
01786                                                                 sPush += rRet;
01787                                                                 rRet = sPush;
01788                                                                 rRet += sMainTerm;
01789                                                                 newline--;
01790                                                         }
01791                                                         nPart++;
01792                                                         break;
01793                                                 case 0x2a:
01794                                                 case 0x2b:
01795                                                         APPEND(rRet,"} ");
01796 
01797                                                         if ((nPart == 0) &&
01798                                                                         ((nVariation == 0) || (nVariation == 1)))
01799                                                         {
01800                                                                 sMainTerm = rRet;
01801                                                                 rRet.Erase();
01802                                                                 newline--;
01803                                                         }
01804                                                         else if ((nPart == 0) && (nVariation == 2))
01805                                                                 newline--;
01806                                                         else if ((nPart == 1) && (nVariation == 2))
01807                                                         {
01808                                                                 sMainTerm = rRet;
01809                                                                 rRet.Erase();
01810                                                                 newline--;
01811                                                         }
01812                                                         else if ((nPart == 2) || (((nPart == 1) &&
01813                                                                         (nVariation == 0) || (nVariation == 1))))
01814                                                         {
01815                                                                 sPush+=rRet;
01816                                                                 rRet = sPush;
01817                                                                 rRet += sMainTerm;
01818                                                         }
01819                                                         nPart++;
01820                                                         break;
01821                                                 case 0x2d:
01822                                                         if (nVariation==0)
01823                                                         {
01824                                                                 if (nPart == 0)
01825                                                                 {
01826                                                                         newline--; //there is another term to arrive
01827                                                                         APPEND(rRet," mline ");
01828                                                                 }
01829                                                                 else
01830                                                                         APPEND(rRet," rangle ");
01831                                                         }
01832                                                         else if (nVariation==1)
01833                                                                 APPEND(rRet," \\lline ");
01834                                                         else if (nVariation==2)
01835                                                                 APPEND(rRet," \\rangle ");
01836                                                         nPart++;
01837                                                         break;
01838                                                 default:
01839                                                         break;
01840                                                 }
01841                                                 bSilent = TRUE; //Skip the optional brackets and/or
01842                                                                                 //symbols that follow some of these
01843                                                                                 //records. Foo Data.
01844 
01845                                                 /*In matrices and piles we cannot seperate equation
01846                                                  *lines with the newline keyword*/
01847                                                 if (nMatrixCols==0)
01848                                                         newline++;
01849                                         }
01850                                 }
01851                                 break;
01852                         case CHAR:
01853                 if (xfLMOVE(nTag))
01854                     HandleNudge();
01855                                 nRet = HandleChar(nTextStart,nSetSize,nLevel,nTag,nSelector,
01856                                         nVariation,bSilent);
01857                                 break;
01858                         case TMPL:
01859                 if (xfLMOVE(nTag))
01860                     HandleNudge();
01861                                 nRet = HandleTemplate(nLevel,nSelector,nVariation,
01862                                         nLastTemplateBracket);
01863                                 break;
01864                         case PILE:
01865                 if (xfLMOVE(nTag))
01866                     HandleNudge();
01867                                 nRet = HandlePile(nSetAlign,nLevel,nSelector,nVariation);
01868                                 HandleMatrixSeperator(nMatrixRows,nMatrixCols,nCurCol,nCurRow);
01869                                 break;
01870                         case MATRIX:
01871                 if (xfLMOVE(nTag))
01872                     HandleNudge();
01873                                 nRet = HandleMatrix(nLevel,nSelector,nVariation);
01874                                 HandleMatrixSeperator(nMatrixRows,nMatrixCols,nCurCol,nCurRow);
01875                                 break;
01876                         case EMBEL:
01877                 if (xfLMOVE(nTag))
01878                     HandleNudge();
01879                                 HandleEmblishments();
01880                                 break;
01881                         case RULER:
01882                                 *pS >> nTabStops;
01883                                 for (i=0;i<nTabStops;i++)
01884                                 {
01885                                         *pS >> nTabType;
01886                                         *pS >> nTabOffset;
01887                                 }
01888                                 DBG_ASSERT(FALSE,"Not seen in the wild Equation Ruler Field")
01889                                 break;
01890                         case FONT:
01891                                 {
01892                                         MathTypeFont aFont;
01893                                         *pS >> aFont.nTface;
01894                     /*
01895                                         The typeface number is the negative (which makes it
01896                                         positive) of the typeface value (unbiased) that appears in
01897                                         CHAR records that might follow a given FONT record
01898                     */
01899                     aFont.nTface = 128-aFont.nTface;
01900                                         *pS >> aFont.nStyle;
01901                                         aUserStyles.insert(aFont);
01902                                         sFontName.Erase();
01903                                         do
01904                                         {
01905                                                 *pS >> nChar8;
01906                                                 sFontName.Append(ByteString::ConvertToUnicode(
01907                                                         nChar8,RTL_TEXTENCODING_MS_1252));
01908                                         }
01909                                         while(nChar8);
01910                                 }
01911                                 break;
01912                         case SIZE:
01913                                 HandleSetSize();
01914                                 break;
01915                         case 10:
01916                         case 11:
01917                         case 12:
01918                         case 13:
01919                         case 14:
01920                                 nLSize=nRecord-10;
01921                                 break;
01922                         case END:
01923                         default:
01924                                 break;
01925                 }
01926         }
01927     while (nRecord != END && !pS->IsEof());
01928         while (nSetSize)
01929         {
01930                 rRet += '}';
01931                 nSetSize--;
01932         }
01933         return nRet;
01934 }
01935 
01936 /*Simply determine if we are at the end of a record or the end of a line,
01937  *with fiddley logic to see if we are in a matrix or a pile or neither
01938 
01939  Note we cannot tell until after the event that this is the last entry
01940  of a pile, so we must strip the last seperator of a pile after this
01941  is detected in the PILE handler
01942  */
01943 void MathType::HandleMatrixSeperator(int nMatrixRows,int nMatrixCols,
01944         int &rCurCol,int &rCurRow)
01945 {
01946         if (nMatrixRows!=0)
01947         {
01948                 if (rCurCol == nMatrixCols-1)
01949                 {
01950                         if (rCurRow != nMatrixRows-1)
01951                                 APPEND(rRet," {} ##\n");
01952                         if (nMatrixRows!=-1)
01953                         {
01954                                 rCurCol=0;
01955                                 rCurRow++;
01956                         }
01957                 }
01958                 else
01959                 {
01960                         APPEND(rRet," {} # ");
01961                         if (nMatrixRows!=-1)
01962                                 rCurCol++;
01963                         else
01964                             rRet += '\n';
01965                 }
01966         }
01967 }
01968 
01969 /* set the alignment of the following term, but starmath currently
01970  * cannot handle vertical alignment */
01971 void MathType::HandleAlign(sal_uInt8 nHorAlign, sal_uInt8 /*nVAlign*/, int &rSetAlign)
01972 {
01973     switch(nHorAlign)
01974         {
01975         case 1:
01976         default:
01977                 APPEND(rRet,"alignl {");
01978                 break;
01979         case 2:
01980                 APPEND(rRet,"alignc {");
01981                 break;
01982         case 3:
01983                 APPEND(rRet,"alignr {");
01984                 break;
01985         }
01986 #if 0
01987         switch(nVAlign)
01988         {
01989         }
01990         rSetAlign+=2;
01991 #endif
01992         rSetAlign++;
01993 }
01994 
01995 /* set size of text, complexity due to overuse of signedness as a flag
01996  * indicator by mathtype file format*/
01997 sal_Bool MathType::HandleSize(sal_Int16 nLstSize,sal_Int16 nDefSize, int &rSetSize)
01998 {
01999         sal_Bool bRet=FALSE;
02000     if (nLstSize < 0)
02001         {
02002         if ((-nLstSize/32 != nDefaultSize) && (-nLstSize/32 != nCurSize))
02003                 {
02004                         if (rSetSize)
02005                         {
02006                                 rSetSize--;
02007                                 rRet += '}';
02008                                 bRet=TRUE;
02009                         }
02010             if (-nLstSize/32 != nLastSize)
02011                         {
02012                                 nLastSize = nCurSize;
02013                                 APPEND(rRet," size ");
02014                 rRet += String::CreateFromInt32(-nLstSize/32);
02015                                 rRet += '{';
02016                                 bRet=TRUE;
02017                                 rSetSize++;
02018                         }
02019             nCurSize = -nLstSize/32;
02020                 }
02021         }
02022         else
02023         {
02024                 /*sizetable should theoreticaly be filled with the default sizes
02025                  *of the various font groupings matching starmaths equivalents
02026                  in aTypeFaces, and a test would be done to see if the new font
02027                  size would be the same as what starmath would have chosen for
02028                  itself anyway in which case the size setting could be ignored*/
02029         nLstSize = aSizeTable[nLstSize];
02030         nLstSize = nLstSize + nDefSize;
02031         //if (nLstSize != nDefaultSize)
02032         if (nLstSize != nCurSize)
02033                 {
02034                         if (rSetSize)
02035                         {
02036                                 rSetSize--;
02037                                 rRet += '}';
02038                                 bRet=TRUE;
02039                         }
02040             if (nLstSize != nLastSize)
02041                         {
02042                                 nLastSize = nCurSize;
02043                                 APPEND(rRet," size ");
02044                 rRet += String::CreateFromInt32(nLstSize);
02045                                 rRet += '{';
02046                                 bRet=TRUE;
02047                                 rSetSize++;
02048                         }
02049             nCurSize = nLstSize;
02050                 }
02051         }
02052         return bRet;
02053 }
02054 
02055 int MathType::ConvertFromStarMath( SfxMedium& rMedium )
02056 {
02057         if (!pTree)
02058                 return 0;
02059 
02060     SvStream *pStream = rMedium.GetOutStream();
02061     if ( pStream )
02062     {
02063         SvStorageRef pStor = new SotStorage( pStream, FALSE );
02064 
02065         SvGlobalName aGName(0x0002ce02L, 0x0000, 0x0000,0xc0,0x00,
02066             0x00,0x00,0x00,0x00,0x00,0x46 );
02067         pStor->SetClass( aGName, 0, C2S("Microsoft Equation 3.0"));
02068 
02069         static sal_uInt8 __READONLY_DATA aCompObj[] = {
02070             0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
02071             0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0xCE, 0x02, 0x00,
02072             0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
02073             0x00, 0x00, 0x00, 0x46, 0x17, 0x00, 0x00, 0x00,
02074             0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
02075             0x74, 0x20, 0x45, 0x71, 0x75, 0x61, 0x74, 0x69,
02076             0x6F, 0x6E, 0x20, 0x33, 0x2E, 0x30, 0x00, 0x0C,
02077             0x00, 0x00, 0x00, 0x44, 0x53, 0x20, 0x45, 0x71,
02078             0x75, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x0B,
02079             0x00, 0x00, 0x00, 0x45, 0x71, 0x75, 0x61, 0x74,
02080             0x69, 0x6F, 0x6E, 0x2E, 0x33, 0x00, 0xF4, 0x39,
02081             0xB2, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02082             0x00, 0x00, 0x00, 0x00, 0x00, 0x00
02083         };
02084         SvStorageStreamRef xStor( pStor->OpenSotStream( C2S("\1CompObj")));
02085         xStor->Write(aCompObj,sizeof(aCompObj));
02086 
02087         static sal_uInt8 __READONLY_DATA aOle[] = {
02088             0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
02089             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
02090             0x00, 0x00, 0x00, 0x00
02091             };
02092         SvStorageStreamRef xStor2( pStor->OpenSotStream( C2S("\1Ole")));
02093         xStor2->Write(aOle,sizeof(aOle));
02094         xStor.Clear();
02095         xStor2.Clear();
02096 
02097         SvStorageStreamRef xSrc = pStor->OpenSotStream(C2S("Equation Native"));
02098         if ( (!xSrc.Is()) || (SVSTREAM_OK != xSrc->GetError()))
02099             return 0;
02100 
02101         pS = &xSrc;
02102         pS->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
02103 
02104         pS->SeekRel(EQNOLEFILEHDR_SIZE); //Skip 28byte Header and fill it in later
02105         *pS << sal_uInt8(0x03);
02106         *pS << sal_uInt8(0x01);
02107         *pS << sal_uInt8(0x01);
02108         *pS << sal_uInt8(0x03);
02109         *pS << sal_uInt8(0x00);
02110         sal_uInt32 nSize = pS->Tell();
02111         nPendingAttributes=0;
02112 
02113         HandleNodes(pTree);
02114         *pS << sal_uInt8(END);
02115 
02116         nSize = pS->Tell()-nSize;
02117         pS->Seek(0);
02118         EQNOLEFILEHDR aHdr(nSize+4+1);
02119         aHdr.Write(pS);
02120 
02121         pStor->Commit();
02122     }
02123 
02124         return 1;
02125 }
02126 
02127 
02128 sal_uInt8 MathType::HandleNodes(SmNode *pNode,int nLevel)
02129 {
02130         sal_Bool bRet=FALSE;
02131         switch(pNode->GetType())
02132         {
02133                 case NATTRIBUT:
02134                         HandleAttributes(pNode,nLevel);
02135                         break;
02136                 case NTEXT:
02137                         HandleText(pNode,nLevel);
02138                         break;
02139                 case NVERTICAL_BRACE:
02140                         HandleVerticalBrace(pNode,nLevel);
02141                         break;
02142                 case NBRACE:
02143                         HandleBrace(pNode,nLevel);
02144                         break;
02145                 case NOPER:
02146                         HandleOperator(pNode,nLevel);
02147                         break;
02148                 case NBINVER:
02149                         HandleFractions(pNode,nLevel);
02150                         break;
02151                 case NROOT:
02152                         HandleRoot(pNode,nLevel);
02153                         break;
02154                 case NSPECIAL:
02155                         {
02156                         SmTextNode *pText=(SmTextNode *)pNode;
02157                         //if the token str and the result text are the same then this
02158                         //is to be seen as text, else assume its a mathchar
02159                         if (pText->GetText() == pText->GetToken().aText)
02160                                 HandleText(pText,nLevel);
02161                         else
02162                                 HandleMath(pText,nLevel);
02163                         }
02164                         break;
02165                 case NMATH:
02166                         HandleMath(pNode,nLevel);
02167                         break;
02168                 case NSUBSUP:
02169                         HandleSubSupScript(pNode,nLevel);
02170                         break;
02171                 case NEXPRESSION:
02172                         {
02173                         USHORT  nSize = pNode->GetNumSubNodes();
02174                         for (USHORT i = 0; i < nSize; i++)
02175                                 if (SmNode *pTemp = pNode->GetSubNode(i))
02176                                         HandleNodes(pTemp,nLevel+1);
02177                         }
02178                         break;
02179                 case NTABLE:
02180                         //Root Node, PILE equivalent, i.e. vertical stack
02181                         HandleTable(pNode,nLevel);
02182                         break;
02183                 case NMATRIX:
02184                         HandleSmMatrix((SmMatrixNode *)pNode,nLevel);
02185                         break;
02186                 case NLINE:
02187                         {
02188                         *pS << sal_uInt8(0x0a);
02189                         *pS << sal_uInt8(LINE);
02190                         USHORT  nSize = pNode->GetNumSubNodes();
02191                         for (USHORT i = 0; i < nSize; i++)
02192                                 if (SmNode *pTemp = pNode->GetSubNode(i))
02193                                         HandleNodes(pTemp,nLevel+1);
02194                         *pS << sal_uInt8(END);
02195                         }
02196                         break;
02197                 case NALIGN:
02198                         HandleMAlign(pNode,nLevel);
02199                         break;
02200                 case NBLANK:
02201                         *pS << sal_uInt8(CHAR);
02202                         *pS << sal_uInt8(0x98);
02203                         if (pNode->GetToken().eType == TSBLANK)
02204                                 *pS << sal_uInt16(0xEB04);
02205                         else
02206                                 *pS << sal_uInt16(0xEB05);
02207                         break;
02208                 default:
02209                         {
02210                         USHORT  nSize = pNode->GetNumSubNodes();
02211                         for (USHORT i = 0; i < nSize; i++)
02212                                 if (SmNode *pTemp = pNode->GetSubNode(i))
02213                                         HandleNodes(pTemp,nLevel+1);
02214                         }
02215                         break;
02216         }
02217         return bRet;
02218 }
02219 
02220 
02221 int MathType::StartTemplate(sal_uInt16 nSelector,sal_uInt16 nVariation)
02222 {
02223         int nOldPending=nPendingAttributes;
02224         *pS << sal_uInt8(TMPL); //Template
02225         *pS << sal_uInt8(nSelector); //selector
02226         *pS << sal_uInt8(nVariation); //variation
02227         *pS << sal_uInt8(0x00); //options
02228         *pS << sal_uInt8(LINE);
02229         //theres just no way we can now handle any character
02230         //attributes (from mathtypes perspective) centered
02231         //over an expression but above template attribute
02232         //such as widevec and similiar constructs
02233         //we have to drop them
02234         nPendingAttributes=0;
02235         return nOldPending;
02236 }
02237 
02238 void MathType::EndTemplate(int nOldPendingAttributes)
02239 {
02240         *pS << sal_uInt8(END); //end line
02241         *pS << sal_uInt8(END); //end template
02242         nPendingAttributes=nOldPendingAttributes;
02243 }
02244 
02245 
02246 void MathType::HandleSmMatrix(SmMatrixNode *pMatrix,int nLevel)
02247 {
02248         *pS << sal_uInt8(MATRIX);
02249         *pS << sal_uInt8(0x00); //vAlign ?
02250         *pS << sal_uInt8(0x00); //h_just
02251         *pS << sal_uInt8(0x00); //v_just
02252         *pS << sal_uInt8(pMatrix->GetNumRows()); //v_just
02253         *pS << sal_uInt8(pMatrix->GetNumCols()); //v_just
02254         int nBytes=(pMatrix->GetNumRows()+1)*2/8;
02255         if (((pMatrix->GetNumRows()+1)*2)%8)
02256                 nBytes++;
02257         for (USHORT j = 0; j < nBytes; j++)
02258                 *pS << sal_uInt8(0x00); //row_parts
02259         nBytes=(pMatrix->GetNumCols()+1)*2/8;
02260         if (((pMatrix->GetNumCols()+1)*2)%8)
02261                 nBytes++;
02262         for (USHORT k = 0; k < nBytes; k++)
02263                 *pS << sal_uInt8(0x00); //col_parts
02264         USHORT  nSize = pMatrix->GetNumSubNodes();
02265         for (USHORT i = 0; i < nSize; i++)
02266                 if (SmNode *pTemp = pMatrix->GetSubNode(i))
02267                 {
02268                         *pS << sal_uInt8(LINE); //line
02269                         HandleNodes(pTemp,nLevel+1);
02270                         *pS << sal_uInt8(END); //end line
02271                 }
02272         *pS << sal_uInt8(END);
02273 }
02274 
02275 
02276 //Root Node, PILE equivalent, i.e. vertical stack
02277 void MathType::HandleTable(SmNode *pNode,int nLevel)
02278 {
02279         USHORT  nSize = pNode->GetNumSubNodes();
02280         //The root of the starmath is a table, if
02281         //we convert this them each iteration of
02282         //conversion from starmath to mathtype will
02283         //add an extra unnecessary level to the
02284         //mathtype output stack which would grow
02285         //without bound in a multi step conversion
02286 
02287         if (nLevel == 0)
02288                 *pS << sal_uInt8(0x0A); //initial size
02289 
02290         if ( nLevel || (nSize >1))
02291         {
02292                 *pS << sal_uInt8(PILE);
02293                 *pS << sal_uInt8(nHAlign); //vAlign ?
02294                 *pS << sal_uInt8(0x01); //hAlign
02295         }
02296 
02297         for (USHORT i = 0; i < nSize; i++)
02298                 if (SmNode *pTemp = pNode->GetSubNode(i))
02299                 {
02300                         *pS << sal_uInt8(LINE);
02301                         HandleNodes(pTemp,nLevel+1);
02302                         *pS << sal_uInt8(END);
02303                 }
02304         if (nLevel || (nSize>1))
02305                 *pS << sal_uInt8(END);
02306 }
02307 
02308 
02309 void MathType::HandleRoot(SmNode *pNode,int nLevel)
02310 {
02311     //USHORT  nSize = pNode->GetNumSubNodes();
02312         SmNode *pTemp;
02313         *pS << sal_uInt8(TMPL); //Template
02314         *pS << sal_uInt8(0x0D); //selector
02315         if (pNode->GetSubNode(0))
02316                 *pS << sal_uInt8(0x01); //variation
02317         else
02318                 *pS << sal_uInt8(0x00); //variation
02319         *pS << sal_uInt8(0x00); //options
02320 
02321         /*
02322         if (pTemp = pNode->GetSubNode(1))
02323                         HandleNodes(pTemp,nLevel+1);
02324         */
02325     if (NULL != (pTemp = pNode->GetSubNode(2)))
02326         {
02327                 *pS << sal_uInt8(LINE); //line
02328                 HandleNodes(pTemp,nLevel+1);
02329                 *pS << sal_uInt8(END);
02330         }
02331 
02332     if (NULL != (pTemp = pNode->GetSubNode(0)))
02333         {
02334                 *pS << sal_uInt8(LINE); //line
02335                 HandleNodes(pTemp,nLevel+1);
02336                 *pS << sal_uInt8(END);
02337         }
02338         else
02339                 *pS << sal_uInt8(LINE|0x10); //dummy line
02340 
02341 
02342 
02343         *pS << sal_uInt8(END);
02344 }
02345 
02346 sal_uInt8 MathType::HandleCScript(SmNode *pNode,SmNode *pContent,int nLevel,
02347         ULONG *pPos,sal_Bool bTest)
02348 {
02349         sal_uInt8 nVariation2=0xff;
02350 
02351         if (bTest && pNode->GetSubNode(CSUP+1))
02352         {
02353                 nVariation2=0;
02354                 if (pNode->GetSubNode(CSUB+1))
02355                         nVariation2=2;
02356         }
02357         else if (pNode->GetSubNode(CSUB+1))
02358                 nVariation2=1;
02359 
02360         if (nVariation2!=0xff)
02361         {
02362                 if (pPos)
02363                         *pPos = pS->Tell();
02364                 *pS << sal_uInt8(TMPL); //Template
02365                 *pS << sal_uInt8(0x2B); //selector
02366                 *pS << nVariation2;
02367                 *pS << sal_uInt8(0x00); //options
02368 
02369                 if (pContent)
02370                 {
02371                         *pS << sal_uInt8(LINE); //line
02372                         HandleNodes(pContent,nLevel+1);
02373                         *pS << sal_uInt8(END); //line
02374                 }
02375                 else
02376                         *pS << sal_uInt8(LINE|0x10);
02377 
02378                 *pS << sal_uInt8(0x0B);
02379 
02380                 SmNode *pTemp;
02381         if (NULL != (pTemp = pNode->GetSubNode(CSUB+1)))
02382                 {
02383                         *pS << sal_uInt8(LINE); //line
02384                         HandleNodes(pTemp,nLevel+1);
02385                         *pS << sal_uInt8(END); //line
02386                 }
02387                 else
02388                         *pS << sal_uInt8(LINE|0x10);
02389         if (bTest && NULL != (pTemp = pNode->GetSubNode(CSUP+1)))
02390                 {
02391                         *pS << sal_uInt8(LINE); //line
02392                         HandleNodes(pTemp,nLevel+1);
02393                         *pS << sal_uInt8(END); //line
02394                 }
02395                 else
02396                         *pS << sal_uInt8(LINE|0x10);
02397         }
02398         return nVariation2;
02399 }
02400 
02401 
02402 
02403 /*
02404  Sub and Sup scripts and another problem area, StarMath
02405  can have all possible options used at the same time, whereas
02406  Mathtype cannot. The ordering of the nodes for each system
02407  is quite different as well leading to some complexity
02408  */
02409 void MathType::HandleSubSupScript(SmNode *pNode,int nLevel)
02410 {
02411     //USHORT  nSize = pNode->GetNumSubNodes();
02412         SmNode *pTemp;
02413 
02414         sal_uInt8 nVariation=0xff;
02415         if (pNode->GetSubNode(LSUP+1))
02416         {
02417                 nVariation=0;
02418                 if (pNode->GetSubNode(LSUB+1))
02419                         nVariation=2;
02420         }
02421     else if (NULL != (pTemp = pNode->GetSubNode(LSUB+1)))
02422                 nVariation=1;
02423 
02424         if (nVariation!=0xff)
02425         {
02426                 *pS << sal_uInt8(TMPL); //Template
02427                 *pS << sal_uInt8(0x2c); //selector
02428                 *pS << nVariation;
02429                 *pS << sal_uInt8(0x00); //options
02430                 *pS << sal_uInt8(0x0B);
02431 
02432         if (NULL != (pTemp = pNode->GetSubNode(LSUB+1)))
02433                 {
02434                         *pS << sal_uInt8(LINE); //line
02435                         HandleNodes(pTemp,nLevel+1);
02436                         *pS << sal_uInt8(END); //line
02437                 }
02438                 else
02439                         *pS << sal_uInt8(LINE|0x10);
02440         if (NULL != (pTemp = pNode->GetSubNode(LSUP+1)))
02441                 {
02442                         *pS << sal_uInt8(LINE); //line
02443                         HandleNodes(pTemp,nLevel+1);
02444                         *pS << sal_uInt8(END); //line
02445                 }
02446                 else
02447                         *pS << sal_uInt8(LINE|0x10);
02448                 *pS << sal_uInt8(END);
02449                 nVariation=0xff;
02450         }
02451 
02452 
02453         sal_uInt8 nVariation2=HandleCScript(pNode,NULL,nLevel);
02454 
02455     if (NULL != (pTemp = pNode->GetSubNode(0)))
02456         {
02457 //              *pS << sal_uInt8(0x0A);
02458 //              *pS << sal_uInt8(LINE);
02459                 HandleNodes(pTemp,nLevel+1);
02460 //              *pS << sal_uInt8(END);
02461         }
02462 
02463         if (nVariation2 != 0xff)
02464                 *pS << sal_uInt8(END);
02465 
02466     if (NULL != (pNode->GetSubNode(RSUP+1)))
02467         {
02468                 nVariation=0;
02469                 if (pNode->GetSubNode(RSUB+1))
02470                         nVariation=2;
02471         }
02472     else if (NULL != (pTemp = pNode->GetSubNode(RSUB+1)))
02473                 nVariation=1;
02474 
02475         if (nVariation!=0xff)
02476         {
02477                 *pS << sal_uInt8(TMPL); //Template
02478                 *pS << sal_uInt8(0x0F); //selector
02479                 *pS << nVariation;
02480                 *pS << sal_uInt8(0x00); //options
02481                 *pS << sal_uInt8(0x0B);
02482 
02483         if (NULL != (pTemp = pNode->GetSubNode(RSUB+1)))
02484                 {
02485                         *pS << sal_uInt8(LINE); //line
02486                         HandleNodes(pTemp,nLevel+1);
02487                         *pS << sal_uInt8(END); //line
02488                 }
02489                 else
02490                         *pS << sal_uInt8(LINE|0x10);
02491         if (NULL != (pTemp = pNode->GetSubNode(RSUP+1)))
02492                 {
02493                         *pS << sal_uInt8(LINE); //line
02494                         HandleNodes(pTemp,nLevel+1);
02495                         *pS << sal_uInt8(END); //line
02496                 }
02497                 else
02498                         *pS << sal_uInt8(LINE|0x10);
02499         *pS << sal_uInt8(END); //line
02500         }
02501 
02502         //After subscript mathtype will keep the size of
02503         //normal text at the subscript size, sigh.
02504         *pS << sal_uInt8(0x0A);
02505 }
02506 
02507 
02508 void MathType::HandleFractions(SmNode *pNode,int nLevel)
02509 {
02510     //USHORT  nSize = pNode->GetNumSubNodes();
02511         SmNode *pTemp;
02512         *pS << sal_uInt8(TMPL); //Template
02513         *pS << sal_uInt8(0x0E); //selector
02514         *pS << sal_uInt8(0x00); //variation
02515         *pS << sal_uInt8(0x00); //options
02516 
02517         *pS << sal_uInt8(0x0A);
02518         *pS << sal_uInt8(LINE); //line
02519     if (NULL != (pTemp = pNode->GetSubNode(0)))
02520                 HandleNodes(pTemp,nLevel+1);
02521         *pS << sal_uInt8(END);
02522 
02523         *pS << sal_uInt8(0x0A);
02524         *pS << sal_uInt8(LINE); //line
02525     if (NULL != (pTemp = pNode->GetSubNode(2)))
02526                 HandleNodes(pTemp,nLevel+1);
02527         *pS << sal_uInt8(END);
02528 
02529         *pS << sal_uInt8(END);
02530 }
02531 
02532 
02533 void MathType::HandleBrace(SmNode *pNode,int nLevel)
02534 {
02535     //USHORT  nSize = pNode->GetNumSubNodes();
02536         SmNode *pTemp;
02537         SmNode *pLeft=pNode->GetSubNode(0);
02538         SmNode *pRight=pNode->GetSubNode(2);
02539 
02540         *pS << sal_uInt8(TMPL); //Template
02541     bIsReInterpBrace=0;
02542         sal_uInt8 nBSpec=0x10;
02543         ULONG nLoc = pS->Tell();
02544         if (pLeft)
02545         {
02546                 switch (pLeft->GetToken().eType)
02547                 {
02548                         case TLANGLE:
02549                                 *pS << sal_uInt8(tmANGLE); //selector
02550                                 *pS << sal_uInt8(0x00); //variation
02551                                 *pS << sal_uInt8(0x00); //options
02552                                 break;
02553                         case TLBRACE:
02554                                 *pS << sal_uInt8(tmBRACE); //selector
02555                                 *pS << sal_uInt8(0x00); //variation
02556                                 *pS << sal_uInt8(0x00); //options
02557                                 nBSpec+=3;
02558                                 break;
02559                         case TLBRACKET:
02560                                 *pS << sal_uInt8(tmBRACK); //selector
02561                                 *pS << sal_uInt8(0x00); //variation
02562                                 *pS << sal_uInt8(0x00); //options
02563                                 nBSpec+=3;
02564                                 break;
02565             case TLFLOOR:
02566                 *pS << sal_uInt8(tmFLOOR); //selector
02567                                 *pS << sal_uInt8(0x00); //variation
02568                                 *pS << sal_uInt8(0x00); //options
02569                 break;
02570                         case TLLINE:
02571                                 *pS << sal_uInt8(tmBAR); //selector
02572                                 *pS << sal_uInt8(0x00); //variation
02573                                 *pS << sal_uInt8(0x00); //options
02574                                 nBSpec+=3;
02575                                 break;
02576                         case TLDLINE:
02577                                 *pS << sal_uInt8(tmDBAR); //selector
02578                                 *pS << sal_uInt8(0x00); //variation
02579                                 *pS << sal_uInt8(0x00); //options
02580                                 break;
02581                         default:
02582                                 *pS << sal_uInt8(tmPAREN); //selector
02583                                 *pS << sal_uInt8(0x00); //variation
02584                                 *pS << sal_uInt8(0x00); //options
02585                                 nBSpec+=3;
02586                                 break;
02587                 }
02588         }
02589 
02590     if (NULL != (pTemp = pNode->GetSubNode(1)))
02591         {
02592                 *pS << sal_uInt8(LINE); //line
02593                 HandleNodes(pTemp,nLevel+1);
02594                 *pS << sal_uInt8(END); //options
02595         }
02596         nSpec=nBSpec;
02597         if (pLeft)
02598                 HandleNodes(pLeft,nLevel+1);
02599     if (bIsReInterpBrace)
02600         {
02601                 ULONG nLoc2 = pS->Tell();
02602                 pS->Seek(nLoc);
02603                 *pS << sal_uInt8(0x2D);
02604                 pS->Seek(nLoc2);
02605                 *pS << sal_uInt8(CHAR);
02606                 *pS << sal_uInt8(0x96);
02607                 *pS << sal_uInt16(0xEC07);
02608         bIsReInterpBrace=0;
02609         }
02610         if (pRight)
02611                 HandleNodes(pRight,nLevel+1);
02612         nSpec=0x0;
02613         *pS << sal_uInt8(END);
02614 }
02615 
02616 
02617 void MathType::HandleVerticalBrace(SmNode *pNode,int nLevel)
02618 {
02619         SmNode *pTemp;
02620         *pS << sal_uInt8(TMPL); //Template
02621         if (pNode->GetToken().eType == TUNDERBRACE)
02622                 *pS << sal_uInt8(tmLHBRACE); //selector
02623         else
02624                 *pS << sal_uInt8(tmUHBRACE); //selector
02625         *pS << sal_uInt8(0x01); //variation
02626         *pS << sal_uInt8(0x00); //options
02627 
02628     if (NULL != (pTemp = pNode->GetSubNode(0)))
02629         {
02630                 *pS << sal_uInt8(LINE); //line
02631                 HandleNodes(pTemp,nLevel+1);
02632                 *pS << sal_uInt8(END); //options
02633         }
02634 
02635     if (NULL != (pTemp = pNode->GetSubNode(2)))
02636         {
02637                 *pS << sal_uInt8(LINE); //line
02638                 HandleNodes(pTemp,nLevel+1);
02639                 *pS << sal_uInt8(END); //options
02640         }
02641         *pS << sal_uInt8(END);
02642 }
02643 
02644 void MathType::HandleOperator(SmNode *pNode,int nLevel)
02645 {
02646     //USHORT  nSize = pNode->GetNumSubNodes();
02647 
02648         if (HandleLim(pNode,nLevel))
02649                 return;
02650 
02651         ULONG nPos;
02652         sal_uInt8 nVariation;
02653 
02654         switch (pNode->GetToken().eType)
02655         {
02656                 case TIINT:
02657                 case TIIINT:
02658                 case TLINT:
02659                 case TLLINT:
02660                 case TLLLINT:
02661                         nVariation=HandleCScript(pNode->GetSubNode(0),
02662                                 pNode->GetSubNode(1),nLevel,&nPos,0);
02663                         break;
02664                 default:
02665                         nVariation=HandleCScript(pNode->GetSubNode(0),
02666                                 pNode->GetSubNode(1),nLevel,&nPos);
02667                         break;
02668         }
02669 
02670         sal_uInt8 nOldVariation=nVariation;
02671         sal_uInt8 nIntVariation=nVariation;
02672 
02673         ULONG nPos2=0;
02674         if (nVariation != 0xff)
02675         {
02676                 nPos2 = pS->Tell();
02677                 pS->Seek(nPos);
02678                 if (nVariation == 2)
02679                 {
02680                         nIntVariation=0;
02681                         nVariation = 1;
02682                 }
02683                 else if (nVariation == 0)
02684                         nVariation = 1;
02685                 else if (nVariation == 1)
02686                         nVariation = 0;
02687         }
02688         else
02689         {
02690                 nVariation = 2;
02691                 nIntVariation=0;
02692         }
02693         *pS << sal_uInt8(TMPL);
02694         switch(pNode->GetToken().eType)
02695         {
02696         case TINT:
02697                 if (nOldVariation != 0xff)
02698                         *pS << sal_uInt8(0x18); //selector
02699                 else
02700                         *pS << sal_uInt8(0x15); //selector
02701                 *pS << nIntVariation; //variation
02702                 break;
02703         case TIINT:
02704                 if (nOldVariation != 0xff)
02705                 {
02706                         *pS << sal_uInt8(0x19);
02707                         *pS << sal_uInt8(0x01);
02708                 }
02709                 else
02710                 {
02711                         *pS << sal_uInt8(0x16);
02712                         *pS << sal_uInt8(0x00);
02713                 }
02714                 break;
02715         case TIIINT:
02716                 if (nOldVariation != 0xff)
02717                 {
02718                         *pS << sal_uInt8(0x1a);
02719                         *pS << sal_uInt8(0x01);
02720                 }
02721                 else
02722                 {
02723                         *pS << sal_uInt8(0x17);
02724                         *pS << sal_uInt8(0x00);
02725                 }
02726                 break;
02727         case TLINT:
02728                 if (nOldVariation != 0xff)
02729                 {
02730                         *pS << sal_uInt8(0x18);
02731                         *pS << sal_uInt8(0x02);
02732                 }
02733                 else
02734                 {
02735                         *pS << sal_uInt8(0x15);
02736                         *pS << sal_uInt8(0x03);
02737                 }
02738                 break;
02739         case TLLINT:
02740                 if (nOldVariation != 0xff)
02741                 {
02742                         *pS << sal_uInt8(0x19);
02743                         *pS << sal_uInt8(0x00);
02744                 }
02745                 else
02746                 {
02747                         *pS << sal_uInt8(0x16);
02748                         *pS << sal_uInt8(0x02);
02749                 }
02750                 break;
02751         case TLLLINT:
02752                 if (nOldVariation != 0xff)
02753                 {
02754                         *pS << sal_uInt8(0x1a);
02755                         *pS << sal_uInt8(0x00);
02756                 }
02757                 else
02758                 {
02759                         *pS << sal_uInt8(0x17);
02760                         *pS << sal_uInt8(0x02);
02761                 }
02762                 break;
02763         case TSUM:
02764         default:
02765                 *pS << sal_uInt8(0x1d);
02766                 *pS << nVariation;
02767                 break;
02768         case TPROD:
02769                 *pS << sal_uInt8(0x1f);
02770                 *pS << nVariation;
02771                 break;
02772         case TCOPROD:
02773                 *pS << sal_uInt8(0x21);
02774                 *pS << nVariation;
02775                 break;
02776         }
02777         *pS << sal_uInt8(0x00); //options
02778 
02779         if (nPos2)
02780                 pS->Seek(nPos2);
02781         else
02782         {
02783                 *pS << sal_uInt8(LINE); //line
02784                 HandleNodes(pNode->GetSubNode(1),nLevel+1);
02785                 *pS << sal_uInt8(END); //line
02786                 *pS << sal_uInt8(LINE|0x10);
02787                 *pS << sal_uInt8(LINE|0x10);
02788         }
02789 
02790 
02791         *pS << sal_uInt8(0x0D);
02792         switch(pNode->GetToken().eType)
02793         {
02794         case TSUM:
02795         default:
02796                 *pS << sal_uInt8(CHAR);
02797                 *pS << sal_uInt8(0x86);
02798                 *pS << sal_uInt16(0x2211);
02799                 break;
02800         case TPROD:
02801                 *pS << sal_uInt8(CHAR);
02802                 *pS << sal_uInt8(0x86);
02803                 *pS << sal_uInt16(0x220F);
02804                 break;
02805         case TCOPROD:
02806                 *pS << sal_uInt8(CHAR);
02807                 *pS << sal_uInt8(0x8B);
02808                 *pS << sal_uInt16(0x2210);
02809                 break;
02810         case TIIINT:
02811         case TLLLINT:
02812                 *pS << sal_uInt8(CHAR);
02813                 *pS << sal_uInt8(0x86);
02814                 *pS << sal_uInt16(0x222B);
02815         case TIINT:
02816         case TLLINT:
02817                 *pS << sal_uInt8(CHAR);
02818                 *pS << sal_uInt8(0x86);
02819                 *pS << sal_uInt16(0x222B);
02820         case TINT:
02821         case TLINT:
02822                 *pS << sal_uInt8(CHAR);
02823                 *pS << sal_uInt8(0x86);
02824                 *pS << sal_uInt16(0x222B);
02825                 break;
02826         }
02827         *pS << sal_uInt8(END);
02828         *pS << sal_uInt8(0x0A);
02829 }
02830 
02831 
02832 int MathType::HandlePile(int &rSetAlign,int nLevel,sal_uInt8 nSelector,
02833         sal_uInt8 nVariation)
02834 {
02835         *pS >> nHAlign;
02836         *pS >> nVAlign;
02837 
02838         HandleAlign(nHAlign,nVAlign,rSetAlign);
02839 
02840         APPEND(rRet," stack {\n");
02841         int nRet = HandleRecords(nLevel+1,nSelector,nVariation,-1,-1);
02842         rRet.Erase(rRet.Len()-3,2);
02843         APPEND(rRet,"} ");
02844 
02845         while (rSetAlign)
02846         {
02847                 APPEND(rRet,"} ");
02848                 rSetAlign--;
02849         }
02850         return nRet;
02851 }
02852 
02853 int MathType::HandleMatrix(int nLevel,sal_uInt8 nSelector,
02854         sal_uInt8 nVariation)
02855 {
02856         sal_uInt8 nH_just,nV_just,nRows,nCols;
02857         *pS >> nVAlign;
02858         *pS >> nH_just;
02859         *pS >> nV_just;
02860         *pS >> nRows;
02861         *pS >> nCols;
02862         int nBytes = ((nRows+1)*2)/8;
02863         if (((nRows+1)*2)%8)
02864                 nBytes++;
02865         pS->SeekRel(nBytes);
02866         nBytes = ((nCols+1)*2)/8;
02867         if (((nCols+1)*2)%8)
02868                 nBytes++;
02869         pS->SeekRel(nBytes);
02870         APPEND(rRet," matrix {\n");
02871         int nRet = HandleRecords(nLevel+1,nSelector,nVariation,nRows,nCols);
02872 
02873     xub_StrLen nI = rRet.SearchBackward('#');
02874     if ((nI != STRING_NOTFOUND) && (nI > 0))
02875         if (rRet.GetChar(nI-1) != '#')  //missing column
02876             APPEND(rRet,"{}");
02877 
02878         APPEND(rRet,"\n} ");
02879         return nRet;
02880 }
02881 
02882 int MathType::HandleTemplate(int nLevel,sal_uInt8 &rSelector,
02883         sal_uInt8 &rVariation, xub_StrLen &rLastTemplateBracket)
02884 {
02885         sal_uInt8 nOption; //This appears utterly unused
02886         *pS >> rSelector;
02887         *pS >> rVariation;
02888         *pS >> nOption;
02889         DBG_ASSERT(rSelector < 48,"Selector out of range")
02890         if ((rSelector >= 21) && (rSelector <=26))
02891         {
02892                 DBG_ASSERT(nOption < 2,"Option out of range");
02893         }
02894     else if (/*(rSelector >= 0) &&*/ (rSelector <=12))
02895         {
02896                 DBG_ASSERT(nOption < 3,"Option out of range");
02897         }
02898 
02899     //For the (broken) case where one subscript template ends, and there is
02900     //another one after it, mathtype handles it as if the second one was
02901     //inside the first one and renders it as sub of sub
02902     BOOL bRemove=FALSE;
02903     if ( (rSelector == 0xf) && (rLastTemplateBracket != STRING_NOTFOUND) )
02904     {
02905         bRemove=TRUE;
02906         for (xub_StrLen nI = rLastTemplateBracket+1; nI < rRet.Len(); nI++ )
02907             if (rRet.GetChar(nI) != ' ')
02908             {
02909                 bRemove=FALSE;
02910                 break;
02911             }
02912     }
02913 
02914         //suborderlist
02915     int nRet = HandleRecords(nLevel+1,rSelector,rVariation);
02916 
02917     if (bRemove)
02918     {
02919         rRet.Erase(rLastTemplateBracket,1);
02920         APPEND(rRet,"} ");
02921         rLastTemplateBracket = STRING_NOTFOUND;
02922     }
02923     if (rSelector == 0xf)
02924         rLastTemplateBracket = rRet.SearchBackward('}');
02925     else
02926         rLastTemplateBracket = STRING_NOTFOUND;
02927 
02928     rSelector = sal::static_int_cast< sal_uInt8 >(-1);
02929         return nRet;
02930 }
02931 
02932 void MathType::HandleEmblishments()
02933 {
02934         sal_uInt8 nEmbel;
02935         do
02936         {
02937                 *pS >> nEmbel;
02938                 switch (nEmbel)
02939                 {
02940                 case 0x02:
02941                         APPEND(rRet," dot ");
02942                         break;
02943                 case 0x03:
02944                         APPEND(rRet," ddot ");
02945                         break;
02946                 case 0x04:
02947                         APPEND(rRet," dddot ");
02948                         break;
02949                 case 0x05:
02950                         if (nPostSup == 0)
02951                         {
02952                                 APPEND(sPost," sup {}");
02953                                 nPostSup = sPost.Len();
02954                         }
02955                         sPost.InsertAscii(" ' ",nPostSup-1);
02956                         nPostSup += 3;
02957                         break;
02958                 case 0x06:
02959                         if (nPostSup == 0)
02960                         {
02961                                 APPEND(sPost," sup {}");
02962                                 nPostSup = sPost.Len();
02963                         }
02964                         sPost.InsertAscii(" '' ",nPostSup-1);
02965                         nPostSup += 4;
02966                         break;
02967                 case 0x07:
02968                         if (nPostlSup == 0)
02969                         {
02970                                 APPEND(sPost," lsup {}");
02971                                 nPostlSup = sPost.Len();
02972                         }
02973                         sPost.InsertAscii(" ' ",nPostlSup-1);
02974                         nPostlSup += 3;
02975                         break;
02976                 case 0x08:
02977                         APPEND(rRet," tilde ");
02978                         break;
02979                 case 0x09:
02980                         APPEND(rRet," hat ");
02981                         break;
02982                 case 0x0b:
02983                         APPEND(rRet," vec ");
02984                         break;
02985                 case 0x10:
02986                         APPEND(rRet," overstrike ");
02987                         break;
02988                 case 0x11:
02989                         APPEND(rRet," bar ");
02990                         break;
02991                 case 0x12:
02992                         if (nPostSup == 0)
02993                         {
02994                                 APPEND(sPost," sup {}");
02995                                 nPostSup = sPost.Len();
02996                         }
02997                         sPost.InsertAscii(" ''' ",nPostSup-1);
02998                         nPostSup += 5;
02999                         break;
03000                 case 0x14:
03001                         APPEND(rRet," breve ");
03002                         break;
03003                 default:
03004                         DBG_ASSERT(nEmbel < 21,"Embel out of range")
03005                         break;
03006                 }
03007         if (nVersion < 3)
03008             break;
03009         }while (nEmbel);
03010 }
03011 
03012 void MathType::HandleSetSize()
03013 {
03014         sal_uInt8 nTemp;
03015         *pS >> nTemp;
03016         switch (nTemp)
03017         {
03018                 case 101:
03019                         *pS >> nLSize;
03020                         nLSize = -nLSize;
03021                         break;
03022                 case 100:
03023                         *pS >> nTemp;
03024                         nLSize = nTemp;
03025                         *pS >> nDSize;
03026                         break;
03027                 default:
03028                         nLSize = nTemp;
03029                         *pS >> nTemp;
03030                         nDSize = nTemp-128;
03031                         break;
03032         }
03033 }
03034 
03035 int MathType::HandleChar(xub_StrLen &rTextStart,int &rSetSize,int nLevel,
03036         sal_uInt8 nTag,sal_uInt8 nSelector,sal_uInt8 nVariation, sal_Bool bSilent)
03037 {
03038         sal_Unicode nChar;
03039         int nRet=1;
03040 
03041         if (xfAUTO(nTag))
03042         {
03043         //This is a candidate for function recognition, whatever
03044         //that is!
03045         }
03046 
03047         sal_uInt8 nOldTypeFace = nTypeFace;
03048         *pS >> nTypeFace;
03049         if (nVersion < 3)
03050         {
03051                 sal_uInt8 nChar8;
03052                 *pS >> nChar8;
03053                 nChar = nChar8;
03054         }
03055         else
03056                 *pS >> nChar;
03057 
03058     /*
03059     ##912##
03060     bad character, old mathtype < 3 has these
03061     */
03062     if (nChar < 0x20)
03063         return nRet;
03064 
03065         if (xfEMBELL(nTag))
03066         {
03067                 //A bit tricky, the character emblishments for
03068                 //mathtype can all be listed after eachother, in
03069                 //starmath some must go before the character and some
03070                 //must go after. In addition some of the emblishments
03071                 //may repeated and in starmath some of these groups
03072                 //must be gathered together. sPost is the portion that
03073                 //follows the char and nPostSup and nPostlSup are the
03074                 //indexes at which this class of emblishment is
03075                 //collated together
03076                 sPost.Erase();
03077                 nPostSup = nPostlSup = 0;
03078                 int nOriglen=rRet.Len()-rTextStart;
03079         APPEND(rRet," {");  // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n"
03080                 if ((!bSilent) && ((nOriglen) > 1))
03081                         rRet += '\"';
03082                 nRet = HandleRecords(nLevel+1,nSelector,nVariation);
03083                 if (!bSilent)
03084                 {
03085                         if (nOriglen > 1)
03086                         {
03087                                 String aStr;
03088                                 TypeFaceToString(aStr,nOldTypeFace);
03089                                 aStr += '\"';
03090                                 rRet.Insert(aStr,rTextStart);
03091 
03092                                 aStr.Erase();
03093                                 TypeFaceToString(aStr,nTypeFace);
03094                                 rRet.Append(aStr);
03095                                 rRet += '{';
03096                         }
03097                         else
03098                                 APPEND(rRet," {");
03099             rTextStart = rRet.Len();
03100                 }
03101         }
03102 
03103         if (!bSilent)
03104         {
03105         xub_StrLen nOldLen = rRet.Len();
03106                 //nLastSize = nCurSize;
03107                 if (
03108                         HandleSize(nLSize,nDSize,rSetSize) ||
03109                         (nOldTypeFace != nTypeFace)
03110                    )
03111                 {
03112                         if ((nOldLen - rTextStart) > 1)
03113                         {
03114                                 rRet.InsertAscii("\"",nOldLen);
03115                                 String aStr;
03116                                 TypeFaceToString(aStr,nOldTypeFace);
03117                                 aStr += '\"';
03118                                 rRet.Insert(aStr,rTextStart);
03119                         }
03120                         rTextStart = rRet.Len();
03121                 }
03122                 nOldLen = rRet.Len();
03123                 if (!LookupChar(nChar,rRet,nVersion,nTypeFace))
03124                 {
03125                         if (nOldLen - rTextStart > 1)
03126                         {
03127                                 rRet.InsertAscii("\"",nOldLen);
03128                                 String aStr;
03129                                 TypeFaceToString(aStr,nOldTypeFace);
03130                                 aStr += '\"';
03131                                 rRet.Insert(aStr,rTextStart);
03132                         }
03133                         rTextStart = rRet.Len();
03134                 }
03135         lcl_PrependDummyTerm(rRet, rTextStart);
03136         }
03137 
03138         if ((xfEMBELL(nTag)) && (!bSilent))
03139         {
03140         rRet += '}';    // #i24340# make what would be "vec {A}_n" become "{vec {A}}_n"
03141                 rRet += '}';
03142                 rRet += sPost;
03143                 rTextStart = rRet.Len();
03144         }
03145         return nRet;
03146 }
03147 
03148 sal_Bool MathType::HandleLim(SmNode *pNode,int nLevel)
03149 {
03150         sal_Bool bRet=0;
03151         //Special case for the "lim" option in StarMath
03152         if ((pNode->GetToken().eType == TLIM)
03153                 || (pNode->GetToken().eType == TLIMSUP)
03154                 || (pNode->GetToken().eType == TLIMINF)
03155                 )
03156         {
03157                 if (pNode->GetSubNode(1))
03158                 {
03159                         sal_uInt8 nVariation2=HandleCScript(pNode->GetSubNode(0),NULL,
03160                                 nLevel);
03161 
03162                         *pS << sal_uInt8(0x0A);
03163                         *pS << sal_uInt8(LINE); //line
03164                         *pS << sal_uInt8(CHAR|0x10);
03165                         *pS << sal_uInt8(0x82);
03166                         *pS << sal_uInt16('l');
03167                         *pS << sal_uInt8(CHAR|0x10);
03168                         *pS << sal_uInt8(0x82);
03169                         *pS << sal_uInt16('i');
03170                         *pS << sal_uInt8(CHAR|0x10);
03171                         *pS << sal_uInt8(0x82);
03172                         *pS << sal_uInt16('m');
03173 
03174                         if (pNode->GetToken().eType == TLIMSUP)
03175                         {
03176                                 *pS << sal_uInt8(CHAR); //some space
03177                                 *pS << sal_uInt8(0x98);
03178                                 *pS << sal_uInt16(0xEB04);
03179 
03180                                 *pS << sal_uInt8(CHAR|0x10);
03181                                 *pS << sal_uInt8(0x82);
03182                                 *pS << sal_uInt16('s');
03183                                 *pS << sal_uInt8(CHAR|0x10);
03184                                 *pS << sal_uInt8(0x82);
03185                                 *pS << sal_uInt16('u');
03186                                 *pS << sal_uInt8(CHAR|0x10);
03187                                 *pS << sal_uInt8(0x82);
03188                                 *pS << sal_uInt16('p');
03189                         }
03190                         else if (pNode->GetToken().eType == TLIMINF)
03191                         {
03192                                 *pS << sal_uInt8(CHAR); //some space
03193                                 *pS << sal_uInt8(0x98);
03194                                 *pS << sal_uInt16(0xEB04);
03195 
03196                                 *pS << sal_uInt8(CHAR|0x10);
03197                                 *pS << sal_uInt8(0x82);
03198                                 *pS << sal_uInt16('i');
03199                                 *pS << sal_uInt8(CHAR|0x10);
03200                                 *pS << sal_uInt8(0x82);
03201                                 *pS << sal_uInt16('n');
03202                                 *pS << sal_uInt8(CHAR|0x10);
03203                                 *pS << sal_uInt8(0x82);
03204                                 *pS << sal_uInt16('f');
03205                         }
03206 
03207 
03208                         *pS << sal_uInt8(CHAR); //some space
03209                         *pS << sal_uInt8(0x98);
03210                         *pS << sal_uInt16(0xEB04);
03211 
03212                         if (nVariation2 != 0xff)
03213                         {
03214                                 *pS << sal_uInt8(END);
03215                                 *pS << sal_uInt8(END);
03216                         }
03217                         HandleNodes(pNode->GetSubNode(1),nLevel+1);
03218                         //*pS << sal_uInt8(END); //options
03219                         bRet = 1;
03220                 }
03221         }
03222         return bRet;
03223 }
03224 
03225 void MathType::HandleMAlign(SmNode *pNode,int nLevel)
03226 {
03227         sal_uInt8 nPushedHAlign=nHAlign;
03228         switch(pNode->GetToken().eType)
03229         {
03230                 case TALIGNC:
03231                         nHAlign=2;
03232                         break;
03233                 case TALIGNR:
03234                         nHAlign=3;
03235                         break;
03236                 default:
03237                         nHAlign=1;
03238                         break;
03239         }
03240         USHORT  nSize = pNode->GetNumSubNodes();
03241         for (USHORT i = 0; i < nSize; i++)
03242                 if (SmNode *pTemp = pNode->GetSubNode(i))
03243                         HandleNodes(pTemp,nLevel+1);
03244         nHAlign=nPushedHAlign;
03245 }
03246 
03247 void MathType::HandleMath(SmNode *pNode, int /*nLevel*/)
03248 {
03249         if (pNode->GetToken().eType == TMLINE)
03250         {
03251                 *pS << sal_uInt8(END);
03252                 *pS << sal_uInt8(LINE);
03253         bIsReInterpBrace=1;
03254                 return;
03255         }
03256         SmMathSymbolNode *pTemp=(SmMathSymbolNode *)pNode;
03257     for(xub_StrLen i=0;i<pTemp->GetText().Len();i++)
03258         {
03259                 sal_Unicode nArse = Convert(pTemp->GetText().GetChar(i));
03260         if ((nArse == 0x2224) || (nArse == 0x2288) || (nArse == 0x2285) ||
03261                         (nArse == 0x2289))
03262                 {
03263                         *pS << sal_uInt8(CHAR|0x20);
03264                 }
03265         else if ((nPendingAttributes) &&
03266                 (i == ((pTemp->GetText().Len()+1)/2)-1))
03267             {
03268                 *pS << sal_uInt8(0x22);
03269             }
03270                 else
03271                         *pS << sal_uInt8(CHAR); //char without formula recognition
03272                 //The typeface seems to be MTEXTRA for unicode characters,
03273                 //though how to determine when mathtype chooses one over
03274                 //the other is unknown. This should do the trick
03275                 //nevertheless.
03276                 sal_uInt8 nBias;
03277                 if ( (nArse == 0x2213) || (nArse == 0x2218) ||
03278                         (nArse == 0x210F) || (
03279                                 (nArse >= 0x22EE) && (nArse <= 0x22FF)
03280                         ))
03281                 {
03282                         nBias = 0xB; //typeface
03283                 }
03284                 else if ((nArse > 0x2000) || (nArse == 0x00D7))
03285                         nBias = 0x6; //typeface
03286                 else if (nArse == 0x3d1)
03287                         nBias = 0x4;
03288                 else if ((nArse > 0xFF) && ((nArse < 0x393) || (nArse > 0x3c9)))
03289                         nBias = 0xB; //typeface
03290                 else if ((nArse == 0x2F) || (nArse == 0x2225))
03291                         nBias = 0x2; //typeface
03292                 else
03293                         nBias = 0x3; //typeface
03294 
03295                 *pS << sal_uInt8(nSpec+nBias+128); //typeface
03296 
03297                 if (nArse == 0x2224)
03298                 {
03299                         *pS << sal_uInt16(0x7C);
03300                         *pS << sal_uInt8(EMBEL);
03301                         *pS << sal_uInt8(0x0A);
03302                         *pS << sal_uInt8(END); //end embel
03303                         *pS << sal_uInt8(END); //end embel
03304                 }
03305                 else if (nArse == 0x2225)
03306                         *pS << sal_uInt16(0xEC09);
03307                 else if (nArse == 0xE421)
03308                         *pS << sal_uInt16(0x2265);
03309         else if (nArse == 0x230A)
03310                         *pS << sal_uInt16(0xF8F0);
03311                 else if (nArse == 0x230B)
03312                         *pS << sal_uInt16(0xF8FB);
03313                 else if (nArse == 0xE425)
03314                         *pS << sal_uInt16(0x2264);
03315                 else if (nArse == 0x226A)
03316                 {
03317                         *pS << sal_uInt16(0x3C);
03318                         *pS << sal_uInt8(CHAR);
03319                         *pS << sal_uInt8(0x98);
03320                         *pS << sal_uInt16(0xEB01);
03321                         *pS << sal_uInt8(CHAR);
03322                         *pS << sal_uInt8(0x86);
03323                         *pS << sal_uInt16(0x3c);
03324                 }
03325                 else if (nArse == 0x2288)
03326                 {
03327                         *pS << sal_uInt16(0x2286);
03328                         *pS << sal_uInt8(EMBEL);
03329                         *pS << sal_uInt8(0x0A);
03330                         *pS << sal_uInt8(END); //end embel
03331                         *pS << sal_uInt8(END); //end embel
03332                 }
03333                 else if (nArse == 0x2289)
03334                 {
03335                         *pS << sal_uInt16(0x2287);
03336                         *pS << sal_uInt8(EMBEL);
03337                         *pS << sal_uInt8(0x0A);
03338                         *pS << sal_uInt8(END); //end embel
03339                         *pS << sal_uInt8(END); //end embel
03340                 }
03341                 else if (nArse == 0x2285)
03342                 {
03343                         *pS << sal_uInt16(0x2283);
03344                         *pS << sal_uInt8(EMBEL);
03345                         *pS << sal_uInt8(0x0A);
03346                         *pS << sal_uInt8(END); //end embel
03347                         *pS << sal_uInt8(END); //end embel
03348                 }
03349                 else
03350                         *pS << nArse;
03351         }
03352     nPendingAttributes = 0;
03353 }
03354 
03355 void MathType::HandleAttributes(SmNode *pNode,int nLevel)
03356 {
03357     int nOldPending = 0;
03358     //USHORT  nSize = pNode->GetNumSubNodes();
03359     SmNode *pTemp       = 0;
03360     SmTextNode *pIsText = 0;
03361 
03362         //SmTextNode *pTemp=(SmTextNode *)pNode;
03363         //for(int i=0;i<pTemp->GetText().Len();i++)
03364 
03365     if (NULL != (pTemp = pNode->GetSubNode(0)))
03366         {
03367                 pIsText = (SmTextNode *)pNode->GetSubNode(1);
03368 
03369                 switch (pTemp->GetToken().eType)
03370                 {
03371                 case TWIDEVEC:
03372                         //theres just no way we can now handle any character
03373                         //attributes (from mathtypes perspective) centered
03374                         //over an expression but above template attributes
03375                         //such as widevec and similiar constructs
03376                         //we have to drop them
03377                         nOldPending = StartTemplate(0x2f,0x01);
03378                         break;
03379                 case TCHECK: //Not Exportable
03380                 case TACUTE: //Not Exportable
03381                 case TGRAVE: //Not Exportable
03382                 case TCIRCLE: //Not Exportable
03383                 case TWIDETILDE: //Not Exportable
03384                 case TWIDEHAT: //Not Exportable
03385                         break;
03386                 case TUNDERLINE:
03387                         nOldPending = StartTemplate(0x10);
03388                         break;
03389                 case TOVERLINE: //If the next node is not text
03390                                                 //or text with more than one char
03391             if ((pIsText->GetToken().eType != TTEXT) ||
03392                                 (pIsText->GetText().Len() > 1))
03393                                 nOldPending = StartTemplate(0x11);
03394                         break;
03395                 default:
03396                         nPendingAttributes++;
03397                         break;
03398                 }
03399         }
03400 
03401         if (pIsText)
03402                 HandleNodes(pIsText,nLevel+1);
03403 
03404         switch (pTemp->GetToken().eType)
03405         {
03406                 case TWIDEVEC:
03407                 case TUNDERLINE:
03408                         EndTemplate(nOldPending);
03409                         break;
03410                 case TOVERLINE:
03411             if ((pIsText->GetToken().eType != TTEXT) ||
03412                                 (pIsText->GetText().Len() > 1))
03413                                 EndTemplate(nOldPending);
03414                         break;
03415                 default:
03416                         break;
03417         }
03418 
03419         //if there was no suitable place to put the attribute,
03420         //then we have to just give up on it
03421         if (nPendingAttributes)
03422                 nPendingAttributes--;
03423         else
03424         {
03425         if ((nInsertion != 0) && NULL != (pTemp = pNode->GetSubNode(0)))
03426                 {
03427                         ULONG nPos = pS->Tell();
03428                         nInsertion--;
03429                         pS->Seek(nInsertion);
03430                         switch(pTemp->GetToken().eType)
03431                         {
03432                         case TACUTE: //Not Exportable
03433                         case TGRAVE: //Not Exportable
03434                         case TCIRCLE: //Not Exportable
03435                                 break;
03436                         case TCDOT:
03437                                 *pS << sal_uInt8(2);
03438                                 break;
03439                         case TDDOT:
03440                                 *pS << sal_uInt8(3);
03441                                 break;
03442                         case TDDDOT:
03443                                 *pS << sal_uInt8(4);
03444                                 break;
03445                         case TTILDE:
03446                                 *pS << sal_uInt8(8);
03447                                 break;
03448                         case THAT:
03449                                 *pS << sal_uInt8(9);
03450                                 break;
03451                         case TVEC:
03452                                 *pS << sal_uInt8(11);
03453                                 break;
03454                         case TOVERSTRIKE:
03455                                 *pS << sal_uInt8(16);
03456                                 break;
03457                         case TOVERLINE:
03458                 if ((pIsText->GetToken().eType == TTEXT) &&
03459                                         (pIsText->GetText().Len() == 1))
03460                                         *pS << sal_uInt8(17);
03461                                 break;
03462                         case TBREVE:
03463                                 *pS << sal_uInt8(20);
03464                                 break;
03465                         case TWIDEVEC:
03466                         case TUNDERLINE:
03467                         case TWIDETILDE:
03468                         case TWIDEHAT:
03469                                 break;
03470                         case TBAR:
03471                                 *pS << sal_uInt8(17);
03472                                 break;
03473                         default:
03474                                 *pS << sal_uInt8(0x2);
03475                                 break;
03476                         }
03477                 pS->Seek(nPos);
03478                 }
03479         }
03480 }
03481 
03482 void MathType::HandleText(SmNode *pNode, int /*nLevel*/)
03483 {
03484         SmTextNode *pTemp=(SmTextNode *)pNode;
03485     for(xub_StrLen i=0;i<pTemp->GetText().Len();i++)
03486         {
03487                 if ((nPendingAttributes) &&
03488                         (i == ((pTemp->GetText().Len()+1)/2)-1))
03489                 {
03490                         *pS << sal_uInt8(0x22);         //char, with attributes right
03491                                                                 //after the character
03492                 }
03493                 else
03494             *pS << sal_uInt8(CHAR);
03495                         //*pS << sal_uInt8(CHAR|0x10); //char with formula recognition
03496 
03497 #if 1
03498                 sal_uInt8 nFace = 0x1;
03499                 if (pNode->GetFont().GetItalic() == ITALIC_NORMAL)
03500                         nFace = 0x3;
03501                 else if (pNode->GetFont().GetWeight() == WEIGHT_BOLD)
03502                         nFace = 0x7;
03503                 *pS << sal_uInt8(nFace+128); //typeface
03504 #else
03505                 if ((pTemp->GetText().GetChar(i) >= '0') &&
03506                         (pTemp->GetText().GetChar(i) <= '9'))
03507                         *pS << sal_uInt8(0x8+128); //typeface
03508                 else
03509                         *pS << sal_uInt8(0x3+128); //typeface
03510 #endif
03511         sal_uInt16 nChar = pTemp->GetText().GetChar(i);
03512                 *pS << Convert(nChar);
03513 
03514                 //Mathtype can only have these sort of character
03515                 //attributes on a single character, starmath can put them
03516                 //anywhere, when the entity involved is a text run this is
03517                 //a large effort to place the character attribute on the
03518                 //central mathtype character so that it does pretty much
03519                 //what the user probably has in mind. The attributes
03520                 //filled in here are dummy ones which are replaced in the
03521                 //ATTRIBUT handler if a suitable location for the
03522                 //attributes was found here. Unfortunately it is
03523                 //possible for starmath to place character attributes on
03524                 //entities which cannot occur in mathtype e.g. a Summation
03525                 //symbol so these attributes may be lost
03526                 if ((nPendingAttributes) &&
03527                         (i == ((pTemp->GetText().Len()+1)/2)-1))
03528                 {
03529                         *pS << sal_uInt8(EMBEL);
03530                         while (nPendingAttributes)
03531                         {
03532                                 *pS << sal_uInt8(2);
03533                                 //wedge the attributes in here and clear
03534                                 //the pending stack
03535                                 nPendingAttributes--;
03536                         }
03537                         nInsertion=pS->Tell();
03538                         *pS << sal_uInt8(END); //end embel
03539                         *pS << sal_uInt8(END); //end embel
03540                 }
03541         }
03542 }
03543 
03544 /* vi:set tabstop=4 shiftwidth=4 expandtab: */

Generated on Wed Feb 20 17:21:57 2008 for maths by  doxygen 1.5.1