1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_starmath.hxx" 30 31 32 #include <stdio.h> 33 34 #define SMDLL 1 35 36 #include <com/sun/star/i18n/UnicodeType.hpp> 37 #include <i18npool/lang.h> 38 #include <unotools/charclass.hxx> 39 #include <editeng/unolingu.hxx> 40 #include <unotools/syslocale.hxx> 41 #include "parse.hxx" 42 #ifndef _STARMATH_HRC 43 #include "starmath.hrc" 44 #endif 45 #ifndef _SMDLL_HXX 46 #include "smdll.hxx" 47 #endif 48 #include "smmod.hxx" 49 #include "config.hxx" 50 51 #include "node.hxx" 52 53 using namespace ::com::sun::star; 54 using namespace ::com::sun::star::i18n; 55 56 /////////////////////////////////////////////////////////////////////////// 57 58 static inline sal_Bool strnccmp(const String &u1, xub_StrLen nIdx, 59 const sal_Char *s2, xub_StrLen nLen) 60 { 61 return u1.EqualsIgnoreCaseAscii( s2, nIdx, nLen ); 62 } 63 64 static const sal_Unicode aDelimiterTable[] = 65 { 66 ' ', '\t', '\n', '\r', '+', '-', '*', '/', '=', '#', 67 '%', '\\', '"', '~', '`', '>', '<', '&', '|', '(', 68 ')', '{', '}', '[', ']', '^', '_', 69 '\0' // end of list symbol 70 }; 71 72 73 static inline sal_Bool IsDigit( sal_Unicode cChar ) 74 { 75 return '0' <= cChar && cChar <= '9'; 76 } 77 78 /////////////////////////////////////////////////////////////////////////// 79 80 SmToken::SmToken() : 81 eType (TUNKNOWN), 82 cMathChar ('\0') 83 { 84 nGroup = nCol = nRow = nLevel = 0; 85 } 86 87 /////////////////////////////////////////////////////////////////////////// 88 89 struct SmTokenTableEntry 90 { 91 const sal_Char* pIdent; 92 SmTokenType eType; 93 sal_Unicode cMathChar; 94 sal_uLong nGroup; 95 sal_uInt16 nLevel; 96 }; 97 98 static const SmTokenTableEntry aTokenTable[] = 99 { 100 // { "#", TPOUND, '\0', 0, 0 }, 101 // { "##", TDPOUND, '\0', 0, 0 }, 102 // { "&", TAND, MS_AND, TGPRODUCT, 0 }, 103 // { "(", TLPARENT, MS_LPARENT, TGLBRACES, 5 }, //! 5 to continue expression 104 // { ")", TRPARENT, MS_RPARENT, TGRBRACES, 0 }, //! 0 to terminate expression 105 // { "*", TMULTIPLY, MS_MULTIPLY, TGPRODUCT, 0 }, 106 // { "+", TPLUS, MS_PLUS, TGUNOPER | TGSUM, 5 }, 107 // { "+-", TPLUSMINUS, MS_PLUSMINUS, TGUNOPER | TGSUM, 5 }, 108 // { "-", TMINUS, MS_MINUS, TGUNOPER | TGSUM, 5 }, 109 // { "-+", TMINUSPLUS, MS_MINUSPLUS, TGUNOPER | TGSUM, 5 }, 110 // { ".", TPOINT, '\0', 0, 0 }, 111 // { "/", TDIVIDEBY, MS_SLASH, TGPRODUCT, 0 }, 112 // { "<", TLT, MS_LT, TGRELATION, 0 }, 113 // { "<<", TLL, MS_LL, TGRELATION, 0 }, 114 // { "<=", TLE, MS_LE, TGRELATION, 0 }, 115 // { "<>", TNEQ, MS_NEQ, TGRELATION, 0}, 116 // { "<?>", TPLACE, MS_PLACE, 0, 5 }, 117 // { "=", TASSIGN, MS_ASSIGN, TGRELATION, 0}, 118 // { ">", TGT, MS_GT, TGRELATION, 0 }, 119 // { ">=", TGE, MS_GE, TGRELATION, 0 }, 120 // { ">>", TGG, MS_GG, TGRELATION, 0 }, 121 { "Im" , TIM, MS_IM, TGSTANDALONE, 5 }, 122 { "MZ23", TDEBUG, '\0', TGATTRIBUT, 0 }, 123 { "Re" , TRE, MS_RE, TGSTANDALONE, 5 }, 124 { "abs", TABS, '\0', TGUNOPER, 13 }, 125 { "arcosh", TACOSH, '\0', TGFUNCTION, 5 }, 126 { "arcoth", TACOTH, '\0', TGFUNCTION, 5 }, 127 { "acute", TACUTE, MS_ACUTE, TGATTRIBUT, 5 }, 128 { "aleph" , TALEPH, MS_ALEPH, TGSTANDALONE, 5 }, 129 { "alignb", TALIGNC, '\0', TGALIGN | TGDISCARDED, 0}, 130 { "alignc", TALIGNC, '\0', TGALIGN, 0}, 131 { "alignl", TALIGNL, '\0', TGALIGN, 0}, 132 { "alignm", TALIGNC, '\0', TGALIGN | TGDISCARDED, 0}, 133 { "alignr", TALIGNR, '\0', TGALIGN, 0}, 134 { "alignt", TALIGNC, '\0', TGALIGN | TGDISCARDED, 0}, 135 { "and", TAND, MS_AND, TGPRODUCT, 0}, 136 { "approx", TAPPROX, MS_APPROX, TGRELATION, 0}, 137 { "arccos", TACOS, '\0', TGFUNCTION, 5}, 138 { "arccot", TACOT, '\0', TGFUNCTION, 5}, 139 { "arcsin", TASIN, '\0', TGFUNCTION, 5}, 140 { "arctan", TATAN, '\0', TGFUNCTION, 5}, 141 { "arsinh", TASINH, '\0', TGFUNCTION, 5}, 142 { "artanh", TATANH, '\0', TGFUNCTION, 5}, 143 { "backepsilon" , TBACKEPSILON, MS_BACKEPSILON, TGSTANDALONE, 5}, 144 { "bar", TBAR, MS_BAR, TGATTRIBUT, 5}, 145 { "binom", TBINOM, '\0', 0, 5 }, 146 { "black", TBLACK, '\0', TGCOLOR, 0}, 147 { "blue", TBLUE, '\0', TGCOLOR, 0}, 148 { "bold", TBOLD, '\0', TGFONTATTR, 5}, 149 { "boper", TBOPER, '\0', TGPRODUCT, 0}, 150 { "breve", TBREVE, MS_BREVE, TGATTRIBUT, 5}, 151 { "bslash", TBACKSLASH, MS_BACKSLASH, TGPRODUCT, 0 }, 152 { "cdot", TCDOT, MS_CDOT, TGPRODUCT, 0}, 153 { "check", TCHECK, MS_CHECK, TGATTRIBUT, 5}, 154 { "circ" , TCIRC, MS_CIRC, TGSTANDALONE, 5}, 155 { "circle", TCIRCLE, MS_CIRCLE, TGATTRIBUT, 5}, 156 { "color", TCOLOR, '\0', TGFONTATTR, 5}, 157 { "coprod", TCOPROD, MS_COPROD, TGOPER, 5}, 158 { "cos", TCOS, '\0', TGFUNCTION, 5}, 159 { "cosh", TCOSH, '\0', TGFUNCTION, 5}, 160 { "cot", TCOT, '\0', TGFUNCTION, 5}, 161 { "coth", TCOTH, '\0', TGFUNCTION, 5}, 162 { "csub", TCSUB, '\0', TGPOWER, 0}, 163 { "csup", TCSUP, '\0', TGPOWER, 0}, 164 { "cyan", TCYAN, '\0', TGCOLOR, 0}, 165 { "dddot", TDDDOT, MS_DDDOT, TGATTRIBUT, 5}, 166 { "ddot", TDDOT, MS_DDOT, TGATTRIBUT, 5}, 167 { "def", TDEF, MS_DEF, TGRELATION, 0}, 168 { "div", TDIV, MS_DIV, TGPRODUCT, 0}, 169 { "divides", TDIVIDES, MS_LINE, TGRELATION, 0}, 170 { "dlarrow" , TDLARROW, MS_DLARROW, TGSTANDALONE, 5}, 171 { "dlrarrow" , TDLRARROW, MS_DLRARROW, TGSTANDALONE, 5}, 172 { "dot", TDOT, MS_DOT, TGATTRIBUT, 5}, 173 { "dotsaxis", TDOTSAXIS, MS_DOTSAXIS, TGSTANDALONE, 5}, // 5 to continue expression 174 { "dotsdiag", TDOTSDIAG, MS_DOTSUP, TGSTANDALONE, 5}, // 175 { "dotsdown", TDOTSDOWN, MS_DOTSDOWN, TGSTANDALONE, 5}, // 176 { "dotslow", TDOTSLOW, MS_DOTSLOW, TGSTANDALONE, 5}, // 177 { "dotsup", TDOTSUP, MS_DOTSUP, TGSTANDALONE, 5}, // 178 { "dotsvert", TDOTSVERT, MS_DOTSVERT, TGSTANDALONE, 5}, // 179 { "downarrow" , TDOWNARROW, MS_DOWNARROW, TGSTANDALONE, 5}, 180 { "drarrow" , TDRARROW, MS_DRARROW, TGSTANDALONE, 5}, 181 { "emptyset" , TEMPTYSET, MS_EMPTYSET, TGSTANDALONE, 5}, 182 { "equiv", TEQUIV, MS_EQUIV, TGRELATION, 0}, 183 { "exists", TEXISTS, MS_EXISTS, TGSTANDALONE, 5}, 184 { "exp", TEXP, '\0', TGFUNCTION, 5}, 185 { "fact", TFACT, MS_FACT, TGUNOPER, 5}, 186 { "fixed", TFIXED, '\0', TGFONT, 0}, 187 { "font", TFONT, '\0', TGFONTATTR, 5}, 188 { "forall", TFORALL, MS_FORALL, TGSTANDALONE, 5}, 189 { "from", TFROM, '\0', TGLIMIT, 0}, 190 { "func", TFUNC, '\0', TGFUNCTION, 5}, 191 { "ge", TGE, MS_GE, TGRELATION, 0}, 192 { "geslant", TGESLANT, MS_GESLANT, TGRELATION, 0 }, 193 { "gg", TGG, MS_GG, TGRELATION, 0}, 194 { "grave", TGRAVE, MS_GRAVE, TGATTRIBUT, 5}, 195 { "green", TGREEN, '\0', TGCOLOR, 0}, 196 { "gt", TGT, MS_GT, TGRELATION, 0}, 197 { "hat", THAT, MS_HAT, TGATTRIBUT, 5}, 198 { "hbar" , THBAR, MS_HBAR, TGSTANDALONE, 5}, 199 { "iiint", TIIINT, MS_IIINT, TGOPER, 5}, 200 { "iint", TIINT, MS_IINT, TGOPER, 5}, 201 { "in", TIN, MS_IN, TGRELATION, 0}, 202 { "infinity" , TINFINITY, MS_INFINITY, TGSTANDALONE, 5}, 203 { "infty" , TINFINITY, MS_INFINITY, TGSTANDALONE, 5}, 204 { "int", TINT, MS_INT, TGOPER, 5}, 205 { "intersection", TINTERSECT, MS_INTERSECT, TGPRODUCT, 0}, 206 { "ital", TITALIC, '\0', TGFONTATTR, 5}, 207 { "italic", TITALIC, '\0', TGFONTATTR, 5}, 208 { "lambdabar" , TLAMBDABAR, MS_LAMBDABAR, TGSTANDALONE, 5}, 209 { "langle", TLANGLE, MS_LANGLE, TGLBRACES, 5}, 210 { "lbrace", TLBRACE, MS_LBRACE, TGLBRACES, 5}, 211 { "lceil", TLCEIL, MS_LCEIL, TGLBRACES, 5}, 212 { "ldbracket", TLDBRACKET, MS_LDBRACKET, TGLBRACES, 5}, 213 { "ldline", TLDLINE, MS_DLINE, TGLBRACES, 5}, 214 { "le", TLE, MS_LE, TGRELATION, 0}, 215 { "left", TLEFT, '\0', 0, 5}, 216 { "leftarrow" , TLEFTARROW, MS_LEFTARROW, TGSTANDALONE, 5}, 217 { "leslant", TLESLANT, MS_LESLANT, TGRELATION, 0 }, 218 { "lfloor", TLFLOOR, MS_LFLOOR, TGLBRACES, 5}, 219 { "lim", TLIM, '\0', TGOPER, 5}, 220 { "liminf", TLIMINF, '\0', TGOPER, 5}, 221 { "limsup", TLIMSUP, '\0', TGOPER, 5}, 222 { "lint", TLINT, MS_LINT, TGOPER, 5}, 223 { "ll", TLL, MS_LL, TGRELATION, 0}, 224 { "lline", TLLINE, MS_LINE, TGLBRACES, 5}, 225 { "llint", TLLINT, MS_LLINT, TGOPER, 5}, 226 { "lllint", TLLLINT, MS_LLLINT, TGOPER, 5}, 227 { "ln", TLN, '\0', TGFUNCTION, 5}, 228 { "log", TLOG, '\0', TGFUNCTION, 5}, 229 { "lsub", TLSUB, '\0', TGPOWER, 0}, 230 { "lsup", TLSUP, '\0', TGPOWER, 0}, 231 { "lt", TLT, MS_LT, TGRELATION, 0}, 232 { "magenta", TMAGENTA, '\0', TGCOLOR, 0}, 233 { "matrix", TMATRIX, '\0', 0, 5}, 234 { "minusplus", TMINUSPLUS, MS_MINUSPLUS, TGUNOPER | TGSUM, 5}, 235 { "mline", TMLINE, MS_LINE, 0, 0}, //! nicht in TGRBRACES, Level 0 236 { "nabla", TNABLA, MS_NABLA, TGSTANDALONE, 5}, 237 { "nbold", TNBOLD, '\0', TGFONTATTR, 5}, 238 { "ndivides", TNDIVIDES, MS_NDIVIDES, TGRELATION, 0}, 239 { "neg", TNEG, MS_NEG, TGUNOPER, 5 }, 240 { "neq", TNEQ, MS_NEQ, TGRELATION, 0}, 241 { "newline", TNEWLINE, '\0', 0, 0}, 242 { "ni", TNI, MS_NI, TGRELATION, 0}, 243 { "nitalic", TNITALIC, '\0', TGFONTATTR, 5}, 244 { "none", TNONE, '\0', TGLBRACES | TGRBRACES, 0}, 245 { "nospace", TNOSPACE, '\0', TGSTANDALONE, 5}, 246 { "notin", TNOTIN, MS_NOTIN, TGRELATION, 0}, 247 { "nroot", TNROOT, MS_SQRT, TGUNOPER, 5}, 248 { "nsubset", TNSUBSET, MS_NSUBSET, TGRELATION, 0 }, 249 { "nsupset", TNSUPSET, MS_NSUPSET, TGRELATION, 0 }, 250 { "nsubseteq", TNSUBSETEQ, MS_NSUBSETEQ, TGRELATION, 0 }, 251 { "nsupseteq", TNSUPSETEQ, MS_NSUPSETEQ, TGRELATION, 0 }, 252 { "odivide", TODIVIDE, MS_ODIVIDE, TGPRODUCT, 0}, 253 { "odot", TODOT, MS_ODOT, TGPRODUCT, 0}, 254 { "ominus", TOMINUS, MS_OMINUS, TGSUM, 0}, 255 { "oper", TOPER, '\0', TGOPER, 5}, 256 { "oplus", TOPLUS, MS_OPLUS, TGSUM, 0}, 257 { "or", TOR, MS_OR, TGSUM, 0}, 258 { "ortho", TORTHO, MS_ORTHO, TGRELATION, 0}, 259 { "otimes", TOTIMES, MS_OTIMES, TGPRODUCT, 0}, 260 { "over", TOVER, '\0', TGPRODUCT, 0}, 261 { "overbrace", TOVERBRACE, MS_OVERBRACE, TGPRODUCT, 5}, 262 { "overline", TOVERLINE, '\0', TGATTRIBUT, 5}, 263 { "overstrike", TOVERSTRIKE, '\0', TGATTRIBUT, 5}, 264 { "owns", TNI, MS_NI, TGRELATION, 0}, 265 { "parallel", TPARALLEL, MS_DLINE, TGRELATION, 0}, 266 { "partial", TPARTIAL, MS_PARTIAL, TGSTANDALONE, 5 }, 267 { "phantom", TPHANTOM, '\0', TGFONTATTR, 5}, 268 { "plusminus", TPLUSMINUS, MS_PLUSMINUS, TGUNOPER | TGSUM, 5}, 269 { "prod", TPROD, MS_PROD, TGOPER, 5}, 270 { "prop", TPROP, MS_PROP, TGRELATION, 0}, 271 { "rangle", TRANGLE, MS_RANGLE, TGRBRACES, 0}, //! 0 to terminate expression 272 { "rbrace", TRBRACE, MS_RBRACE, TGRBRACES, 0}, // 273 { "rceil", TRCEIL, MS_RCEIL, TGRBRACES, 0}, // 274 { "rdbracket", TRDBRACKET, MS_RDBRACKET, TGRBRACES, 0}, // 275 { "rdline", TRDLINE, MS_DLINE, TGRBRACES, 0}, // 276 { "red", TRED, '\0', TGCOLOR, 0}, 277 { "rfloor", TRFLOOR, MS_RFLOOR, TGRBRACES, 0}, //! 0 to terminate expression 278 { "right", TRIGHT, '\0', 0, 0}, 279 { "rightarrow" , TRIGHTARROW, MS_RIGHTARROW, TGSTANDALONE, 5}, 280 { "rline", TRLINE, MS_LINE, TGRBRACES, 0}, //! 0 to terminate expression 281 { "rsub", TRSUB, '\0', TGPOWER, 0}, 282 { "rsup", TRSUP, '\0', TGPOWER, 0}, 283 { "sans", TSANS, '\0', TGFONT, 0}, 284 { "serif", TSERIF, '\0', TGFONT, 0}, 285 { "setC" , TSETC, MS_SETC, TGSTANDALONE, 5}, 286 { "setN" , TSETN, MS_SETN, TGSTANDALONE, 5}, 287 { "setQ" , TSETQ, MS_SETQ, TGSTANDALONE, 5}, 288 { "setR" , TSETR, MS_SETR, TGSTANDALONE, 5}, 289 { "setZ" , TSETZ, MS_SETZ, TGSTANDALONE, 5}, 290 { "setminus", TBACKSLASH, MS_BACKSLASH, TGPRODUCT, 0 }, 291 { "sim", TSIM, MS_SIM, TGRELATION, 0}, 292 { "simeq", TSIMEQ, MS_SIMEQ, TGRELATION, 0}, 293 { "sin", TSIN, '\0', TGFUNCTION, 5}, 294 { "sinh", TSINH, '\0', TGFUNCTION, 5}, 295 { "size", TSIZE, '\0', TGFONTATTR, 5}, 296 { "slash", TSLASH, MS_SLASH, TGPRODUCT, 0 }, 297 { "sqrt", TSQRT, MS_SQRT, TGUNOPER, 5}, 298 { "stack", TSTACK, '\0', 0, 5}, 299 { "sub", TRSUB, '\0', TGPOWER, 0}, 300 { "subset", TSUBSET, MS_SUBSET, TGRELATION, 0}, 301 { "subseteq", TSUBSETEQ, MS_SUBSETEQ, TGRELATION, 0}, 302 { "sum", TSUM, MS_SUM, TGOPER, 5}, 303 { "sup", TRSUP, '\0', TGPOWER, 0}, 304 { "supset", TSUPSET, MS_SUPSET, TGRELATION, 0}, 305 { "supseteq", TSUPSETEQ, MS_SUPSETEQ, TGRELATION, 0}, 306 { "tan", TTAN, '\0', TGFUNCTION, 5}, 307 { "tanh", TTANH, '\0', TGFUNCTION, 5}, 308 { "tilde", TTILDE, MS_TILDE, TGATTRIBUT, 5}, 309 { "times", TTIMES, MS_TIMES, TGPRODUCT, 0}, 310 { "to", TTO, '\0', TGLIMIT, 0}, 311 { "toward", TTOWARD, MS_RIGHTARROW, TGRELATION, 0}, 312 { "transl", TTRANSL, MS_TRANSL, TGRELATION, 0}, 313 { "transr", TTRANSR, MS_TRANSR, TGRELATION, 0}, 314 { "underbrace", TUNDERBRACE, MS_UNDERBRACE, TGPRODUCT, 5}, 315 { "underline", TUNDERLINE, '\0', TGATTRIBUT, 5}, 316 { "union", TUNION, MS_UNION, TGSUM, 0}, 317 { "uoper", TUOPER, '\0', TGUNOPER, 5}, 318 { "uparrow" , TUPARROW, MS_UPARROW, TGSTANDALONE, 5}, 319 { "vec", TVEC, MS_VEC, TGATTRIBUT, 5}, 320 { "white", TWHITE, '\0', TGCOLOR, 0}, 321 { "widebslash", TWIDEBACKSLASH, MS_BACKSLASH, TGPRODUCT, 0 }, 322 { "widehat", TWIDEHAT, MS_HAT, TGATTRIBUT, 5}, 323 { "widetilde", TWIDETILDE, MS_TILDE, TGATTRIBUT, 5}, 324 { "wideslash", TWIDESLASH, MS_SLASH, TGPRODUCT, 0 }, 325 { "widevec", TWIDEVEC, MS_VEC, TGATTRIBUT, 5}, 326 { "wp" , TWP, MS_WP, TGSTANDALONE, 5}, 327 { "yellow", TYELLOW, '\0', TGCOLOR, 0}, 328 // { "[", TLBRACKET, MS_LBRACKET, TGLBRACES, 5}, //! 5 to continue expression 329 // { "\\", TESCAPE, '\0', 0, 5}, 330 // { "]", TRBRACKET, MS_RBRACKET, TGRBRACES, 0}, //! 0 to terminate expression 331 // { "^", TRSUP, '\0', TGPOWER, 0}, 332 // { "_", TRSUB, '\0', TGPOWER, 0}, 333 // { "`", TSBLANK, '\0', TGBLANK, 5}, 334 // { "{", TLGROUP, MS_LBRACE, 0, 5}, //! 5 to continue expression 335 // { "|", TOR, MS_OR, TGSUM, 0}, 336 // { "}", TRGROUP, MS_RBRACE, 0, 0}, //! 0 to terminate expression 337 // { "~", TBLANK, '\0', TGBLANK, 5}, 338 { "", TEND, '\0', 0, 0} 339 }; 340 341 342 static const SmTokenTableEntry * GetTokenTableEntry( const String &rName ) 343 { 344 const SmTokenTableEntry * pRes = 0; 345 if (rName.Len()) 346 { 347 sal_Int32 nEntries = sizeof( aTokenTable ) / sizeof( aTokenTable[0] ); 348 for (sal_Int32 i = 0; i < nEntries; ++i) 349 { 350 if (rName.EqualsIgnoreCaseAscii( aTokenTable[i].pIdent )) 351 { 352 pRes = &aTokenTable[i]; 353 break; 354 } 355 } 356 357 } 358 359 return pRes; 360 } 361 362 363 /////////////////////////////////////////////////////////////////////////// 364 365 #if OSL_DEBUG_LEVEL 366 367 sal_Bool SmParser::IsDelimiter( const String &rTxt, xub_StrLen nPos ) 368 // returns 'sal_True' iff cChar is '\0' or a delimeter 369 { 370 DBG_ASSERT( nPos <= rTxt.Len(), "index out of range" ); 371 372 sal_Unicode cChar = rTxt.GetChar( nPos ); 373 if(!cChar) 374 return sal_True; 375 376 // check if 'cChar' is in the delimeter table 377 const sal_Unicode *pDelim = &aDelimiterTable[0]; 378 for ( ; *pDelim != 0; pDelim++) 379 if (*pDelim == cChar) 380 break; 381 382 sal_Bool bIsDelim = *pDelim != 0; 383 384 sal_Int16 nTypJp = SM_MOD()->GetSysLocale().GetCharClass().getType( rTxt, nPos ); 385 bIsDelim |= nTypJp == com::sun::star::i18n::UnicodeType::SPACE_SEPARATOR || 386 nTypJp == com::sun::star::i18n::UnicodeType::CONTROL; 387 388 return bIsDelim; 389 } 390 391 #endif 392 393 void SmParser::Insert(const String &rText, sal_uInt16 nPos) 394 { 395 m_aBufferString.Insert(rText, nPos); 396 397 xub_StrLen nLen = rText.Len(); 398 m_nBufferIndex = m_nBufferIndex + nLen; 399 m_nTokenIndex = m_nTokenIndex + nLen; 400 } 401 402 403 void SmParser::Replace( sal_uInt16 nPos, sal_uInt16 nLen, const String &rText ) 404 { 405 DBG_ASSERT( nPos + nLen <= m_aBufferString.Len(), "argument mismatch" ); 406 407 m_aBufferString.Replace( nPos, nLen, rText ); 408 sal_Int16 nChg = rText.Len() - nLen; 409 m_nBufferIndex = m_nBufferIndex + nChg; 410 m_nTokenIndex = m_nTokenIndex + nChg; 411 } 412 413 414 // First character may be any alphabetic 415 const sal_Int32 coStartFlags = 416 KParseTokens::ANY_LETTER_OR_NUMBER | 417 KParseTokens::IGNORE_LEADING_WS; 418 419 // Continuing characters may be any alphanumeric or dot. 420 const sal_Int32 coContFlags = 421 ((coStartFlags | KParseTokens::ASC_DOT) & ~KParseTokens::IGNORE_LEADING_WS) 422 | KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING; 423 424 // First character for numbers, may be any numeric or dot 425 const sal_Int32 coNumStartFlags = 426 KParseTokens::ASC_DIGIT | 427 KParseTokens::ASC_DOT | 428 KParseTokens::IGNORE_LEADING_WS; 429 // Continuing characters for numbers, may be any numeric or dot. 430 const sal_Int32 coNumContFlags = 431 (coNumStartFlags | KParseTokens::ASC_DOT) & ~KParseTokens::IGNORE_LEADING_WS; 432 433 void SmParser::NextToken() 434 { 435 static const String aEmptyStr; 436 437 xub_StrLen nBufLen = m_aBufferString.Len(); 438 ParseResult aRes; 439 xub_StrLen nRealStart; 440 sal_Bool bCont; 441 sal_Bool bNumStart = sal_False; 442 CharClass aCC(SM_MOD()->GetSysLocale().GetCharClass().getLocale()); 443 do 444 { 445 // skip white spaces 446 while (UnicodeType::SPACE_SEPARATOR == 447 aCC.getType( m_aBufferString, m_nBufferIndex )) 448 ++m_nBufferIndex; 449 450 sal_Int32 nStartFlags = coStartFlags; 451 sal_Int32 nContFlags = coContFlags; 452 sal_Unicode cFirstChar = m_aBufferString.GetChar( m_nBufferIndex ); 453 /* 454 removed because of #i11752# 455 bNumStart = cFirstChar == '.' || ('0' <= cFirstChar && cFirstChar <= '9'); 456 if (bNumStart) 457 { 458 nStartFlags = coNumStartFlags; 459 nContFlags = coNumContFlags; 460 } 461 */ 462 aRes = aCC.parseAnyToken( m_aBufferString, m_nBufferIndex, 463 nStartFlags, aEmptyStr, 464 nContFlags, aEmptyStr ); 465 466 // #i45779# parse numbers correctly 467 // i.e. independent from the locale setting. 468 // (note that #i11752# remains fixed) 469 if ((aRes.TokenType & KParseType::IDENTNAME) && IsDigit( cFirstChar )) 470 { 471 //! locale where '.' is decimal seperator! 472 static lang::Locale aDotLoc( SvxCreateLocale( LANGUAGE_ENGLISH_US ) ); 473 474 ParseResult aTmpRes; 475 lang::Locale aOldLoc( aCC.getLocale() ); 476 aCC.setLocale( aDotLoc ); 477 aTmpRes = aCC.parsePredefinedToken( 478 KParseType::ASC_NUMBER, 479 m_aBufferString, m_nBufferIndex, 480 KParseTokens::ASC_DIGIT, aEmptyStr, 481 KParseTokens::ASC_DIGIT | KParseTokens::ASC_DOT, aEmptyStr ); 482 aCC.setLocale( aOldLoc ); 483 if (aTmpRes.TokenType & KParseType::ASC_NUMBER) 484 aRes.TokenType = aTmpRes.TokenType; 485 } 486 487 nRealStart = m_nBufferIndex + sal::static_int_cast< xub_StrLen >(aRes.LeadingWhiteSpace); 488 m_nBufferIndex = nRealStart; 489 490 bCont = sal_False; 491 if ( aRes.TokenType == 0 && 492 nRealStart < nBufLen && 493 '\n' == m_aBufferString.GetChar( nRealStart ) ) 494 { 495 // keep data needed for tokens row and col entry up to date 496 ++m_Row; 497 m_nBufferIndex = m_nColOff = nRealStart + 1; 498 bCont = sal_True; 499 } 500 else if (aRes.TokenType & KParseType::ONE_SINGLE_CHAR) 501 { 502 String aName( m_aBufferString.Copy( nRealStart, 2 )); 503 if ( aName.EqualsAscii( "%%" )) 504 { 505 //SkipComment 506 m_nBufferIndex = nRealStart + 2; 507 while (m_nBufferIndex < nBufLen && 508 '\n' != m_aBufferString.GetChar( m_nBufferIndex )) 509 ++m_nBufferIndex; 510 bCont = sal_True; 511 } 512 } 513 514 } while (bCont); 515 516 // set index of current token 517 m_nTokenIndex = m_nBufferIndex; 518 519 m_aCurToken.nRow = m_Row; 520 m_aCurToken.nCol = nRealStart - m_nColOff + 1; 521 522 sal_Bool bHandled = sal_True; 523 if (nRealStart >= nBufLen) 524 { 525 m_aCurToken.eType = TEND; 526 m_aCurToken.cMathChar = '\0'; 527 m_aCurToken.nGroup = 0; 528 m_aCurToken.nLevel = 0; 529 m_aCurToken.aText.Erase(); 530 } 531 else if ((aRes.TokenType & (KParseType::ASC_NUMBER | KParseType::UNI_NUMBER)) 532 || (bNumStart && (aRes.TokenType & KParseType::IDENTNAME))) 533 { 534 sal_Int32 n = aRes.EndPos - nRealStart; 535 DBG_ASSERT( n >= 0, "length < 0" ); 536 m_aCurToken.eType = TNUMBER; 537 m_aCurToken.cMathChar = '\0'; 538 m_aCurToken.nGroup = 0; 539 m_aCurToken.nLevel = 5; 540 m_aCurToken.aText = m_aBufferString.Copy( nRealStart, sal::static_int_cast< xub_StrLen >(n) ); 541 542 #if OSL_DEBUG_LEVEL > 1 543 if (!IsDelimiter( m_aBufferString, static_cast< xub_StrLen >(aRes.EndPos) )) 544 { 545 DBG_WARNING( "identifier really finished? (compatibility!)" ); 546 } 547 #endif 548 } 549 else if (aRes.TokenType & KParseType::DOUBLE_QUOTE_STRING) 550 { 551 m_aCurToken.eType = TTEXT; 552 m_aCurToken.cMathChar = '\0'; 553 m_aCurToken.nGroup = 0; 554 m_aCurToken.nLevel = 5; 555 m_aCurToken.aText = aRes.DequotedNameOrString; 556 m_aCurToken.nRow = m_Row; 557 m_aCurToken.nCol = nRealStart - m_nColOff + 2; 558 } 559 else if (aRes.TokenType & KParseType::IDENTNAME) 560 { 561 sal_Int32 n = aRes.EndPos - nRealStart; 562 DBG_ASSERT( n >= 0, "length < 0" ); 563 String aName( m_aBufferString.Copy( nRealStart, sal::static_int_cast< xub_StrLen >(n) ) ); 564 const SmTokenTableEntry *pEntry = GetTokenTableEntry( aName ); 565 566 if (pEntry) 567 { 568 m_aCurToken.eType = pEntry->eType; 569 m_aCurToken.cMathChar = pEntry->cMathChar; 570 m_aCurToken.nGroup = pEntry->nGroup; 571 m_aCurToken.nLevel = pEntry->nLevel; 572 m_aCurToken.aText.AssignAscii( pEntry->pIdent ); 573 } 574 else 575 { 576 m_aCurToken.eType = TIDENT; 577 m_aCurToken.cMathChar = '\0'; 578 m_aCurToken.nGroup = 0; 579 m_aCurToken.nLevel = 5; 580 m_aCurToken.aText = aName; 581 582 #if OSL_DEBUG_LEVEL > 1 583 if (!IsDelimiter( m_aBufferString, static_cast< xub_StrLen >(aRes.EndPos) )) 584 { 585 DBG_WARNING( "identifier really finished? (compatibility!)" ); 586 } 587 #endif 588 } 589 } 590 else if (aRes.TokenType == 0 && '_' == m_aBufferString.GetChar( nRealStart )) 591 { 592 m_aCurToken.eType = TRSUB; 593 m_aCurToken.cMathChar = '\0'; 594 m_aCurToken.nGroup = TGPOWER; 595 m_aCurToken.nLevel = 0; 596 m_aCurToken.aText.AssignAscii( "_" ); 597 598 aRes.EndPos = nRealStart + 1; 599 } 600 else if (aRes.TokenType & KParseType::BOOLEAN) 601 { 602 sal_Int32 &rnEndPos = aRes.EndPos; 603 String aName( m_aBufferString.Copy( nRealStart, 604 sal::static_int_cast< xub_StrLen >(rnEndPos - nRealStart) )); 605 if (2 >= aName.Len()) 606 { 607 sal_Unicode ch = aName.GetChar( 0 ); 608 switch (ch) 609 { 610 case '<': 611 { 612 if (m_aBufferString.Copy( nRealStart, 2 ). 613 EqualsAscii( "<<" )) 614 { 615 m_aCurToken.eType = TLL; 616 m_aCurToken.cMathChar = MS_LL; 617 m_aCurToken.nGroup = TGRELATION; 618 m_aCurToken.nLevel = 0; 619 m_aCurToken.aText.AssignAscii( "<<" ); 620 621 rnEndPos = nRealStart + 2; 622 } 623 else if (m_aBufferString.Copy( nRealStart, 2 ). 624 EqualsAscii( "<=" )) 625 { 626 m_aCurToken.eType = TLE; 627 m_aCurToken.cMathChar = MS_LE; 628 m_aCurToken.nGroup = TGRELATION; 629 m_aCurToken.nLevel = 0; 630 m_aCurToken.aText.AssignAscii( "<=" ); 631 632 rnEndPos = nRealStart + 2; 633 } 634 else if (m_aBufferString.Copy( nRealStart, 2 ). 635 EqualsAscii( "<>" )) 636 { 637 m_aCurToken.eType = TNEQ; 638 m_aCurToken.cMathChar = MS_NEQ; 639 m_aCurToken.nGroup = TGRELATION; 640 m_aCurToken.nLevel = 0; 641 m_aCurToken.aText.AssignAscii( "<>" ); 642 643 rnEndPos = nRealStart + 2; 644 } 645 else if (m_aBufferString.Copy( nRealStart, 3 ). 646 EqualsAscii( "<?>" )) 647 { 648 m_aCurToken.eType = TPLACE; 649 m_aCurToken.cMathChar = MS_PLACE; 650 m_aCurToken.nGroup = 0; 651 m_aCurToken.nLevel = 5; 652 m_aCurToken.aText.AssignAscii( "<?>" ); 653 654 rnEndPos = nRealStart + 3; 655 } 656 else 657 { 658 m_aCurToken.eType = TLT; 659 m_aCurToken.cMathChar = MS_LT; 660 m_aCurToken.nGroup = TGRELATION; 661 m_aCurToken.nLevel = 0; 662 m_aCurToken.aText.AssignAscii( "<" ); 663 } 664 } 665 break; 666 case '>': 667 { 668 if (m_aBufferString.Copy( nRealStart, 2 ). 669 EqualsAscii( ">=" )) 670 { 671 m_aCurToken.eType = TGE; 672 m_aCurToken.cMathChar = MS_GE; 673 m_aCurToken.nGroup = TGRELATION; 674 m_aCurToken.nLevel = 0; 675 m_aCurToken.aText.AssignAscii( ">=" ); 676 677 rnEndPos = nRealStart + 2; 678 } 679 else if (m_aBufferString.Copy( nRealStart, 2 ). 680 EqualsAscii( ">>" )) 681 { 682 m_aCurToken.eType = TGG; 683 m_aCurToken.cMathChar = MS_GG; 684 m_aCurToken.nGroup = TGRELATION; 685 m_aCurToken.nLevel = 0; 686 m_aCurToken.aText.AssignAscii( ">>" ); 687 688 rnEndPos = nRealStart + 2; 689 } 690 else 691 { 692 m_aCurToken.eType = TGT; 693 m_aCurToken.cMathChar = MS_GT; 694 m_aCurToken.nGroup = TGRELATION; 695 m_aCurToken.nLevel = 0; 696 m_aCurToken.aText.AssignAscii( ">" ); 697 } 698 } 699 break; 700 default: 701 bHandled = sal_False; 702 } 703 } 704 } 705 else if (aRes.TokenType & KParseType::ONE_SINGLE_CHAR) 706 { 707 sal_Int32 &rnEndPos = aRes.EndPos; 708 String aName( m_aBufferString.Copy( nRealStart, 709 sal::static_int_cast< xub_StrLen >(rnEndPos - nRealStart) ) ); 710 711 if (1 == aName.Len()) 712 { 713 sal_Unicode ch = aName.GetChar( 0 ); 714 switch (ch) 715 { 716 case '%': 717 { 718 //! modifies aRes.EndPos 719 720 DBG_ASSERT( rnEndPos >= nBufLen || 721 '%' != m_aBufferString.GetChar( sal::static_int_cast< xub_StrLen >(rnEndPos) ), 722 "unexpected comment start" ); 723 724 // get identifier of user-defined character 725 ParseResult aTmpRes = aCC.parseAnyToken( 726 m_aBufferString, rnEndPos, 727 KParseTokens::ANY_LETTER, 728 aEmptyStr, 729 coContFlags, 730 aEmptyStr ); 731 732 xub_StrLen nTmpStart = sal::static_int_cast< xub_StrLen >(rnEndPos + 733 aTmpRes.LeadingWhiteSpace); 734 735 // default setting for the case that no identifier 736 // i.e. a valid symbol-name is following the '%' 737 // character 738 m_aCurToken.eType = TTEXT; 739 m_aCurToken.cMathChar = '\0'; 740 m_aCurToken.nGroup = 0; 741 m_aCurToken.nLevel = 5; 742 m_aCurToken.aText = String(); 743 m_aCurToken.nRow = sal::static_int_cast< xub_StrLen >(m_Row); 744 m_aCurToken.nCol = nTmpStart - m_nColOff; 745 746 if (aTmpRes.TokenType & KParseType::IDENTNAME) 747 { 748 749 xub_StrLen n = sal::static_int_cast< xub_StrLen >(aTmpRes.EndPos - nTmpStart); 750 m_aCurToken.eType = TSPECIAL; 751 m_aCurToken.aText = m_aBufferString.Copy( sal::static_int_cast< xub_StrLen >(nTmpStart-1), n+1 ); 752 753 DBG_ASSERT( aTmpRes.EndPos > rnEndPos, 754 "empty identifier" ); 755 if (aTmpRes.EndPos > rnEndPos) 756 rnEndPos = aTmpRes.EndPos; 757 else 758 ++rnEndPos; 759 } 760 761 // if no symbol-name was found we start-over with 762 // finding the next token right afer the '%' sign. 763 // I.e. we leave rnEndPos unmodified. 764 } 765 break; 766 case '[': 767 { 768 m_aCurToken.eType = TLBRACKET; 769 m_aCurToken.cMathChar = MS_LBRACKET; 770 m_aCurToken.nGroup = TGLBRACES; 771 m_aCurToken.nLevel = 5; 772 m_aCurToken.aText.AssignAscii( "[" ); 773 } 774 break; 775 case '\\': 776 { 777 m_aCurToken.eType = TESCAPE; 778 m_aCurToken.cMathChar = '\0'; 779 m_aCurToken.nGroup = 0; 780 m_aCurToken.nLevel = 5; 781 m_aCurToken.aText.AssignAscii( "\\" ); 782 } 783 break; 784 case ']': 785 { 786 m_aCurToken.eType = TRBRACKET; 787 m_aCurToken.cMathChar = MS_RBRACKET; 788 m_aCurToken.nGroup = TGRBRACES; 789 m_aCurToken.nLevel = 0; 790 m_aCurToken.aText.AssignAscii( "]" ); 791 } 792 break; 793 case '^': 794 { 795 m_aCurToken.eType = TRSUP; 796 m_aCurToken.cMathChar = '\0'; 797 m_aCurToken.nGroup = TGPOWER; 798 m_aCurToken.nLevel = 0; 799 m_aCurToken.aText.AssignAscii( "^" ); 800 } 801 break; 802 case '`': 803 { 804 m_aCurToken.eType = TSBLANK; 805 m_aCurToken.cMathChar = '\0'; 806 m_aCurToken.nGroup = TGBLANK; 807 m_aCurToken.nLevel = 5; 808 m_aCurToken.aText.AssignAscii( "`" ); 809 } 810 break; 811 case '{': 812 { 813 m_aCurToken.eType = TLGROUP; 814 m_aCurToken.cMathChar = MS_LBRACE; 815 m_aCurToken.nGroup = 0; 816 m_aCurToken.nLevel = 5; 817 m_aCurToken.aText.AssignAscii( "{" ); 818 } 819 break; 820 case '|': 821 { 822 m_aCurToken.eType = TOR; 823 m_aCurToken.cMathChar = MS_OR; 824 m_aCurToken.nGroup = TGSUM; 825 m_aCurToken.nLevel = 0; 826 m_aCurToken.aText.AssignAscii( "|" ); 827 } 828 break; 829 case '}': 830 { 831 m_aCurToken.eType = TRGROUP; 832 m_aCurToken.cMathChar = MS_RBRACE; 833 m_aCurToken.nGroup = 0; 834 m_aCurToken.nLevel = 0; 835 m_aCurToken.aText.AssignAscii( "}" ); 836 } 837 break; 838 case '~': 839 { 840 m_aCurToken.eType = TBLANK; 841 m_aCurToken.cMathChar = '\0'; 842 m_aCurToken.nGroup = TGBLANK; 843 m_aCurToken.nLevel = 5; 844 m_aCurToken.aText.AssignAscii( "~" ); 845 } 846 break; 847 case '#': 848 { 849 if (m_aBufferString.Copy( nRealStart, 2 ). 850 EqualsAscii( "##" )) 851 { 852 m_aCurToken.eType = TDPOUND; 853 m_aCurToken.cMathChar = '\0'; 854 m_aCurToken.nGroup = 0; 855 m_aCurToken.nLevel = 0; 856 m_aCurToken.aText.AssignAscii( "##" ); 857 858 rnEndPos = nRealStart + 2; 859 } 860 else 861 { 862 m_aCurToken.eType = TPOUND; 863 m_aCurToken.cMathChar = '\0'; 864 m_aCurToken.nGroup = 0; 865 m_aCurToken.nLevel = 0; 866 m_aCurToken.aText.AssignAscii( "#" ); 867 } 868 } 869 break; 870 case '&': 871 { 872 m_aCurToken.eType = TAND; 873 m_aCurToken.cMathChar = MS_AND; 874 m_aCurToken.nGroup = TGPRODUCT; 875 m_aCurToken.nLevel = 0; 876 m_aCurToken.aText.AssignAscii( "&" ); 877 } 878 break; 879 case '(': 880 { 881 m_aCurToken.eType = TLPARENT; 882 m_aCurToken.cMathChar = MS_LPARENT; 883 m_aCurToken.nGroup = TGLBRACES; 884 m_aCurToken.nLevel = 5; //! 0 to continue expression 885 m_aCurToken.aText.AssignAscii( "(" ); 886 } 887 break; 888 case ')': 889 { 890 m_aCurToken.eType = TRPARENT; 891 m_aCurToken.cMathChar = MS_RPARENT; 892 m_aCurToken.nGroup = TGRBRACES; 893 m_aCurToken.nLevel = 0; //! 0 to terminate expression 894 m_aCurToken.aText.AssignAscii( ")" ); 895 } 896 break; 897 case '*': 898 { 899 m_aCurToken.eType = TMULTIPLY; 900 m_aCurToken.cMathChar = MS_MULTIPLY; 901 m_aCurToken.nGroup = TGPRODUCT; 902 m_aCurToken.nLevel = 0; 903 m_aCurToken.aText.AssignAscii( "*" ); 904 } 905 break; 906 case '+': 907 { 908 if (m_aBufferString.Copy( nRealStart, 2 ). 909 EqualsAscii( "+-" )) 910 { 911 m_aCurToken.eType = TPLUSMINUS; 912 m_aCurToken.cMathChar = MS_PLUSMINUS; 913 m_aCurToken.nGroup = TGUNOPER | TGSUM; 914 m_aCurToken.nLevel = 5; 915 m_aCurToken.aText.AssignAscii( "+-" ); 916 917 rnEndPos = nRealStart + 2; 918 } 919 else 920 { 921 m_aCurToken.eType = TPLUS; 922 m_aCurToken.cMathChar = MS_PLUS; 923 m_aCurToken.nGroup = TGUNOPER | TGSUM; 924 m_aCurToken.nLevel = 5; 925 m_aCurToken.aText.AssignAscii( "+" ); 926 } 927 } 928 break; 929 case '-': 930 { 931 if (m_aBufferString.Copy( nRealStart, 2 ). 932 EqualsAscii( "-+" )) 933 { 934 m_aCurToken.eType = TMINUSPLUS; 935 m_aCurToken.cMathChar = MS_MINUSPLUS; 936 m_aCurToken.nGroup = TGUNOPER | TGSUM; 937 m_aCurToken.nLevel = 5; 938 m_aCurToken.aText.AssignAscii( "-+" ); 939 940 rnEndPos = nRealStart + 2; 941 } 942 else 943 { 944 m_aCurToken.eType = TMINUS; 945 m_aCurToken.cMathChar = MS_MINUS; 946 m_aCurToken.nGroup = TGUNOPER | TGSUM; 947 m_aCurToken.nLevel = 5; 948 m_aCurToken.aText.AssignAscii( "-" ); 949 } 950 } 951 break; 952 case '.': 953 { 954 // for compatibility with SO5.2 955 // texts like .34 ...56 ... h ...78..90 956 // will be treated as numbers 957 m_aCurToken.eType = TNUMBER; 958 m_aCurToken.cMathChar = '\0'; 959 m_aCurToken.nGroup = 0; 960 m_aCurToken.nLevel = 5; 961 962 xub_StrLen nTxtStart = m_nBufferIndex; 963 sal_Unicode cChar; 964 do 965 { 966 cChar = m_aBufferString.GetChar( ++m_nBufferIndex ); 967 } 968 while ( cChar == '.' || IsDigit( cChar ) ); 969 970 m_aCurToken.aText = m_aBufferString.Copy( sal::static_int_cast< xub_StrLen >(nTxtStart), 971 sal::static_int_cast< xub_StrLen >(m_nBufferIndex - nTxtStart) ); 972 aRes.EndPos = m_nBufferIndex; 973 } 974 break; 975 case '/': 976 { 977 m_aCurToken.eType = TDIVIDEBY; 978 m_aCurToken.cMathChar = MS_SLASH; 979 m_aCurToken.nGroup = TGPRODUCT; 980 m_aCurToken.nLevel = 0; 981 m_aCurToken.aText.AssignAscii( "/" ); 982 } 983 break; 984 case '=': 985 { 986 m_aCurToken.eType = TASSIGN; 987 m_aCurToken.cMathChar = MS_ASSIGN; 988 m_aCurToken.nGroup = TGRELATION; 989 m_aCurToken.nLevel = 0; 990 m_aCurToken.aText.AssignAscii( "=" ); 991 } 992 break; 993 default: 994 bHandled = sal_False; 995 } 996 } 997 } 998 else 999 bHandled = sal_False; 1000 1001 if (!bHandled) 1002 { 1003 m_aCurToken.eType = TCHARACTER; 1004 m_aCurToken.cMathChar = '\0'; 1005 m_aCurToken.nGroup = 0; 1006 m_aCurToken.nLevel = 5; 1007 m_aCurToken.aText = m_aBufferString.Copy( nRealStart, 1 ); 1008 1009 aRes.EndPos = nRealStart + 1; 1010 } 1011 1012 if (TEND != m_aCurToken.eType) 1013 m_nBufferIndex = sal::static_int_cast< xub_StrLen >(aRes.EndPos); 1014 } 1015 1016 1017 //////////////////////////////////////// 1018 // grammar 1019 // 1020 1021 1022 void SmParser::Table() 1023 { 1024 SmNodeArray LineArray; 1025 1026 Line(); 1027 while (m_aCurToken.eType == TNEWLINE) 1028 { 1029 NextToken(); 1030 Line(); 1031 } 1032 1033 if (m_aCurToken.eType != TEND) 1034 Error(PE_UNEXPECTED_CHAR); 1035 1036 sal_uLong n = m_aNodeStack.Count(); 1037 1038 LineArray.resize(n); 1039 1040 for (sal_uLong i = 0; i < n; i++) 1041 LineArray[n - (i + 1)] = m_aNodeStack.Pop(); 1042 1043 SmStructureNode *pSNode = new SmTableNode(m_aCurToken); 1044 pSNode->SetSubNodes(LineArray); 1045 m_aNodeStack.Push(pSNode); 1046 } 1047 1048 1049 void SmParser::Align() 1050 // parse alignment info (if any), then go on with rest of expression 1051 { 1052 SmStructureNode *pSNode = 0; 1053 sal_Bool bNeedGroupClose = sal_False; 1054 1055 if (TokenInGroup(TGALIGN)) 1056 { 1057 if (CONVERT_40_TO_50 == GetConversion()) 1058 // encapsulate expression to be aligned in group braces 1059 // (here group-open brace) 1060 { Insert('{', GetTokenIndex()); 1061 bNeedGroupClose = sal_True; 1062 1063 // get first valid align statement in sequence 1064 // (the dominant one in 4.0) and erase all others (especially old 1065 // discarded tokens) from command string. 1066 while (TokenInGroup(TGALIGN)) 1067 { 1068 if (TokenInGroup(TGDISCARDED) || pSNode) 1069 { 1070 m_nBufferIndex = GetTokenIndex(); 1071 m_aBufferString.Erase(m_nBufferIndex, m_aCurToken.aText.Len()); 1072 } 1073 else 1074 pSNode = new SmAlignNode(m_aCurToken); 1075 1076 NextToken(); 1077 } 1078 } 1079 else 1080 { 1081 pSNode = new SmAlignNode(m_aCurToken); 1082 1083 NextToken(); 1084 1085 // allow for just one align statement in 5.0 1086 if (CONVERT_40_TO_50 != GetConversion() && TokenInGroup(TGALIGN)) 1087 { Error(PE_DOUBLE_ALIGN); 1088 return; 1089 } 1090 } 1091 } 1092 1093 Expression(); 1094 1095 if (bNeedGroupClose) 1096 Insert('}', GetTokenIndex()); 1097 1098 if (pSNode) 1099 { pSNode->SetSubNodes(m_aNodeStack.Pop(), 0); 1100 m_aNodeStack.Push(pSNode); 1101 } 1102 } 1103 1104 1105 void SmParser::Line() 1106 { 1107 sal_uInt16 n = 0; 1108 SmNodeArray ExpressionArray; 1109 1110 ExpressionArray.resize(n); 1111 1112 // start with single expression that may have an alignment statement 1113 // (and go on with expressions that must not have alignment 1114 // statements in 'while' loop below. See also 'Expression()'.) 1115 if (m_aCurToken.eType != TEND && m_aCurToken.eType != TNEWLINE) 1116 { Align(); 1117 ExpressionArray.resize(++n); 1118 ExpressionArray[n - 1] = m_aNodeStack.Pop(); 1119 } 1120 1121 while (m_aCurToken.eType != TEND && m_aCurToken.eType != TNEWLINE) 1122 { if (CONVERT_40_TO_50 != GetConversion()) 1123 Expression(); 1124 else 1125 Align(); 1126 ExpressionArray.resize(++n); 1127 ExpressionArray[n - 1] = m_aNodeStack.Pop(); 1128 } 1129 1130 SmStructureNode *pSNode = new SmLineNode(m_aCurToken); 1131 pSNode->SetSubNodes(ExpressionArray); 1132 m_aNodeStack.Push(pSNode); 1133 } 1134 1135 1136 void SmParser::Expression() 1137 { 1138 sal_Bool bUseExtraSpaces = sal_True; 1139 SmNode *pNode = m_aNodeStack.Pop(); 1140 if (pNode) 1141 { 1142 if (pNode->GetToken().eType == TNOSPACE) 1143 bUseExtraSpaces = sal_False; 1144 else 1145 m_aNodeStack.Push(pNode); // push the node from above again (now to be used as argument to this current 'nospace' node) 1146 } 1147 1148 sal_uInt16 n = 0; 1149 SmNodeArray RelationArray; 1150 1151 RelationArray.resize(n); 1152 1153 Relation(); 1154 RelationArray.resize(++n); 1155 RelationArray[n - 1] = m_aNodeStack.Pop(); 1156 1157 while (m_aCurToken.nLevel >= 4) 1158 { Relation(); 1159 RelationArray.resize(++n); 1160 RelationArray[n - 1] = m_aNodeStack.Pop(); 1161 } 1162 1163 SmExpressionNode *pSNode = new SmExpressionNode(m_aCurToken); 1164 pSNode->SetSubNodes(RelationArray); 1165 pSNode->SetUseExtraSpaces(bUseExtraSpaces); 1166 m_aNodeStack.Push(pSNode); 1167 } 1168 1169 1170 void SmParser::Relation() 1171 { 1172 Sum(); 1173 while (TokenInGroup(TGRELATION)) 1174 { 1175 SmStructureNode *pSNode = new SmBinHorNode(m_aCurToken); 1176 SmNode *pFirst = m_aNodeStack.Pop(); 1177 1178 OpSubSup(); 1179 SmNode *pSecond = m_aNodeStack.Pop(); 1180 1181 Sum(); 1182 1183 pSNode->SetSubNodes(pFirst, pSecond, m_aNodeStack.Pop()); 1184 m_aNodeStack.Push(pSNode); 1185 } 1186 } 1187 1188 1189 void SmParser::Sum() 1190 { 1191 Product(); 1192 while (TokenInGroup(TGSUM)) 1193 { 1194 SmStructureNode *pSNode = new SmBinHorNode(m_aCurToken); 1195 SmNode *pFirst = m_aNodeStack.Pop(); 1196 1197 OpSubSup(); 1198 SmNode *pSecond = m_aNodeStack.Pop(); 1199 1200 Product(); 1201 1202 pSNode->SetSubNodes(pFirst, pSecond, m_aNodeStack.Pop()); 1203 m_aNodeStack.Push(pSNode); 1204 } 1205 } 1206 1207 1208 void SmParser::Product() 1209 { 1210 Power(); 1211 1212 while (TokenInGroup(TGPRODUCT)) 1213 { SmStructureNode *pSNode; 1214 SmNode *pFirst = m_aNodeStack.Pop(), 1215 *pOper; 1216 sal_Bool bSwitchArgs = sal_False; 1217 1218 SmTokenType eType = m_aCurToken.eType; 1219 switch (eType) 1220 { 1221 case TOVER: 1222 pSNode = new SmBinVerNode(m_aCurToken); 1223 pOper = new SmRectangleNode(m_aCurToken); 1224 NextToken(); 1225 break; 1226 1227 case TBOPER: 1228 pSNode = new SmBinHorNode(m_aCurToken); 1229 1230 NextToken(); 1231 1232 GlyphSpecial(); 1233 pOper = m_aNodeStack.Pop(); 1234 break; 1235 1236 case TOVERBRACE : 1237 case TUNDERBRACE : 1238 pSNode = new SmVerticalBraceNode(m_aCurToken); 1239 pOper = new SmMathSymbolNode(m_aCurToken); 1240 1241 NextToken(); 1242 break; 1243 1244 case TWIDEBACKSLASH: 1245 case TWIDESLASH: 1246 { 1247 SmBinDiagonalNode *pSTmp = new SmBinDiagonalNode(m_aCurToken); 1248 pSTmp->SetAscending(eType == TWIDESLASH); 1249 pSNode = pSTmp; 1250 1251 pOper = new SmPolyLineNode(m_aCurToken); 1252 NextToken(); 1253 1254 bSwitchArgs =sal_True; 1255 break; 1256 } 1257 1258 default: 1259 pSNode = new SmBinHorNode(m_aCurToken); 1260 1261 OpSubSup(); 1262 pOper = m_aNodeStack.Pop(); 1263 } 1264 1265 Power(); 1266 1267 if (bSwitchArgs) 1268 //! vgl siehe SmBinDiagonalNode::Arrange 1269 pSNode->SetSubNodes(pFirst, m_aNodeStack.Pop(), pOper); 1270 else 1271 pSNode->SetSubNodes(pFirst, pOper, m_aNodeStack.Pop()); 1272 m_aNodeStack.Push(pSNode); 1273 } 1274 } 1275 1276 1277 void SmParser::SubSup(sal_uLong nActiveGroup) 1278 { 1279 DBG_ASSERT(nActiveGroup == TGPOWER || nActiveGroup == TGLIMIT, 1280 "Sm: falsche Tokengruppe"); 1281 1282 if (!TokenInGroup(nActiveGroup)) 1283 // already finish 1284 return; 1285 1286 SmSubSupNode *pNode = new SmSubSupNode(m_aCurToken); 1287 //! Of course 'm_aCurToken' is just the first sub-/supscript token. 1288 //! It should be of no further interest. The positions of the 1289 //! sub-/supscripts will be identified by the corresponding subnodes 1290 //! index in the 'aSubNodes' array (enum value from 'SmSubSup'). 1291 1292 pNode->SetUseLimits(nActiveGroup == TGLIMIT); 1293 1294 // initialize subnodes array 1295 SmNodeArray aSubNodes; 1296 aSubNodes.resize(1 + SUBSUP_NUM_ENTRIES); 1297 aSubNodes[0] = m_aNodeStack.Pop(); 1298 for (sal_uInt16 i = 1; i < aSubNodes.size(); i++) 1299 aSubNodes[i] = NULL; 1300 1301 // process all sub-/supscripts 1302 int nIndex = 0; 1303 while (TokenInGroup(nActiveGroup)) 1304 { SmTokenType eType (m_aCurToken.eType); 1305 1306 // skip sub-/supscript token 1307 NextToken(); 1308 1309 // get sub-/supscript node on top of stack 1310 if (eType == TFROM || eType == TTO) 1311 { 1312 // parse limits in old 4.0 and 5.0 style 1313 Relation(); 1314 } 1315 else 1316 Term(); 1317 1318 switch (eType) 1319 { case TRSUB : nIndex = (int) RSUB; break; 1320 case TRSUP : nIndex = (int) RSUP; break; 1321 case TFROM : 1322 case TCSUB : nIndex = (int) CSUB; break; 1323 case TTO : 1324 case TCSUP : nIndex = (int) CSUP; break; 1325 case TLSUB : nIndex = (int) LSUB; break; 1326 case TLSUP : nIndex = (int) LSUP; break; 1327 default : 1328 DBG_ASSERT(sal_False, "Sm: unbekannter Fall"); 1329 } 1330 nIndex++; 1331 DBG_ASSERT(1 <= nIndex && nIndex <= 1 + SUBSUP_NUM_ENTRIES, 1332 "SmParser::Power() : sub-/supscript index falsch"); 1333 1334 // set sub-/supscript if not already done 1335 if (aSubNodes[nIndex] != NULL) 1336 Error(PE_DOUBLE_SUBSUPSCRIPT); 1337 aSubNodes[nIndex] = m_aNodeStack.Pop(); 1338 } 1339 1340 pNode->SetSubNodes(aSubNodes); 1341 m_aNodeStack.Push(pNode); 1342 } 1343 1344 1345 void SmParser::OpSubSup() 1346 { 1347 // push operator symbol 1348 m_aNodeStack.Push(new SmMathSymbolNode(m_aCurToken)); 1349 // skip operator token 1350 NextToken(); 1351 // get sub- supscripts if any 1352 if (TokenInGroup(TGPOWER)) 1353 SubSup(TGPOWER); 1354 } 1355 1356 1357 void SmParser::Power() 1358 { 1359 // get body for sub- supscripts on top of stack 1360 Term(); 1361 1362 SubSup(TGPOWER); 1363 } 1364 1365 1366 void SmParser::Blank() 1367 { 1368 DBG_ASSERT(TokenInGroup(TGBLANK), "Sm : falsches Token"); 1369 SmBlankNode *pBlankNode = new SmBlankNode(m_aCurToken); 1370 1371 while (TokenInGroup(TGBLANK)) 1372 { 1373 pBlankNode->IncreaseBy(m_aCurToken); 1374 NextToken(); 1375 } 1376 1377 // Blanks am Zeilenende ignorieren wenn die entsprechende Option gesetzt ist 1378 if ( m_aCurToken.eType == TNEWLINE || 1379 (m_aCurToken.eType == TEND && SM_MOD()->GetConfig()->IsIgnoreSpacesRight()) ) 1380 { 1381 pBlankNode->Clear(); 1382 } 1383 1384 m_aNodeStack.Push(pBlankNode); 1385 } 1386 1387 1388 void SmParser::Term() 1389 { 1390 switch (m_aCurToken.eType) 1391 { 1392 case TESCAPE : 1393 Escape(); 1394 break; 1395 1396 case TNOSPACE : 1397 case TLGROUP : 1398 { 1399 bool bNoSpace = m_aCurToken.eType == TNOSPACE; 1400 if (bNoSpace) // push 'no space' node and continue to parse expression 1401 { 1402 m_aNodeStack.Push(new SmExpressionNode(m_aCurToken)); 1403 NextToken(); 1404 } 1405 if (m_aCurToken.eType != TLGROUP) 1406 { 1407 m_aNodeStack.Pop(); // get rid of the 'no space' node pushed above 1408 Term(); 1409 } 1410 else 1411 { 1412 NextToken(); 1413 1414 // allow for empty group 1415 if (m_aCurToken.eType == TRGROUP) 1416 { 1417 if (bNoSpace) // get rid of the 'no space' node pushed above 1418 m_aNodeStack.Pop(); 1419 SmStructureNode *pSNode = new SmExpressionNode(m_aCurToken); 1420 pSNode->SetSubNodes(NULL, NULL); 1421 m_aNodeStack.Push(pSNode); 1422 1423 NextToken(); 1424 } 1425 else // go as usual 1426 { 1427 Align(); 1428 if (m_aCurToken.eType != TRGROUP) 1429 Error(PE_RGROUP_EXPECTED); 1430 else 1431 NextToken(); 1432 } 1433 } 1434 } 1435 break; 1436 1437 case TLEFT : 1438 Brace(); 1439 break; 1440 1441 case TBLANK : 1442 case TSBLANK : 1443 Blank(); 1444 break; 1445 1446 case TTEXT : 1447 m_aNodeStack.Push(new SmTextNode(m_aCurToken, FNT_TEXT)); 1448 NextToken(); 1449 break; 1450 case TIDENT : 1451 case TCHARACTER : 1452 m_aNodeStack.Push(new SmTextNode(m_aCurToken, FNT_VARIABLE)); 1453 NextToken(); 1454 break; 1455 case TNUMBER : 1456 m_aNodeStack.Push(new SmTextNode(m_aCurToken, FNT_NUMBER)); 1457 NextToken(); 1458 break; 1459 1460 case TLEFTARROW : 1461 case TRIGHTARROW : 1462 case TUPARROW : 1463 case TDOWNARROW : 1464 case TSETN : 1465 case TSETZ : 1466 case TSETQ : 1467 case TSETR : 1468 case TSETC : 1469 case THBAR : 1470 case TLAMBDABAR : 1471 case TCIRC : 1472 case TDRARROW : 1473 case TDLARROW : 1474 case TDLRARROW : 1475 case TBACKEPSILON : 1476 case TALEPH : 1477 case TIM : 1478 case TRE : 1479 case TWP : 1480 case TEMPTYSET : 1481 case TINFINITY : 1482 case TEXISTS : 1483 case TFORALL : 1484 case TPARTIAL : 1485 case TNABLA : 1486 case TTOWARD : 1487 case TDOTSAXIS : 1488 case TDOTSDIAG : 1489 case TDOTSDOWN : 1490 case TDOTSLOW : 1491 case TDOTSUP : 1492 case TDOTSVERT : 1493 m_aNodeStack.Push(new SmMathSymbolNode(m_aCurToken)); 1494 NextToken(); 1495 break; 1496 1497 case TPLACE: 1498 m_aNodeStack.Push(new SmPlaceNode(m_aCurToken)); 1499 NextToken(); 1500 break; 1501 1502 case TSPECIAL: 1503 Special(); 1504 break; 1505 1506 case TBINOM: 1507 Binom(); 1508 break; 1509 1510 case TSTACK: 1511 Stack(); 1512 break; 1513 1514 case TMATRIX: 1515 Matrix(); 1516 break; 1517 1518 default: 1519 if (TokenInGroup(TGLBRACES)) 1520 { Brace(); 1521 } 1522 else if (TokenInGroup(TGOPER)) 1523 { Operator(); 1524 } 1525 else if (TokenInGroup(TGUNOPER)) 1526 { UnOper(); 1527 } 1528 else if ( TokenInGroup(TGATTRIBUT) 1529 || TokenInGroup(TGFONTATTR)) 1530 { SmStructureNodeArray aArray; 1531 1532 sal_Bool bIsAttr; 1533 sal_uInt16 n = 0; 1534 while (sal_True == (bIsAttr = TokenInGroup(TGATTRIBUT)) 1535 || TokenInGroup(TGFONTATTR)) 1536 { aArray.resize(n + 1); 1537 1538 if (bIsAttr) 1539 Attribut(); 1540 else 1541 FontAttribut(); 1542 1543 // check if casting in following line is ok 1544 DBG_ASSERT(!m_aNodeStack.Top()->IsVisible(), "Sm : Ooops..."); 1545 1546 aArray[n] = (SmStructureNode *) m_aNodeStack.Pop(); 1547 n++; 1548 } 1549 1550 Power(); 1551 1552 SmNode *pFirstNode = m_aNodeStack.Pop(); 1553 while (n > 0) 1554 { aArray[n - 1]->SetSubNodes(0, pFirstNode); 1555 pFirstNode = aArray[n - 1]; 1556 n--; 1557 } 1558 m_aNodeStack.Push(pFirstNode); 1559 } 1560 else if (TokenInGroup(TGFUNCTION)) 1561 { if (CONVERT_40_TO_50 != GetConversion()) 1562 { Function(); 1563 } 1564 else // encapsulate old 4.0 style parsing in braces 1565 { 1566 // insert opening brace 1567 Insert('{', GetTokenIndex()); 1568 1569 // 1570 // parse in 4.0 style 1571 // 1572 Function(); 1573 1574 SmNode *pFunc = m_aNodeStack.Pop(); 1575 1576 if (m_aCurToken.eType == TLPARENT) 1577 { Term(); 1578 } 1579 else 1580 { Align(); 1581 } 1582 1583 // insert closing brace 1584 Insert('}', GetTokenIndex()); 1585 1586 SmStructureNode *pSNode = new SmExpressionNode(pFunc->GetToken()); 1587 pSNode->SetSubNodes(pFunc, m_aNodeStack.Pop()); 1588 m_aNodeStack.Push(pSNode); 1589 } 1590 } 1591 else 1592 Error(PE_UNEXPECTED_CHAR); 1593 } 1594 } 1595 1596 1597 void SmParser::Escape() 1598 { 1599 NextToken(); 1600 1601 sal_Unicode cChar; 1602 switch (m_aCurToken.eType) 1603 { case TLPARENT : cChar = MS_LPARENT; break; 1604 case TRPARENT : cChar = MS_RPARENT; break; 1605 case TLBRACKET : cChar = MS_LBRACKET; break; 1606 case TRBRACKET : cChar = MS_RBRACKET; break; 1607 case TLDBRACKET : cChar = MS_LDBRACKET; break; 1608 case TRDBRACKET : cChar = MS_RDBRACKET; break; 1609 case TLBRACE : 1610 case TLGROUP : cChar = MS_LBRACE; break; 1611 case TRBRACE : 1612 case TRGROUP : cChar = MS_RBRACE; break; 1613 case TLANGLE : cChar = MS_LANGLE; break; 1614 case TRANGLE : cChar = MS_RANGLE; break; 1615 case TLCEIL : cChar = MS_LCEIL; break; 1616 case TRCEIL : cChar = MS_RCEIL; break; 1617 case TLFLOOR : cChar = MS_LFLOOR; break; 1618 case TRFLOOR : cChar = MS_RFLOOR; break; 1619 case TLLINE : 1620 case TRLINE : cChar = MS_LINE; break; 1621 case TLDLINE : 1622 case TRDLINE : cChar = MS_DLINE; break; 1623 default: 1624 Error(PE_UNEXPECTED_TOKEN); 1625 } 1626 1627 SmNode *pNode = new SmMathSymbolNode(m_aCurToken); 1628 m_aNodeStack.Push(pNode); 1629 1630 NextToken(); 1631 } 1632 1633 1634 void SmParser::Operator() 1635 { 1636 if (TokenInGroup(TGOPER)) 1637 { SmStructureNode *pSNode = new SmOperNode(m_aCurToken); 1638 1639 // put operator on top of stack 1640 Oper(); 1641 1642 if (TokenInGroup(TGLIMIT) || TokenInGroup(TGPOWER)) 1643 SubSup(m_aCurToken.nGroup); 1644 SmNode *pOperator = m_aNodeStack.Pop(); 1645 1646 // get argument 1647 Power(); 1648 1649 pSNode->SetSubNodes(pOperator, m_aNodeStack.Pop()); 1650 m_aNodeStack.Push(pSNode); 1651 } 1652 } 1653 1654 1655 void SmParser::Oper() 1656 { 1657 SmTokenType eType (m_aCurToken.eType); 1658 SmNode *pNode = NULL; 1659 1660 switch (eType) 1661 { 1662 case TSUM : 1663 case TPROD : 1664 case TCOPROD : 1665 case TINT : 1666 case TIINT : 1667 case TIIINT : 1668 case TLINT : 1669 case TLLINT : 1670 case TLLLINT : 1671 pNode = new SmMathSymbolNode(m_aCurToken); 1672 break; 1673 1674 case TLIM : 1675 case TLIMSUP : 1676 case TLIMINF : 1677 { 1678 const sal_Char* pLim = 0; 1679 switch (eType) 1680 { 1681 case TLIM : pLim = "lim"; break; 1682 case TLIMSUP : pLim = "lim sup"; break; 1683 case TLIMINF : pLim = "lim inf"; break; 1684 default: 1685 break; 1686 } 1687 if( pLim ) 1688 m_aCurToken.aText.AssignAscii( pLim ); 1689 pNode = new SmTextNode(m_aCurToken, FNT_TEXT); 1690 } 1691 break; 1692 1693 case TOVERBRACE : 1694 case TUNDERBRACE : 1695 pNode = new SmMathSymbolNode(m_aCurToken); 1696 break; 1697 1698 case TOPER : 1699 NextToken(); 1700 1701 DBG_ASSERT(m_aCurToken.eType == TSPECIAL, "Sm: falsches Token"); 1702 pNode = new SmGlyphSpecialNode(m_aCurToken); 1703 break; 1704 1705 default : 1706 DBG_ASSERT(0, "Sm: unbekannter Fall"); 1707 } 1708 m_aNodeStack.Push(pNode); 1709 1710 NextToken(); 1711 } 1712 1713 1714 void SmParser::UnOper() 1715 { 1716 DBG_ASSERT(TokenInGroup(TGUNOPER), "Sm: falsches Token"); 1717 1718 SmToken aNodeToken = m_aCurToken; 1719 SmTokenType eType = m_aCurToken.eType; 1720 sal_Bool bIsPostfix = eType == TFACT; 1721 1722 SmStructureNode *pSNode; 1723 SmNode *pOper = 0, 1724 *pExtra = 0, 1725 *pArg; 1726 1727 switch (eType) 1728 { 1729 case TABS : 1730 case TSQRT : 1731 NextToken(); 1732 break; 1733 1734 case TNROOT : 1735 NextToken(); 1736 Power(); 1737 pExtra = m_aNodeStack.Pop(); 1738 break; 1739 1740 case TUOPER : 1741 NextToken(); 1742 GlyphSpecial(); 1743 pOper = m_aNodeStack.Pop(); 1744 break; 1745 1746 case TPLUS : 1747 case TMINUS : 1748 case TPLUSMINUS : 1749 case TMINUSPLUS : 1750 case TNEG : 1751 case TFACT : 1752 OpSubSup(); 1753 pOper = m_aNodeStack.Pop(); 1754 break; 1755 1756 default : 1757 Error(PE_UNOPER_EXPECTED); 1758 } 1759 1760 // get argument 1761 Power(); 1762 pArg = m_aNodeStack.Pop(); 1763 1764 if (eType == TABS) 1765 { pSNode = new SmBraceNode(aNodeToken); 1766 pSNode->SetScaleMode(SCALE_HEIGHT); 1767 1768 // build nodes for left & right lines 1769 // (text, group, level of the used token are of no interrest here) 1770 // we'll use row & column of the keyword for abs 1771 aNodeToken.eType = TABS; 1772 // 1773 aNodeToken.cMathChar = MS_LINE; 1774 SmNode* pLeft = new SmMathSymbolNode(aNodeToken); 1775 // 1776 aNodeToken.cMathChar = MS_LINE; 1777 SmNode* pRight = new SmMathSymbolNode(aNodeToken); 1778 1779 pSNode->SetSubNodes(pLeft, pArg, pRight); 1780 } 1781 else if (eType == TSQRT || eType == TNROOT) 1782 { pSNode = new SmRootNode(aNodeToken); 1783 pOper = new SmRootSymbolNode(aNodeToken); 1784 pSNode->SetSubNodes(pExtra, pOper, pArg); 1785 } 1786 else 1787 { pSNode = new SmUnHorNode(aNodeToken); 1788 1789 if (bIsPostfix) 1790 pSNode->SetSubNodes(pArg, pOper); 1791 else 1792 // prefix operator 1793 pSNode->SetSubNodes(pOper, pArg); 1794 } 1795 1796 m_aNodeStack.Push(pSNode); 1797 } 1798 1799 1800 void SmParser::Attribut() 1801 { 1802 DBG_ASSERT(TokenInGroup(TGATTRIBUT), "Sm: falsche Tokengruppe"); 1803 1804 SmStructureNode *pSNode = new SmAttributNode(m_aCurToken); 1805 SmNode *pAttr; 1806 SmScaleMode eScaleMode = SCALE_NONE; 1807 1808 // get appropriate node for the attribut itself 1809 switch (m_aCurToken.eType) 1810 { case TUNDERLINE : 1811 case TOVERLINE : 1812 case TOVERSTRIKE : 1813 pAttr = new SmRectangleNode(m_aCurToken); 1814 eScaleMode = SCALE_WIDTH; 1815 break; 1816 1817 case TWIDEVEC : 1818 case TWIDEHAT : 1819 case TWIDETILDE : 1820 pAttr = new SmMathSymbolNode(m_aCurToken); 1821 eScaleMode = SCALE_WIDTH; 1822 break; 1823 1824 default : 1825 pAttr = new SmMathSymbolNode(m_aCurToken); 1826 } 1827 1828 NextToken(); 1829 1830 pSNode->SetSubNodes(pAttr, 0); 1831 pSNode->SetScaleMode(eScaleMode); 1832 m_aNodeStack.Push(pSNode); 1833 } 1834 1835 1836 void SmParser::FontAttribut() 1837 { 1838 DBG_ASSERT(TokenInGroup(TGFONTATTR), "Sm: falsche Tokengruppe"); 1839 1840 switch (m_aCurToken.eType) 1841 { 1842 case TITALIC : 1843 case TNITALIC : 1844 case TBOLD : 1845 case TNBOLD : 1846 case TPHANTOM : 1847 m_aNodeStack.Push(new SmFontNode(m_aCurToken)); 1848 NextToken(); 1849 break; 1850 1851 case TSIZE : 1852 FontSize(); 1853 break; 1854 1855 case TFONT : 1856 Font(); 1857 break; 1858 1859 case TCOLOR : 1860 Color(); 1861 break; 1862 1863 default : 1864 DBG_ASSERT(0, "Sm: unbekannter Fall"); 1865 } 1866 } 1867 1868 1869 void SmParser::Color() 1870 { 1871 DBG_ASSERT(m_aCurToken.eType == TCOLOR, "Sm : Ooops..."); 1872 1873 // last color rules, get that one 1874 SmToken aToken; 1875 do 1876 { NextToken(); 1877 1878 if (TokenInGroup(TGCOLOR)) 1879 { aToken = m_aCurToken; 1880 NextToken(); 1881 } 1882 else 1883 Error(PE_COLOR_EXPECTED); 1884 } while (m_aCurToken.eType == TCOLOR); 1885 1886 m_aNodeStack.Push(new SmFontNode(aToken)); 1887 } 1888 1889 1890 void SmParser::Font() 1891 { 1892 DBG_ASSERT(m_aCurToken.eType == TFONT, "Sm : Ooops..."); 1893 1894 // last font rules, get that one 1895 SmToken aToken; 1896 do 1897 { NextToken(); 1898 1899 if (TokenInGroup(TGFONT)) 1900 { aToken = m_aCurToken; 1901 NextToken(); 1902 } 1903 else 1904 Error(PE_FONT_EXPECTED); 1905 } while (m_aCurToken.eType == TFONT); 1906 1907 m_aNodeStack.Push(new SmFontNode(aToken)); 1908 } 1909 1910 1911 // gets number used as arguments in Math formulas (e.g. 'size' command) 1912 // Format: no negative numbers, must start with a digit, no exponent notation, ... 1913 sal_Bool lcl_IsNumber(const UniString& rText) 1914 { 1915 sal_Bool bPoint = sal_False; 1916 const sal_Unicode* pBuffer = rText.GetBuffer(); 1917 for(xub_StrLen nPos = 0; nPos < rText.Len(); nPos++, pBuffer++) 1918 { 1919 const sal_Unicode cChar = *pBuffer; 1920 if(cChar == '.') 1921 { 1922 if(bPoint) 1923 return sal_False; 1924 else 1925 bPoint = sal_True; 1926 } 1927 else if ( !IsDigit( cChar ) ) 1928 return sal_False; 1929 } 1930 return sal_True; 1931 } 1932 1933 void SmParser::FontSize() 1934 { 1935 DBG_ASSERT(m_aCurToken.eType == TSIZE, "Sm : Ooops..."); 1936 1937 sal_uInt16 Type; 1938 SmFontNode *pFontNode = new SmFontNode(m_aCurToken); 1939 1940 NextToken(); 1941 1942 switch (m_aCurToken.eType) 1943 { 1944 case TNUMBER: Type = FNTSIZ_ABSOLUT; break; 1945 case TPLUS: Type = FNTSIZ_PLUS; break; 1946 case TMINUS: Type = FNTSIZ_MINUS; break; 1947 case TMULTIPLY: Type = FNTSIZ_MULTIPLY; break; 1948 case TDIVIDEBY: Type = FNTSIZ_DIVIDE; break; 1949 1950 default: 1951 delete pFontNode; 1952 Error(PE_SIZE_EXPECTED); 1953 return; 1954 } 1955 1956 if (Type != FNTSIZ_ABSOLUT) 1957 { 1958 NextToken(); 1959 if (m_aCurToken.eType != TNUMBER) 1960 { 1961 delete pFontNode; 1962 Error(PE_SIZE_EXPECTED); 1963 return; 1964 } 1965 } 1966 1967 // get number argument 1968 Fraction aValue( 1L ); 1969 if (lcl_IsNumber( m_aCurToken.aText )) 1970 { 1971 double fTmp; 1972 if ((fTmp = m_aCurToken.aText.ToDouble()) != 0.0) 1973 { 1974 aValue = fTmp; 1975 1976 //!! keep the numerator and denominator from being to large 1977 //!! otherwise ongoing multiplications may result in overflows 1978 //!! (for example in SmNode::SetFontSize the font size calculated 1979 //!! may become 0 because of this!!! Happens e.g. for ftmp = 2.9 with Linux 1980 //!! or ftmp = 1.11111111111111111... (11/9) on every platform.) 1981 if (aValue.GetDenominator() > 1000) 1982 { 1983 long nNum = aValue.GetNumerator(); 1984 long nDenom = aValue.GetDenominator(); 1985 while (nDenom > 1000) 1986 { 1987 nNum /= 10; 1988 nDenom /= 10; 1989 } 1990 aValue = Fraction( nNum, nDenom ); 1991 } 1992 } 1993 } 1994 1995 NextToken(); 1996 1997 pFontNode->SetSizeParameter(aValue, Type); 1998 m_aNodeStack.Push(pFontNode); 1999 } 2000 2001 2002 void SmParser::Brace() 2003 { 2004 DBG_ASSERT(m_aCurToken.eType == TLEFT || TokenInGroup(TGLBRACES), 2005 "Sm: kein Klammer Ausdruck"); 2006 2007 SmStructureNode *pSNode = new SmBraceNode(m_aCurToken); 2008 SmNode *pBody = 0, 2009 *pLeft = 0, 2010 *pRight = 0; 2011 SmScaleMode eScaleMode = SCALE_NONE; 2012 SmParseError eError = PE_NONE; 2013 2014 if (m_aCurToken.eType == TLEFT) 2015 { NextToken(); 2016 2017 eScaleMode = SCALE_HEIGHT; 2018 2019 // check for left bracket 2020 if (TokenInGroup(TGLBRACES) || TokenInGroup(TGRBRACES)) 2021 { 2022 pLeft = new SmMathSymbolNode(m_aCurToken); 2023 2024 NextToken(); 2025 Bracebody(sal_True); 2026 pBody = m_aNodeStack.Pop(); 2027 2028 if (m_aCurToken.eType == TRIGHT) 2029 { NextToken(); 2030 2031 // check for right bracket 2032 if (TokenInGroup(TGLBRACES) || TokenInGroup(TGRBRACES)) 2033 { 2034 pRight = new SmMathSymbolNode(m_aCurToken); 2035 NextToken(); 2036 } 2037 else 2038 eError = PE_RBRACE_EXPECTED; 2039 } 2040 else 2041 eError = PE_RIGHT_EXPECTED; 2042 } 2043 else 2044 eError = PE_LBRACE_EXPECTED; 2045 } 2046 else 2047 { 2048 if (TokenInGroup(TGLBRACES)) 2049 { 2050 pLeft = new SmMathSymbolNode(m_aCurToken); 2051 2052 NextToken(); 2053 Bracebody(sal_False); 2054 pBody = m_aNodeStack.Pop(); 2055 2056 SmTokenType eExpectedType = TUNKNOWN; 2057 switch (pLeft->GetToken().eType) 2058 { case TLPARENT : eExpectedType = TRPARENT; break; 2059 case TLBRACKET : eExpectedType = TRBRACKET; break; 2060 case TLBRACE : eExpectedType = TRBRACE; break; 2061 case TLDBRACKET : eExpectedType = TRDBRACKET; break; 2062 case TLLINE : eExpectedType = TRLINE; break; 2063 case TLDLINE : eExpectedType = TRDLINE; break; 2064 case TLANGLE : eExpectedType = TRANGLE; break; 2065 case TLFLOOR : eExpectedType = TRFLOOR; break; 2066 case TLCEIL : eExpectedType = TRCEIL; break; 2067 default : 2068 DBG_ASSERT(0, "Sm: unbekannter Fall"); 2069 } 2070 2071 if (m_aCurToken.eType == eExpectedType) 2072 { 2073 pRight = new SmMathSymbolNode(m_aCurToken); 2074 NextToken(); 2075 } 2076 else 2077 eError = PE_PARENT_MISMATCH; 2078 } 2079 else 2080 eError = PE_LBRACE_EXPECTED; 2081 } 2082 2083 if (eError == PE_NONE) 2084 { DBG_ASSERT(pLeft, "Sm: NULL pointer"); 2085 DBG_ASSERT(pRight, "Sm: NULL pointer"); 2086 pSNode->SetSubNodes(pLeft, pBody, pRight); 2087 pSNode->SetScaleMode(eScaleMode); 2088 m_aNodeStack.Push(pSNode); 2089 } 2090 else 2091 { delete pSNode; 2092 delete pBody; 2093 delete pLeft; 2094 delete pRight; 2095 2096 Error(eError); 2097 } 2098 } 2099 2100 2101 void SmParser::Bracebody(sal_Bool bIsLeftRight) 2102 { 2103 SmStructureNode *pBody = new SmBracebodyNode(m_aCurToken); 2104 SmNodeArray aNodes; 2105 sal_uInt16 nNum = 0; 2106 2107 // get body if any 2108 if (bIsLeftRight) 2109 { 2110 do 2111 { 2112 if (m_aCurToken.eType == TMLINE) 2113 { 2114 m_aNodeStack.Push(new SmMathSymbolNode(m_aCurToken)); 2115 NextToken(); 2116 nNum++; 2117 } 2118 else if (m_aCurToken.eType != TRIGHT) 2119 { Align(); 2120 nNum++; 2121 2122 if (m_aCurToken.eType != TMLINE && m_aCurToken.eType != TRIGHT) 2123 Error(PE_RIGHT_EXPECTED); 2124 } 2125 } while (m_aCurToken.eType != TEND && m_aCurToken.eType != TRIGHT); 2126 } 2127 else 2128 { 2129 do 2130 { 2131 if (m_aCurToken.eType == TMLINE) 2132 { 2133 m_aNodeStack.Push(new SmMathSymbolNode(m_aCurToken)); 2134 NextToken(); 2135 nNum++; 2136 } 2137 else if (!TokenInGroup(TGRBRACES)) 2138 { Align(); 2139 nNum++; 2140 2141 if (m_aCurToken.eType != TMLINE && !TokenInGroup(TGRBRACES)) 2142 Error(PE_RBRACE_EXPECTED); 2143 } 2144 } while (m_aCurToken.eType != TEND && !TokenInGroup(TGRBRACES)); 2145 } 2146 2147 // build argument vector in parsing order 2148 aNodes.resize(nNum); 2149 for (sal_uInt16 i = 0; i < nNum; i++) 2150 aNodes[nNum - 1 - i] = m_aNodeStack.Pop(); 2151 2152 pBody->SetSubNodes(aNodes); 2153 pBody->SetScaleMode(bIsLeftRight ? SCALE_HEIGHT : SCALE_NONE); 2154 m_aNodeStack.Push(pBody); 2155 } 2156 2157 2158 void SmParser::Function() 2159 { 2160 switch (m_aCurToken.eType) 2161 { 2162 case TFUNC: 2163 NextToken(); // skip "FUNC"-statement 2164 // fall through 2165 2166 case TSIN : 2167 case TCOS : 2168 case TTAN : 2169 case TCOT : 2170 case TASIN : 2171 case TACOS : 2172 case TATAN : 2173 case TACOT : 2174 case TSINH : 2175 case TCOSH : 2176 case TTANH : 2177 case TCOTH : 2178 case TASINH : 2179 case TACOSH : 2180 case TATANH : 2181 case TACOTH : 2182 case TLN : 2183 case TLOG : 2184 case TEXP : 2185 m_aNodeStack.Push(new SmTextNode(m_aCurToken, FNT_FUNCTION)); 2186 NextToken(); 2187 break; 2188 2189 default: 2190 Error(PE_FUNC_EXPECTED); 2191 } 2192 } 2193 2194 2195 void SmParser::Binom() 2196 { 2197 SmNodeArray ExpressionArray; 2198 SmStructureNode *pSNode = new SmTableNode(m_aCurToken); 2199 2200 NextToken(); 2201 2202 Sum(); 2203 Sum(); 2204 2205 ExpressionArray.resize(2); 2206 2207 for (int i = 0; i < 2; i++) 2208 ExpressionArray[2 - (i + 1)] = m_aNodeStack.Pop(); 2209 2210 pSNode->SetSubNodes(ExpressionArray); 2211 m_aNodeStack.Push(pSNode); 2212 } 2213 2214 2215 void SmParser::Stack() 2216 { 2217 SmNodeArray ExpressionArray; 2218 NextToken(); 2219 if (m_aCurToken.eType == TLGROUP) 2220 { 2221 sal_uInt16 n = 0; 2222 2223 do 2224 { 2225 NextToken(); 2226 Align(); 2227 n++; 2228 } 2229 while (m_aCurToken.eType == TPOUND); 2230 2231 ExpressionArray.resize(n); 2232 2233 for (sal_uInt16 i = 0; i < n; i++) 2234 ExpressionArray[n - (i + 1)] = m_aNodeStack.Pop(); 2235 2236 if (m_aCurToken.eType != TRGROUP) 2237 Error(PE_RGROUP_EXPECTED); 2238 2239 NextToken(); 2240 2241 SmStructureNode *pSNode = new SmTableNode(m_aCurToken); 2242 pSNode->SetSubNodes(ExpressionArray); 2243 m_aNodeStack.Push(pSNode); 2244 } 2245 else 2246 Error(PE_LGROUP_EXPECTED); 2247 } 2248 2249 2250 void SmParser::Matrix() 2251 { 2252 SmNodeArray ExpressionArray; 2253 2254 NextToken(); 2255 if (m_aCurToken.eType == TLGROUP) 2256 { 2257 sal_uInt16 c = 0; 2258 2259 do 2260 { 2261 NextToken(); 2262 Align(); 2263 c++; 2264 } 2265 while (m_aCurToken.eType == TPOUND); 2266 2267 sal_uInt16 r = 1; 2268 2269 while (m_aCurToken.eType == TDPOUND) 2270 { 2271 NextToken(); 2272 for (sal_uInt16 i = 0; i < c; i++) 2273 { 2274 Align(); 2275 if (i < (c - 1)) 2276 { 2277 if (m_aCurToken.eType == TPOUND) 2278 { 2279 NextToken(); 2280 } 2281 else 2282 Error(PE_POUND_EXPECTED); 2283 } 2284 } 2285 2286 r++; 2287 } 2288 2289 long nRC = r * c; 2290 2291 ExpressionArray.resize(nRC); 2292 2293 for (sal_uInt16 i = 0; i < (nRC); i++) 2294 ExpressionArray[(nRC) - (i + 1)] = m_aNodeStack.Pop(); 2295 2296 if (m_aCurToken.eType != TRGROUP) 2297 Error(PE_RGROUP_EXPECTED); 2298 2299 NextToken(); 2300 2301 SmMatrixNode *pMNode = new SmMatrixNode(m_aCurToken); 2302 pMNode->SetSubNodes(ExpressionArray); 2303 pMNode->SetRowCol(r, c); 2304 m_aNodeStack.Push(pMNode); 2305 } 2306 else 2307 Error(PE_LGROUP_EXPECTED); 2308 } 2309 2310 2311 void SmParser::Special() 2312 { 2313 sal_Bool bReplace = sal_False; 2314 String &rName = m_aCurToken.aText; 2315 String aNewName; 2316 2317 if (CONVERT_NONE == GetConversion()) 2318 { 2319 // conversion of symbol names for 6.0 (XML) file format 2320 // (name change on import / export. 2321 // UI uses localized names XML file format does not.) 2322 if( rName.Len() && rName.GetChar( 0 ) == sal_Unicode( '%' ) ) 2323 { 2324 if (IsImportSymbolNames()) 2325 { 2326 const SmLocalizedSymbolData &rLSD = SM_MOD()->GetLocSymbolData(); 2327 aNewName = rLSD.GetUiSymbolName( rName.Copy( 1 ) ); 2328 bReplace = sal_True; 2329 } 2330 else if (IsExportSymbolNames()) 2331 { 2332 const SmLocalizedSymbolData &rLSD = SM_MOD()->GetLocSymbolData(); 2333 aNewName = rLSD.GetExportSymbolName( rName.Copy( 1 ) ); 2334 bReplace = sal_True; 2335 } 2336 } 2337 if( aNewName.Len() ) 2338 aNewName.Insert( '%', 0 ); 2339 } 2340 else // 5.0 <-> 6.0 formula text (symbol name) conversion 2341 { 2342 LanguageType nLanguage = GetLanguage(); 2343 SmLocalizedSymbolData &rData = SM_MOD()->GetLocSymbolData(); 2344 const ResStringArray *pFrom = 0; 2345 const ResStringArray *pTo = 0; 2346 if (CONVERT_50_TO_60 == GetConversion()) 2347 { 2348 pFrom = rData.Get50NamesArray( nLanguage ); 2349 pTo = rData.Get60NamesArray( nLanguage ); 2350 } 2351 else if (CONVERT_60_TO_50 == GetConversion()) 2352 { 2353 pFrom = rData.Get60NamesArray( nLanguage ); 2354 pTo = rData.Get50NamesArray( nLanguage ); 2355 } 2356 if (pFrom && pTo) 2357 { 2358 DBG_ASSERT( pFrom->Count() == pTo->Count(), 2359 "array length mismatch" ); 2360 sal_uInt16 nCount = sal::static_int_cast< sal_uInt16 >(pFrom->Count()); 2361 for (sal_uInt16 i = 0; i < nCount; ++i) 2362 { 2363 if (pFrom->GetString(i) == rName) 2364 { 2365 aNewName = pTo->GetString(i); 2366 bReplace = sal_True; 2367 } 2368 } 2369 } 2370 // else: 2371 // conversion arrays not found or (usually) 2372 // conversion not necessary 2373 } 2374 2375 if (bReplace && aNewName.Len() && rName != aNewName) 2376 { 2377 Replace( GetTokenIndex(), rName.Len(), aNewName ); 2378 rName = aNewName; 2379 } 2380 2381 // add symbol name to list of used symbols 2382 const String aSymbolName( m_aCurToken.aText.Copy( 1 ) ); 2383 if (aSymbolName.Len() > 0 ) 2384 AddToUsedSymbols( aSymbolName ); 2385 2386 m_aNodeStack.Push(new SmSpecialNode(m_aCurToken)); 2387 NextToken(); 2388 } 2389 2390 2391 void SmParser::GlyphSpecial() 2392 { 2393 m_aNodeStack.Push(new SmGlyphSpecialNode(m_aCurToken)); 2394 NextToken(); 2395 } 2396 2397 2398 void SmParser::Error(SmParseError eError) 2399 { 2400 SmStructureNode *pSNode = new SmExpressionNode(m_aCurToken); 2401 SmErrorNode *pErr = new SmErrorNode(eError, m_aCurToken); 2402 pSNode->SetSubNodes(pErr, 0); 2403 2404 //! put a structure node on the stack (instead of the error node itself) 2405 //! because sometimes such a node is expected in order to attach some 2406 //! subnodes 2407 m_aNodeStack.Push(pSNode); 2408 2409 AddError(eError, pSNode); 2410 2411 NextToken(); 2412 } 2413 2414 2415 // end gramar 2416 2417 2418 SmParser::SmParser() 2419 { 2420 m_eConversion = CONVERT_NONE; 2421 m_bImportSymNames = m_bExportSymNames = sal_False; 2422 m_nLang = Application::GetSettings().GetUILanguage(); 2423 } 2424 2425 2426 SmNode *SmParser::Parse(const String &rBuffer) 2427 { 2428 ClearUsedSymbols(); 2429 2430 m_aBufferString = rBuffer; 2431 m_aBufferString.ConvertLineEnd( LINEEND_LF ); 2432 m_nBufferIndex = 2433 m_nTokenIndex = 0; 2434 m_Row = 1; 2435 m_nColOff = 0; 2436 m_nCurError = -1; 2437 2438 for (sal_uInt16 i = 0; i < m_aErrDescList.Count(); i++) 2439 delete m_aErrDescList.Remove(i); 2440 2441 m_aErrDescList.Clear(); 2442 2443 m_aNodeStack.Clear(); 2444 2445 SetLanguage( Application::GetSettings().GetUILanguage() ); 2446 NextToken(); 2447 Table(); 2448 2449 return m_aNodeStack.Pop(); 2450 } 2451 2452 2453 sal_uInt16 SmParser::AddError(SmParseError Type, SmNode *pNode) 2454 { 2455 SmErrorDesc *pErrDesc = new SmErrorDesc; 2456 2457 pErrDesc->Type = Type; 2458 pErrDesc->pNode = pNode; 2459 pErrDesc->Text = String(SmResId(RID_ERR_IDENT)); 2460 2461 sal_uInt16 nRID; 2462 switch (Type) 2463 { 2464 case PE_UNEXPECTED_CHAR: nRID = RID_ERR_UNEXPECTEDCHARACTER; break; 2465 case PE_LGROUP_EXPECTED: nRID = RID_ERR_LGROUPEXPECTED; break; 2466 case PE_RGROUP_EXPECTED: nRID = RID_ERR_RGROUPEXPECTED; break; 2467 case PE_LBRACE_EXPECTED: nRID = RID_ERR_LBRACEEXPECTED; break; 2468 case PE_RBRACE_EXPECTED: nRID = RID_ERR_RBRACEEXPECTED; break; 2469 case PE_FUNC_EXPECTED: nRID = RID_ERR_FUNCEXPECTED; break; 2470 case PE_UNOPER_EXPECTED: nRID = RID_ERR_UNOPEREXPECTED; break; 2471 case PE_BINOPER_EXPECTED: nRID = RID_ERR_BINOPEREXPECTED; break; 2472 case PE_SYMBOL_EXPECTED: nRID = RID_ERR_SYMBOLEXPECTED; break; 2473 case PE_IDENTIFIER_EXPECTED: nRID = RID_ERR_IDENTEXPECTED; break; 2474 case PE_POUND_EXPECTED: nRID = RID_ERR_POUNDEXPECTED; break; 2475 case PE_COLOR_EXPECTED: nRID = RID_ERR_COLOREXPECTED; break; 2476 case PE_RIGHT_EXPECTED: nRID = RID_ERR_RIGHTEXPECTED; break; 2477 2478 default: 2479 nRID = RID_ERR_UNKOWN; 2480 } 2481 pErrDesc->Text += SmResId(nRID); 2482 2483 m_aErrDescList.Insert(pErrDesc); 2484 2485 return (sal_uInt16) m_aErrDescList.GetPos(pErrDesc); 2486 } 2487 2488 2489 const SmErrorDesc *SmParser::NextError() 2490 { 2491 if (m_aErrDescList.Count()) 2492 if (m_nCurError > 0) return m_aErrDescList.Seek(--m_nCurError); 2493 else 2494 { 2495 m_nCurError = 0; 2496 return m_aErrDescList.Seek(m_nCurError); 2497 } 2498 else return 0; 2499 } 2500 2501 2502 const SmErrorDesc *SmParser::PrevError() 2503 { 2504 if (m_aErrDescList.Count()) 2505 if (m_nCurError < (int) (m_aErrDescList.Count() - 1)) return m_aErrDescList.Seek(++m_nCurError); 2506 else 2507 { 2508 m_nCurError = (int) (m_aErrDescList.Count() - 1); 2509 return m_aErrDescList.Seek(m_nCurError); 2510 } 2511 else return 0; 2512 } 2513 2514 2515 const SmErrorDesc *SmParser::GetError(sal_uInt16 i) 2516 { 2517 return (/*i >= 0 &&*/ i < m_aErrDescList.Count()) 2518 ? m_aErrDescList.Seek(i) 2519 : m_aErrDescList.Seek(m_nCurError); 2520 } 2521 2522 2523