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