diff options
Diffstat (limited to 'starmath')
-rw-r--r-- | starmath/inc/error.hxx | 3 | ||||
-rw-r--r-- | starmath/inc/parse.hxx | 3 | ||||
-rw-r--r-- | starmath/inc/strings.hrc | 5 | ||||
-rw-r--r-- | starmath/inc/strings.hxx | 2 | ||||
-rw-r--r-- | starmath/inc/token.hxx | 28 | ||||
-rw-r--r-- | starmath/source/ElementsDockingWindow.cxx | 7 | ||||
-rw-r--r-- | starmath/source/node.cxx | 41 | ||||
-rw-r--r-- | starmath/source/parse.cxx | 601 | ||||
-rw-r--r-- | starmath/source/visitors.cxx | 34 |
9 files changed, 463 insertions, 261 deletions
diff --git a/starmath/inc/error.hxx b/starmath/inc/error.hxx index a05123d6e080..d8179da593d5 100644 --- a/starmath/inc/error.hxx +++ b/starmath/inc/error.hxx @@ -39,7 +39,8 @@ enum class SmParseError FontExpected, SizeExpected, DoubleAlign, - DoubleSubsupscript + DoubleSubsupscript, + NumberExpected }; diff --git a/starmath/inc/parse.hxx b/starmath/inc/parse.hxx index 519a90041f65..4f1e3024ccb3 100644 --- a/starmath/inc/parse.hxx +++ b/starmath/inc/parse.hxx @@ -83,6 +83,8 @@ class SmParser SmParser& operator=(const SmParser&) = delete; void NextToken(); + void NextTokenColor(); + void NextTokenFontSize(); sal_Int32 GetTokenIndex() const { return m_nTokenIndex; } void Replace( sal_Int32 nPos, sal_Int32 nLen, const OUString &rText ); @@ -140,7 +142,6 @@ public: const SmErrorDesc* NextError(); const SmErrorDesc* PrevError(); const SmErrorDesc* GetError(); - static const SmTokenTableEntry* GetTokenTableEntry( const OUString &rName ); const std::set< OUString >& GetUsedSymbols() const { return m_aUsedSymbols; } }; diff --git a/starmath/inc/strings.hrc b/starmath/inc/strings.hrc index 64144759f5cc..50adc4a3e042 100644 --- a/starmath/inc/strings.hrc +++ b/starmath/inc/strings.hrc @@ -195,6 +195,8 @@ #define RID_COLORX_TEAL_HELP NC_("RID_COLORX_TEAL_HELP", "Color Teal" ) #define RID_COLORX_YELLOW_HELP NC_("RID_COLORX_YELLOW_HELP", "Color Yellow" ) #define RID_COLORX_RGB_HELP NC_("RID_COLORX_RGB_HELP", "Color RGB" ) +#define RID_COLORX_RGBA_HELP NC_("RID_COLORX_RGBA_HELP", "Color RGBA" ) +#define RID_COLORX_HEX_HELP NC_("RID_COLORX_HEX_HELP", "Color hexadecimal" ) #define RID_LRGROUPX_HELP NC_("RID_LRGROUPX_HELP", "Group Brackets" ) #define RID_LRPARENTX_HELP NC_("RID_LRPARENTX_HELP", "Round Brackets" ) #define RID_LRBRACKETX_HELP NC_("RID_LRBRACKETX_HELP", "Square Brackets" ) @@ -317,6 +319,8 @@ #define STR_TEAL NC_("STR_TEAL", "teal" ) #define STR_YELLOW NC_("STR_YELLOW", "yellow" ) #define STR_RGB NC_("STR_RGB", "rgb" ) +#define STR_RGBA NC_("STR_RGBA", "rgba" ) +#define STR_HEX NC_("STR_HEX", "hex" ) #define STR_HIDE NC_("STR_HIDE", "hide" ) #define STR_SIZE NC_("STR_SIZE", "size" ) #define STR_FONT NC_("STR_FONT", "font" ) @@ -339,6 +343,7 @@ #define RID_ERR_SIZEEXPECTED NC_("RID_ERR_SIZEEXPECTED", "'size' followed by an unexpected token" ) #define RID_ERR_DOUBLEALIGN NC_("RID_ERR_DOUBLEALIGN", "Double aligning is not allowed" ) #define RID_ERR_DOUBLESUBSUPSCRIPT NC_("RID_ERR_DOUBLESUBSUPSCRIPT", "Double sub/superscripts is not allowed" ) +#define RID_ERR_NUMBEREXPECTED NC_("RID_ERR_NUMBEREXPECTED", "Expected number" ) #define RID_ERR_POUNDEXPECTED NC_("RID_ERR_POUNDEXPECTED", "'#' expected" ) #define RID_ERR_COLOREXPECTED NC_("RID_ERR_COLOREXPECTED", "Color required" ) #define RID_ERR_RIGHTEXPECTED NC_("RID_ERR_RIGHTEXPECTED", "'RIGHT' expected" ) diff --git a/starmath/inc/strings.hxx b/starmath/inc/strings.hxx index fb00ac2f4782..2daf463afd25 100644 --- a/starmath/inc/strings.hxx +++ b/starmath/inc/strings.hxx @@ -188,6 +188,8 @@ #define RID_COLORX_TEAL "color teal {<?>} " #define RID_COLORX_YELLOW "color yellow {<?>} " #define RID_COLORX_RGB "color rgb 0 0 0 {<?>} " +#define RID_COLORX_RGBA "color rgba 0 0 0 0 {<?>} " +#define RID_COLORX_HEX "color hex 000000 {<?>} " #define RID_LRGROUPX "{<?>} " #define RID_LRPARENTX "(<?>) " #define RID_LRBRACKETX "[<?>] " diff --git a/starmath/inc/token.hxx b/starmath/inc/token.hxx index 1403e96987a2..a58e28d42be8 100644 --- a/starmath/inc/token.hxx +++ b/starmath/inc/token.hxx @@ -64,14 +64,12 @@ enum SmTokenType TDOTSDIAG, TDOTSUP, TDOTSDOWN, TACUTE, TBAR, TBREVE, TCHECK, TCIRCLE, TDOT, TDDOT, TDDDOT, TGRAVE, THAT, TTILDE, TVEC, - THARPOON, TUNDERLINE, TOVERLINE, TOVERSTRIKE, TITALIC, TNITALIC, TBOLD, TNBOLD, TPHANTOM, TFONT, TSIZE, TCOLOR, TALIGNL, TALIGNC, TALIGNR, TLEFT, TRIGHT, TLANGLE, TLBRACE, TLLINE, TLDLINE, TLCEIL, TLFLOOR, TNONE, TMLINE, TRANGLE, TRBRACE, TRLINE, TRDLINE, TRCEIL, TRFLOOR, - TSIN, TCOS, TTAN, TCOT, TFUNC, TSTACK, TMATRIX, TDPOUND, TPLACE, TTEXT, TNUMBER, TCHARACTER, TIDENT, TNEQ, TEQUIV, TDEF, TPROP, TSIM, TSIMEQ, @@ -81,12 +79,7 @@ enum SmTokenType TODIVIDE, TTRANSL, TTRANSR, TIINT, TIIINT, TLINT, TLLINT, TLLLINT, TPROD, TCOPROD, TFORALL, TEXISTS, TNOTEXISTS, TLIM, TNABLA, - TTOWARD, TSINH, TCOSH, TTANH, TCOTH, - TASIN, TACOS, TATAN, TLN, TLOG, - TUOPER, TBOPER, TBLACK, TWHITE, TRED, - TGREEN, TBLUE, TCYAN, TMAGENTA, TYELLOW, - TFIXED, TSANS, TSERIF, TASINH, - TACOSH, TATANH, TACOTH, TACOT, TEXP, + TUOPER, TBOPER, TFIXED, TSANS, TSERIF, TCDOT, TODOT, TLESLANT, TGESLANT, TNSUBSET, TNSUPSET, TNSUBSETEQ, TNSUPSETEQ, TPARTIAL, TNEG, TNI, TBACKEPSILON, TALEPH, TIM, TRE, @@ -96,13 +89,22 @@ enum SmTokenType TLAMBDABAR, TLEFTARROW, TRIGHTARROW, TUPARROW, TDOWNARROW, TDIVIDES, TSETN, TSETZ, TSETQ, TSETR, TSETC, TWIDEVEC, TWIDEHARPOON, TWIDETILDE, - TWIDEHAT, TWIDESLASH, TWIDEBACKSLASH, TLDBRACKET, TRDBRACKET, TNOSPACE, TUNKNOWN, TPRECEDES, TSUCCEEDS, TPRECEDESEQUAL, TSUCCEEDSEQUAL, - TPRECEDESEQUIV, TSUCCEEDSEQUIV, TNOTPRECEDES, TNOTSUCCEEDS, TSILVER, - TGRAY, TMAROON, TPURPLE, TLIME, TOLIVE, - TNAVY, TTEAL, TAQUA, TFUCHSIA, TINTD, - TRGB, TLAPLACE, TFOURIER + TPRECEDESEQUIV, TSUCCEEDSEQUIV, TNOTPRECEDES, TNOTSUCCEEDS, THARPOON, + TINTD, TLAPLACE, TFOURIER, TTOWARD, TWIDEHAT, + // Function + TFUNC, TLN, TLOG, TEXP, // Exp - Log + TSIN, TCOS, TTAN, TCOT, // Trigo + TSINH, TCOSH, TTANH, TCOTH, // Trigo hyperbolic + TASIN, TACOS, TATAN, TACOT, // Arctrigo + TASINH, TACOSH, TATANH, TACOTH, // Arctrigo hyperbolic + // Color + TRGB, TRGBA, THEX, + TAQUA, TBLACK, TBLUE, TCYAN, TFUCHSIA, + TGRAY, TGREEN, TLIME, TMAGENTA, TMAROON, + TNAVY, TOLIVE, TPURPLE, TRED, TSILVER, + TTEAL, TWHITE, TYELLOW }; struct SmToken diff --git a/starmath/source/ElementsDockingWindow.cxx b/starmath/source/ElementsDockingWindow.cxx index 516f424f0107..053c7e04dc06 100644 --- a/starmath/source/ElementsDockingWindow.cxx +++ b/starmath/source/ElementsDockingWindow.cxx @@ -189,7 +189,8 @@ const SmElementDescr SmElementsControl::m_aAttributesList[] = {RID_COLORX_LIME, RID_COLORX_LIME_HELP}, {RID_COLORX_MAROON, RID_COLORX_MAROON_HELP}, {RID_COLORX_NAVY, RID_COLORX_NAVY_HELP}, {RID_COLORX_OLIVE, RID_COLORX_OLIVE_HELP}, {RID_COLORX_PURPLE, RID_COLORX_PURPLE_HELP}, {RID_COLORX_SILVER, RID_COLORX_SILVER_HELP}, - {RID_COLORX_TEAL, RID_COLORX_TEAL_HELP},{RID_COLORX_RGB, RID_COLORX_RGB_HELP} + {RID_COLORX_TEAL, RID_COLORX_TEAL_HELP},{RID_COLORX_RGB, RID_COLORX_RGB_HELP}, + {RID_COLORX_HEX, RID_COLORX_HEX_HELP} }; const SmElementDescr SmElementsControl::m_aBracketsList[] = @@ -924,6 +925,10 @@ void SmElementsControl::addElements(const SmElementDescr aElementsArray[], sal_u addElement(aParser, "color teal { \"" + SmResId(STR_TEAL) + "\" }", aElement, SmResId(pElementHelp)); else if (aElement == RID_COLORX_RGB) addElement(aParser, "color rgb 0 0 0 { \"" + SmResId(STR_RGB) + "\" }", aElement, SmResId(pElementHelp)); + else if (aElement == RID_COLORX_RGBA) + addElement(aParser, "color rgba 0 0 0 0 { \"" + SmResId(STR_RGBA) + "\" }", aElement, SmResId(pElementHelp)); + else if (aElement == RID_COLORX_HEX) + addElement(aParser, "color hex 000000 { \"" + SmResId(STR_HEX) + "\" }", aElement, SmResId(pElementHelp)); else if (aElement == RID_ALIGNLX) addElement(aParser, "\"" + SmResId(STR_ALIGN_LEFT) + "\"", aElement, SmResId(pElementHelp)); else if (aElement == RID_ALIGNCX) diff --git a/starmath/source/node.cxx b/starmath/source/node.cxx index e252b83ee308..957c91cb33c6 100644 --- a/starmath/source/node.cxx +++ b/starmath/source/node.cxx @@ -1607,8 +1607,7 @@ void SmFontNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat) { SmNode *pNode = GetSubNode(1); assert(pNode); - sal_Int32 nc; - Color col_perso_rgb_color = COL_AUTO; + sal_uInt32 nc; switch (GetToken().eType) { case TSIZE : @@ -1646,13 +1645,10 @@ void SmFontNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat) case TAQUA : SetColor(COL_LIGHTCYAN); break; case TFUCHSIA : SetColor(COL_LIGHTMAGENTA); break; case TRGB : - nc = GetToken().aText.toInt32(); - col_perso_rgb_color.SetBlue(nc % 256); - nc /= 256; - col_perso_rgb_color.SetGreen(nc % 256); - nc /= 256; - col_perso_rgb_color.SetRed(nc % 256); - SetColor(col_perso_rgb_color); + case TRGBA : + case THEX : + nc = GetToken().aText.toUInt32(); + SetColor(Color(nc)); break; default: @@ -1855,28 +1851,13 @@ void SmTextNode::GetAccessibleText( OUStringBuffer &rText ) const void SmTextNode::AdjustFontDesc() { - if (GetToken().eType == TTEXT) - mnFontDesc = FNT_TEXT; - else if(GetToken().eType == TFUNC) - mnFontDesc = FNT_FUNCTION; + if (GetToken().nGroup == TG::Function) mnFontDesc = FNT_FUNCTION; + else if (GetToken().eType == TTEXT) mnFontDesc = FNT_TEXT; else { - const SmTokenTableEntry *pEntry = SmParser::GetTokenTableEntry( maText ); - if (pEntry && pEntry->nGroup == TG::Function) { - GetToken().eType = pEntry->eType; - mnFontDesc = FNT_FUNCTION; - } else { - sal_Unicode firstChar = maText[0]; - if( ('0' <= firstChar && firstChar <= '9') || firstChar == '.' || firstChar == ',') { - mnFontDesc = FNT_NUMBER; - GetToken().eType = TNUMBER; - } else if (maText.getLength() > 1) { - mnFontDesc = FNT_VARIABLE; - GetToken().eType = TIDENT; - } else { - mnFontDesc = FNT_VARIABLE; - GetToken().eType = TCHARACTER; - } - } + sal_Unicode firstChar = maText[0]; + if( ('0' <= firstChar && firstChar <= '9') || firstChar == '.' || firstChar == ',') + mnFontDesc = FNT_NUMBER; + else mnFontDesc = FNT_VARIABLE; } } diff --git a/starmath/source/parse.cxx b/starmath/source/parse.cxx index a5872f9e9118..6d7e1891b762 100644 --- a/starmath/source/parse.cxx +++ b/starmath/source/parse.cxx @@ -78,7 +78,6 @@ const SmTokenTableEntry aTokenTable[] = { "alignt", TALIGNC, '\0', TG::Align, 0}, { "and", TAND, MS_AND, TG::Product, 0}, { "approx", TAPPROX, MS_APPROX, TG::Relation, 0}, - { "aqua", TAQUA, '\0', TG::Color, 0}, { "arccos", TACOS, '\0', TG::Function, 5}, { "arccot", TACOT, '\0', TG::Function, 5}, { "arcosh", TACOSH, '\0', TG::Function, 5 }, @@ -90,8 +89,6 @@ const SmTokenTableEntry aTokenTable[] = { "backepsilon" , TBACKEPSILON, MS_BACKEPSILON, TG::Standalone, 5}, { "bar", TBAR, MS_BAR, TG::Attribute, 5}, { "binom", TBINOM, '\0', TG::NONE, 5 }, - { "black", TBLACK, '\0', TG::Color, 0}, - { "blue", TBLUE, '\0', TG::Color, 0}, { "bold", TBOLD, '\0', TG::FontAttr, 5}, { "boper", TBOPER, '\0', TG::Product, 0}, { "breve", TBREVE, MS_BREVE, TG::Attribute, 5}, @@ -108,7 +105,6 @@ const SmTokenTableEntry aTokenTable[] = { "coth", TCOTH, '\0', TG::Function, 5}, { "csub", TCSUB, '\0', TG::Power, 0}, { "csup", TCSUP, '\0', TG::Power, 0}, - { "cyan", TCYAN, '\0', TG::Color, 0}, { "dddot", TDDDOT, MS_DDDOT, TG::Attribute, 5}, { "ddot", TDDOT, MS_DDOT, TG::Attribute, 5}, { "def", TDEF, MS_DEF, TG::Relation, 0}, @@ -135,14 +131,11 @@ const SmTokenTableEntry aTokenTable[] = { "forall", TFORALL, MS_FORALL, TG::Standalone, 5}, { "fourier", TFOURIER, MS_FOURIER, TG::Standalone, 5}, { "from", TFROM, '\0', TG::Limit, 0}, - { "fuchsia", TFUCHSIA, '\0', TG::Color, 0}, { "func", TFUNC, '\0', TG::Function, 5}, { "ge", TGE, MS_GE, TG::Relation, 0}, { "geslant", TGESLANT, MS_GESLANT, TG::Relation, 0 }, { "gg", TGG, MS_GG, TG::Relation, 0}, { "grave", TGRAVE, MS_GRAVE, TG::Attribute, 5}, - { "gray", TGRAY, '\0', TG::Color, 0}, - { "green", TGREEN, '\0', TG::Color, 0}, { "gt", TGT, MS_GT, TG::Relation, 0}, { "harpoon", THARPOON, MS_HARPOON, TG::Attribute, 5}, { "hat", THAT, MS_HAT, TG::Attribute, 5}, @@ -171,7 +164,6 @@ const SmTokenTableEntry aTokenTable[] = { "leslant", TLESLANT, MS_LESLANT, TG::Relation, 0 }, { "lfloor", TLFLOOR, MS_LFLOOR, TG::LBrace, 5}, { "lim", TLIM, '\0', TG::Oper, 5}, - { "lime", TLIME, '\0', TG::Color, 0}, { "liminf", TLIMINF, '\0', TG::Oper, 5}, { "limsup", TLIMSUP, '\0', TG::Oper, 5}, { "lint", TLINT, MS_LINT, TG::Oper, 5}, @@ -184,13 +176,10 @@ const SmTokenTableEntry aTokenTable[] = { "lsub", TLSUB, '\0', TG::Power, 0}, { "lsup", TLSUP, '\0', TG::Power, 0}, { "lt", TLT, MS_LT, TG::Relation, 0}, - { "magenta", TMAGENTA, '\0', TG::Color, 0}, - { "maroon", TMAROON, '\0', TG::Color, 0}, { "matrix", TMATRIX, '\0', TG::NONE, 5}, { "minusplus", TMINUSPLUS, MS_MINUSPLUS, TG::UnOper | TG::Sum, 5}, { "mline", TMLINE, MS_VERTLINE, TG::NONE, 0}, //! not in TG::RBrace, Level 0 { "nabla", TNABLA, MS_NABLA, TG::Standalone, 5}, - { "navy", TNAVY, '\0', TG::Color, 0}, { "nbold", TNBOLD, '\0', TG::FontAttr, 5}, { "ndivides", TNDIVIDES, MS_NDIVIDES, TG::Relation, 0}, { "neg", TNEG, MS_NEG, TG::UnOper, 5 }, @@ -211,7 +200,6 @@ const SmTokenTableEntry aTokenTable[] = { "nsupseteq", TNSUPSETEQ, MS_NSUPSETEQ, TG::Relation, 0 }, { "odivide", TODIVIDE, MS_ODIVIDE, TG::Product, 0}, { "odot", TODOT, MS_ODOT, TG::Product, 0}, - { "olive", TOLIVE, '\0', TG::Color, 0}, { "ominus", TOMINUS, MS_OMINUS, TG::Sum, 0}, { "oper", TOPER, '\0', TG::Oper, 5}, { "oplus", TOPLUS, MS_OPLUS, TG::Sum, 0}, @@ -232,16 +220,13 @@ const SmTokenTableEntry aTokenTable[] = { "precsim", TPRECEDESEQUIV, MS_PRECEDESEQUIV, TG::Relation, 0 }, { "prod", TPROD, MS_PROD, TG::Oper, 5}, { "prop", TPROP, MS_PROP, TG::Relation, 0}, - { "purple", TPURPLE, '\0', TG::Color, 0}, { "rangle", TRANGLE, MS_RMATHANGLE, TG::RBrace, 0}, //! 0 to terminate expression { "rbrace", TRBRACE, MS_RBRACE, TG::RBrace, 0}, { "rceil", TRCEIL, MS_RCEIL, TG::RBrace, 0}, { "rdbracket", TRDBRACKET, MS_RDBRACKET, TG::RBrace, 0}, { "rdline", TRDLINE, MS_DVERTLINE, TG::RBrace, 0}, { "re" , TRE, MS_RE, TG::Standalone, 5 }, - { "red", TRED, '\0', TG::Color, 0}, { "rfloor", TRFLOOR, MS_RFLOOR, TG::RBrace, 0}, //! 0 to terminate expression - { "rgb", TRGB, '\0', TG::Color, 0}, { "right", TRIGHT, '\0', TG::NONE, 0}, { "rightarrow" , TRIGHTARROW, MS_RIGHTARROW, TG::Standalone, 5}, { "rline", TRLINE, MS_VERTLINE, TG::RBrace, 0}, //! 0 to terminate expression @@ -255,7 +240,6 @@ const SmTokenTableEntry aTokenTable[] = { "setQ" , TSETQ, MS_SETQ, TG::Standalone, 5}, { "setR" , TSETR, MS_SETR, TG::Standalone, 5}, { "setZ" , TSETZ, MS_SETZ, TG::Standalone, 5}, - { "silver", TSILVER, '\0', TG::Color, 0}, { "sim", TSIM, MS_SIM, TG::Relation, 0}, { "simeq", TSIMEQ, MS_SIMEQ, TG::Relation, 0}, { "sin", TSIN, '\0', TG::Function, 5}, @@ -276,7 +260,6 @@ const SmTokenTableEntry aTokenTable[] = { "supseteq", TSUPSETEQ, MS_SUPSETEQ, TG::Relation, 0}, { "tan", TTAN, '\0', TG::Function, 5}, { "tanh", TTANH, '\0', TG::Function, 5}, - { "teal", TTEAL, '\0', TG::Color, 0}, { "tilde", TTILDE, MS_TILDE, TG::Attribute, 5}, { "times", TTIMES, MS_TIMES, TG::Product, 0}, { "to", TTO, '\0', TG::Limit, 0}, @@ -289,59 +272,103 @@ const SmTokenTableEntry aTokenTable[] = { "uoper", TUOPER, '\0', TG::UnOper, 5}, { "uparrow" , TUPARROW, MS_UPARROW, TG::Standalone, 5}, { "vec", TVEC, MS_VEC, TG::Attribute, 5}, - { "white", TWHITE, '\0', TG::Color, 0}, { "widebslash", TWIDEBACKSLASH, MS_BACKSLASH, TG::Product, 0 }, { "wideharpoon", TWIDEHARPOON, MS_HARPOON, TG::Attribute, 5}, { "widehat", TWIDEHAT, MS_HAT, TG::Attribute, 5}, { "wideslash", TWIDESLASH, MS_SLASH, TG::Product, 0 }, { "widetilde", TWIDETILDE, MS_TILDE, TG::Attribute, 5}, { "widevec", TWIDEVEC, MS_VEC, TG::Attribute, 5}, - { "wp" , TWP, MS_WP, TG::Standalone, 5}, - { "yellow", TYELLOW, '\0', TG::Color, 0} + { "wp" , TWP, MS_WP, TG::Standalone, 5} }; -//Checks if keyword is in the list by SmTokenTableEntry. -#if !defined NDEBUG -static bool sortCompare(const SmTokenTableEntry & lhs, const SmTokenTableEntry & rhs) +//Definition of color keywords +const SmTokenTableEntry aColorTokenTable[] = { - return OUString::createFromAscii(lhs.pIdent).compareToIgnoreAsciiCase(OUString::createFromAscii(rhs.pIdent)) < 0; -} -#endif + { "aqua", TAQUA, '\0', TG::Color, 0}, + { "black", TBLACK, '\0', TG::Color, 0}, + { "blue", TBLUE, '\0', TG::Color, 0}, + { "cyan", TCYAN, '\0', TG::Color, 0}, + { "fuchsia", TFUCHSIA, '\0', TG::Color, 0}, + { "gray", TGRAY, '\0', TG::Color, 0}, + { "green", TGREEN, '\0', TG::Color, 0}, + { "hex" , THEX, '\0', TG::Color, 0}, + { "lime", TLIME, '\0', TG::Color, 0}, + { "magenta", TMAGENTA, '\0', TG::Color, 0}, + { "maroon", TMAROON, '\0', TG::Color, 0}, + { "navy", TNAVY, '\0', TG::Color, 0}, + { "olive", TOLIVE, '\0', TG::Color, 0}, + { "purple", TPURPLE, '\0', TG::Color, 0}, + { "red", TRED, '\0', TG::Color, 0}, + { "rgb", TRGB, '\0', TG::Color, 0}, + //{ "rgba", TRGBA, '\0', TG::Color, 0}, + { "silver", TSILVER, '\0', TG::Color, 0}, + { "teal", TTEAL, '\0', TG::Color, 0}, + { "white", TWHITE, '\0', TG::Color, 0}, + { "yellow", TYELLOW, '\0', TG::Color, 0} +}; + +// First character may be any alphabetic +const sal_Int32 coStartFlags = KParseTokens::ANY_LETTER | KParseTokens::IGNORE_LEADING_WS; + +// Continuing characters may be any alphabetic +const sal_Int32 coContFlags = (coStartFlags & ~KParseTokens::IGNORE_LEADING_WS) + | KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING; +// First character for numbers, may be any numeric or dot +const sal_Int32 coNumStartFlags = KParseTokens::ASC_DIGIT | KParseTokens::ASC_DOT + | KParseTokens::IGNORE_LEADING_WS; +// Continuing characters for numbers, may be any numeric or dot or comma. +// tdf#127873: additionally accept ',' comma group separator as too many +// existing documents unwittingly may have used that as decimal separator +// in such locales (though it never was as this is always the en-US locale +// and the group separator is only parsed away). +const sal_Int32 coNumContFlags = (coNumStartFlags & ~KParseTokens::IGNORE_LEADING_WS) + | KParseTokens::GROUP_SEPARATOR_IN_NUMBER; +// First character for numbers hexadecimal +const sal_Int32 coNum16StartFlags = KParseTokens::ASC_DIGIT | KParseTokens::ASC_UPALPHA + | KParseTokens::IGNORE_LEADING_WS; + +// Continuing characters for numbers hexadecimal +const sal_Int32 coNum16ContFlags = (coNum16StartFlags & ~KParseTokens::IGNORE_LEADING_WS); +// user-defined char continuing characters may be any alphanumeric or dot. +const sal_Int32 coUserDefinedCharContFlags = KParseTokens::ANY_LETTER_OR_NUMBER + | KParseTokens::ASC_DOT + | KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING; //Checks if keyword is in the list. -static bool findCompare(const SmTokenTableEntry & lhs, const OUString & s) +static inline bool findCompare(const SmTokenTableEntry & lhs, const OUString & s) { return s.compareToIgnoreAsciiCaseAscii(lhs.pIdent) > 0; } //Returns the SmTokenTableEntry for a keyword -const SmTokenTableEntry * SmParser::GetTokenTableEntry( const OUString &rName ) +static const SmTokenTableEntry * GetTokenTableEntry( const OUString &rName ) { - static bool bSortKeyWords = false; // Flag: RTF-token table has been sorted. - if( !bSortKeyWords ) //First time sorts it. - { - assert( std::is_sorted( std::begin(aTokenTable), std::end(aTokenTable), sortCompare ) ); - bSortKeyWords = true; - } - if (rName.isEmpty())return nullptr; //avoid null pointer exceptions - //Looks for the first keyword after or equal to rName in alphabetical order. - auto findIter = std::lower_bound( std::begin(aTokenTable), std::end(aTokenTable), rName, findCompare ); - if ( findIter != std::end(aTokenTable) && rName.equalsIgnoreAsciiCaseAscii( findIter->pIdent ))return &*findIter; //check is equal - + auto findIter = std::lower_bound( std::begin(aTokenTable), + std::end(aTokenTable), rName, findCompare ); + if ( findIter != std::end(aTokenTable) && rName.equalsIgnoreAsciiCaseAscii( findIter->pIdent )) + return &*findIter; //check is equal return nullptr; //not found } -namespace { - -bool IsDelimiter( const OUString &rTxt, sal_Int32 nPos ) - // returns 'true' iff cChar is '\0' or a delimiter +//Returns the SmTokenTableEntry for a keyword +static const SmTokenTableEntry * GetColorTokenTableEntry( const OUString &rName ) { - assert(nPos <= rTxt.getLength()); //index out of range + if (rName.isEmpty())return nullptr; //avoid null pointer exceptions + //Looks for the first keyword after or equal to rName in alphabetical order. + auto findIter = std::lower_bound( std::begin(aColorTokenTable), + std::end(aColorTokenTable), rName, findCompare ); + if ( findIter != std::end(aColorTokenTable) + && rName.equalsIgnoreAsciiCaseAscii( findIter->pIdent )) + return &*findIter; //check is equal + return nullptr; //not found +} +static bool IsDelimiter( const OUString &rTxt, sal_Int32 nPos ) +{ // returns 'true' iff cChar is '\0' or a delimiter + assert(nPos <= rTxt.getLength()); //index out of range if (nPos == rTxt.getLength())return true; //This is EOF - sal_Unicode cChar = rTxt[nPos]; // check if 'cChar' is in the delimiter table @@ -364,7 +391,42 @@ bool IsDelimiter( const OUString &rTxt, sal_Int32 nPos ) nTypJp == css::i18n::UnicodeType::CONTROL); } -}//end namespace +// checks number used as arguments in Math formulas (e.g. 'size' command) +// Format: no negative numbers, must start with a digit, no exponent notation, ... +static bool lcl_IsNumber(const OUString& rText) +{ + bool bPoint = false; + const sal_Unicode* pBuffer = rText.getStr(); + for(sal_Int32 nPos = 0; nPos < rText.getLength(); nPos++, pBuffer++) + { + const sal_Unicode cChar = *pBuffer; + if(cChar == '.') + { + if(bPoint) return false; + else bPoint = true; + } + else if ( !rtl::isAsciiDigit( cChar ) ) return false; + } + return true; +} +// checks number used as arguments in Math formulas (e.g. 'size' command) +// Format: no negative numbers, must start with a digit, no exponent notation, ... +static bool lcl_IsNotWholeNumber(const OUString& rText) +{ + const sal_Unicode* pBuffer = rText.getStr(); + for(sal_Int32 nPos = 0; nPos < rText.getLength(); nPos++, pBuffer++) + if ( !rtl::isAsciiDigit( *pBuffer ) ) return true; + return false; +} +// checks hex number used as arguments in Math formulas (e.g. 'hex' command) +// Format: no negative numbers, must start with a digit, no exponent notation, ... +static bool lcl_IsNotWholeNumber16(const OUString& rText) +{ + const sal_Unicode* pBuffer = rText.getStr(); + for(sal_Int32 nPos = 0; nPos < rText.getLength(); nPos++, pBuffer++) + if ( !rtl::isAsciiCanonicHexDigit( *pBuffer ) ) return true; + return false; +} //Text replace onto m_aBufferString void SmParser::Replace( sal_Int32 nPos, sal_Int32 nLen, const OUString &rText ) @@ -379,36 +441,6 @@ void SmParser::Replace( sal_Int32 nPos, sal_Int32 nLen, const OUString &rText ) void SmParser::NextToken() //Central part of the parser { - // First character may be any alphabetic - static const sal_Int32 coStartFlags = - KParseTokens::ANY_LETTER | - KParseTokens::IGNORE_LEADING_WS; - - // Continuing characters may be any alphabetic - static const sal_Int32 coContFlags = - (coStartFlags & ~KParseTokens::IGNORE_LEADING_WS) - | KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING; - - // user-defined char continuing characters may be any alphanumeric or dot. - static const sal_Int32 coUserDefinedCharContFlags = - KParseTokens::ANY_LETTER_OR_NUMBER | - KParseTokens::ASC_DOT | - KParseTokens::TWO_DOUBLE_QUOTES_BREAK_STRING; - - // First character for numbers, may be any numeric or dot - static const sal_Int32 coNumStartFlags = - KParseTokens::ASC_DIGIT | - KParseTokens::ASC_DOT | - KParseTokens::IGNORE_LEADING_WS; - - // Continuing characters for numbers, may be any numeric or dot. - // tdf#127873: additionally accept ',' comma group separator as too many - // existing documents unwittingly may have used that as decimal separator - // in such locales (though it never was as this is always the en-US locale - // and the group separator is only parsed away). - static const sal_Int32 coNumContFlags = - (coNumStartFlags & ~KParseTokens::IGNORE_LEADING_WS) | - KParseTokens::GROUP_SEPARATOR_IN_NUMBER; sal_Int32 nBufLen = m_aBufferString.getLength(); ParseResult aRes; @@ -979,6 +1011,186 @@ void SmParser::NextToken() //Central part of the parser m_nBufferIndex = aRes.EndPos; } +void SmParser::NextTokenColor() +{ + + sal_Int32 nBufLen = m_aBufferString.getLength(); + ParseResult aRes; + sal_Int32 nRealStart; + bool bCont; + + do + { + // skip white spaces + while (UnicodeType::SPACE_SEPARATOR == + m_pSysCC->getType( m_aBufferString, m_nBufferIndex )) + ++m_nBufferIndex; + //parse, there are few options, so less strict. + aRes = m_pSysCC->parseAnyToken(m_aBufferString, m_nBufferIndex, + coStartFlags, "", coContFlags, ""); + nRealStart = m_nBufferIndex + aRes.LeadingWhiteSpace; + m_nBufferIndex = nRealStart; + bCont = false; + if ( aRes.TokenType == 0 && + nRealStart < nBufLen && + '\n' == m_aBufferString[ nRealStart ] ) + { + // keep data needed for tokens row and col entry up to date + ++m_nRow; + m_nBufferIndex = m_nColOff = nRealStart + 1; + bCont = true; + } + else if (aRes.TokenType & KParseType::ONE_SINGLE_CHAR) + { + if (nRealStart + 2 <= nBufLen && m_aBufferString.match("%%", nRealStart)) + { + //SkipComment + m_nBufferIndex = nRealStart + 2; + while (m_nBufferIndex < nBufLen && + '\n' != m_aBufferString[ m_nBufferIndex ]) + ++m_nBufferIndex; + bCont = true; + } + } + } while (bCont); + + // set index of current token + m_nTokenIndex = m_nBufferIndex; + m_aCurToken.nRow = m_nRow; + m_aCurToken.nCol = nRealStart - m_nColOff + 1; + if (nRealStart >= nBufLen) m_aCurToken.eType = TEND; + else if (aRes.TokenType & KParseType::IDENTNAME) + { + sal_Int32 n = aRes.EndPos - nRealStart; + assert(n >= 0); + OUString aName( m_aBufferString.copy( nRealStart, n ) ); + const SmTokenTableEntry *pEntry = GetColorTokenTableEntry( aName ); + if (pEntry) + { + m_aCurToken.eType = pEntry->eType; + m_aCurToken.cMathChar = pEntry->cMathChar; + m_aCurToken.nGroup = pEntry->nGroup; + m_aCurToken.nLevel = pEntry->nLevel; + m_aCurToken.aText = OUString::createFromAscii( pEntry->pIdent ); + } + else m_aCurToken.eType = TNONE; + } + else m_aCurToken.eType = TNONE; + if (TEND != m_aCurToken.eType) m_nBufferIndex = aRes.EndPos; +} + +void SmParser::NextTokenFontSize() +{ + + sal_Int32 nBufLen = m_aBufferString.getLength(); + ParseResult aRes; + sal_Int32 nRealStart; + bool bCont; + bool hex = false; + + do + { + // skip white spaces + while (UnicodeType::SPACE_SEPARATOR == + m_pSysCC->getType( m_aBufferString, m_nBufferIndex )) + ++m_nBufferIndex; + //hexadecimal parser + aRes = m_pSysCC->parseAnyToken(m_aBufferString, m_nBufferIndex, + coNum16StartFlags, ".", coNum16ContFlags, ".,"); + if (aRes.TokenType == 0) + { + // Try again with the default token parsing. + aRes = m_pSysCC->parseAnyToken(m_aBufferString, m_nBufferIndex, + coStartFlags, "", coContFlags, ""); + } + else hex = true; + nRealStart = m_nBufferIndex + aRes.LeadingWhiteSpace; + m_nBufferIndex = nRealStart; + bCont = false; + if ( aRes.TokenType == 0 && + nRealStart < nBufLen && + '\n' == m_aBufferString[ nRealStart ] ) + { + // keep data needed for tokens row and col entry up to date + ++m_nRow; + m_nBufferIndex = m_nColOff = nRealStart + 1; + bCont = true; + } + else if (aRes.TokenType & KParseType::ONE_SINGLE_CHAR) + { + if (nRealStart + 2 <= nBufLen && m_aBufferString.match("%%", nRealStart)) + { + //SkipComment + m_nBufferIndex = nRealStart + 2; + while (m_nBufferIndex < nBufLen && + '\n' != m_aBufferString[ m_nBufferIndex ]) + ++m_nBufferIndex; + bCont = true; + } + } + } while (bCont); + + // set index of current token + m_nTokenIndex = m_nBufferIndex; + m_aCurToken.nRow = m_nRow; + m_aCurToken.nCol = nRealStart - m_nColOff + 1; + if (nRealStart >= nBufLen) m_aCurToken.eType = TEND; + else if (aRes.TokenType & KParseType::ONE_SINGLE_CHAR) + { + if ( aRes.EndPos - nRealStart == 1 ) + { + switch ( m_aBufferString[ nRealStart ] ) + { + case '*': + m_aCurToken.eType = TMULTIPLY; + m_aCurToken.cMathChar = MS_MULTIPLY; + m_aCurToken.nGroup = TG::Product; + m_aCurToken.nLevel = 0; + m_aCurToken.aText = "*"; + break; + case '+': + m_aCurToken.eType = TPLUS; + m_aCurToken.cMathChar = MS_PLUS; + m_aCurToken.nGroup = TG::UnOper | TG::Sum; + m_aCurToken.nLevel = 5; + m_aCurToken.aText = "+"; + break; + case '-': + m_aCurToken.eType = TMINUS; + m_aCurToken.cMathChar = MS_MINUS; + m_aCurToken.nGroup = TG::UnOper | TG::Sum; + m_aCurToken.nLevel = 5; + m_aCurToken.aText = "-"; + break; + case '/': + m_aCurToken.eType = TDIVIDEBY; + m_aCurToken.cMathChar = MS_SLASH; + m_aCurToken.nGroup = TG::Product; + m_aCurToken.nLevel = 0; + m_aCurToken.aText = "/"; + break; + default: + m_aCurToken.eType = TNONE; + break; + } + } + else m_aCurToken.eType = TNONE; + } + else if(hex) + { + assert(aRes.EndPos > 0); + sal_Int32 n = aRes.EndPos - nRealStart; + assert(n >= 0); + m_aCurToken.eType = THEX; + m_aCurToken.cMathChar = '\0'; + m_aCurToken.nGroup = TG::NONE; + m_aCurToken.nLevel = 5; + m_aCurToken.aText = m_aBufferString.copy( nRealStart, n ); + } + else m_aCurToken.eType = TNONE; + if (TEND != m_aCurToken.eType) m_nBufferIndex = aRes.EndPos; +} + namespace { SmNodeArray buildNodeArray(std::vector<std::unique_ptr<SmNode>>& rSubNodes) @@ -991,6 +1203,7 @@ namespace } //end namespace // grammar +/*************************************************************************************************/ std::unique_ptr<SmTableNode> SmParser::DoTable() { @@ -1537,15 +1750,20 @@ std::unique_ptr<SmNode> SmParser::DoTerm(bool bGroupNumberIdent) case TMATRIX: return DoMatrix(); + case THEX: + NextTokenFontSize(); + if( m_aCurToken.eType == THEX ) + { + auto pTextNode = std::make_unique<SmTextNode>(m_aCurToken, FNT_NUMBER ); + NextToken(); + return pTextNode; + } + else return DoError(SmParseError::NumberExpected); default: - if (TokenInGroup(TG::LBrace)) - return DoBrace(); - if (TokenInGroup(TG::Oper)) - return DoOperator(); - if (TokenInGroup(TG::UnOper)) - return DoUnOper(); - if ( TokenInGroup(TG::Attribute) || - TokenInGroup(TG::FontAttr) ) + if (TokenInGroup(TG::LBrace)) return DoBrace(); + if (TokenInGroup(TG::Oper)) return DoOperator(); + if (TokenInGroup(TG::UnOper)) return DoUnOper(); + if ( TokenInGroup(TG::Attribute) || TokenInGroup(TG::FontAttr) ) { std::stack<std::unique_ptr<SmStructureNode>> aStack; bool bIsAttr; @@ -1862,51 +2080,76 @@ std::unique_ptr<SmStructureNode> SmParser::DoFontAttribut() std::unique_ptr<SmStructureNode> SmParser::DoColor() { DepthProtect aDepthGuard(m_nParseDepth); - if (aDepthGuard.TooDeep()) - throw std::range_error("parser depth limit"); + if (aDepthGuard.TooDeep()) throw std::range_error("parser depth limit"); assert(m_aCurToken.eType == TCOLOR); - - std::unique_ptr<SmStructureNode> xNode; - // last color rules, get that one + NextTokenColor(); SmToken aToken; - do - { - - NextToken(); - if (TokenInGroup(TG::Color)) + if (TokenInGroup(TG::Color)) + { + aToken = m_aCurToken; + if( m_aCurToken.eType == TRGB ) //loads r, g and b { - aToken = m_aCurToken; - if(m_aCurToken.eType==TRGB){ - SmToken r,g,b; - sal_Int32 nr, ng, nb, nc; - NextToken(); - if(m_aCurToken.eType!=TNUMBER)return DoError(SmParseError::ColorExpected); - r = m_aCurToken; - NextToken(); - if(m_aCurToken.eType!=TNUMBER)return DoError(SmParseError::ColorExpected); - g = m_aCurToken; - NextToken(); - if(m_aCurToken.eType!=TNUMBER)return DoError(SmParseError::ColorExpected); - b = m_aCurToken; - nr = r.aText.toInt32(); - if( nr < 0 || nr > 255 )return DoError(SmParseError::ColorExpected); - ng = g.aText.toInt32(); - if( ng < 0 || ng > 255 )return DoError(SmParseError::ColorExpected); - nb = b.aText.toInt32(); - if( nb < 0 || nb > 255 )return DoError(SmParseError::ColorExpected); - nc = nb + 256 * ( ng + nr*256 ); - aToken.aText = OUString::number(nc); - } - NextToken(); + sal_uInt32 nr, ng, nb, nc; + NextTokenFontSize(); + if( lcl_IsNotWholeNumber(m_aCurToken.aText) ) + return DoError(SmParseError::ColorExpected); + nr = m_aCurToken.aText.toUInt32(); + if( nr > 255 )return DoError(SmParseError::ColorExpected); + NextTokenFontSize(); + if( lcl_IsNotWholeNumber(m_aCurToken.aText) ) + return DoError(SmParseError::ColorExpected); + ng = m_aCurToken.aText.toUInt32(); + if( ng > 255 )return DoError(SmParseError::ColorExpected); + NextTokenFontSize(); + if( lcl_IsNotWholeNumber(m_aCurToken.aText) ) + return DoError(SmParseError::ColorExpected); + nb = m_aCurToken.aText.toUInt32(); + if( nb > 255 )return DoError(SmParseError::ColorExpected); + nc = nb | ng << 8 | nr << 16 | sal_uInt32(0) << 24; + aToken.aText = OUString::number(nc); } - else + else if( m_aCurToken.eType == TRGBA ) //loads r, g and b + { + sal_uInt32 nr, na, ng, nb, nc; + NextTokenFontSize(); + if( lcl_IsNotWholeNumber(m_aCurToken.aText) ) + return DoError(SmParseError::ColorExpected); + nr = m_aCurToken.aText.toUInt32(); + if( nr > 255 )return DoError(SmParseError::ColorExpected); + NextTokenFontSize(); + if( lcl_IsNotWholeNumber(m_aCurToken.aText) ) + return DoError(SmParseError::ColorExpected); + ng = m_aCurToken.aText.toUInt32(); + if( ng > 255 )return DoError(SmParseError::ColorExpected); + NextTokenFontSize(); + if( lcl_IsNotWholeNumber(m_aCurToken.aText) ) + return DoError(SmParseError::ColorExpected); + nb = m_aCurToken.aText.toUInt32(); + if( nb > 255 )return DoError(SmParseError::ColorExpected); + NextTokenFontSize(); + if( lcl_IsNotWholeNumber(m_aCurToken.aText) ) + return DoError(SmParseError::ColorExpected); + na = m_aCurToken.aText.toUInt32(); + if( na > 255 )return DoError(SmParseError::ColorExpected); + nc = nb | ng << 8 | nr << 16 | na << 24; + aToken.aText = OUString::number(nc); + } + else if( m_aCurToken.eType == THEX ) //loads hex code { - return DoError(SmParseError::ColorExpected); + sal_uInt32 nc; + NextTokenFontSize(); + if( lcl_IsNotWholeNumber16(m_aCurToken.aText) ) + return DoError(SmParseError::ColorExpected); + nc = m_aCurToken.aText.toUInt32(16); + aToken.aText = OUString::number(nc); } - } while (m_aCurToken.eType == TCOLOR); + NextToken(); + } + else return DoError(SmParseError::ColorExpected); + std::unique_ptr<SmStructureNode> xNode; xNode.reset(new SmFontNode(aToken)); return xNode; } @@ -1939,45 +2182,17 @@ std::unique_ptr<SmStructureNode> SmParser::DoFont() return xNode; } - -// gets number used as arguments in Math formulas (e.g. 'size' command) -// Format: no negative numbers, must start with a digit, no exponent notation, ... -static bool lcl_IsNumber(const OUString& rText) -{ - bool bPoint = false; - const sal_Unicode* pBuffer = rText.getStr(); - for(sal_Int32 nPos = 0; nPos < rText.getLength(); nPos++, pBuffer++) - { - const sal_Unicode cChar = *pBuffer; - if(cChar == '.') - { - if(bPoint) - return false; - else - bPoint = true; - } - else if ( !rtl::isAsciiDigit( cChar ) ) - return false; - } - return true; -} - std::unique_ptr<SmStructureNode> SmParser::DoFontSize() { DepthProtect aDepthGuard(m_nParseDepth); - if (aDepthGuard.TooDeep()) - throw std::range_error("parser depth limit"); - - assert(m_aCurToken.eType == TSIZE); - - FontSizeType Type; + if (aDepthGuard.TooDeep()) throw std::range_error("parser depth limit"); std::unique_ptr<SmFontNode> pFontNode(new SmFontNode(m_aCurToken)); - - NextToken(); + NextTokenFontSize(); + FontSizeType Type; switch (m_aCurToken.eType) { - case TNUMBER: Type = FontSizeType::ABSOLUT; break; + case THEX: Type = FontSizeType::ABSOLUT; break; case TPLUS: Type = FontSizeType::PLUS; break; case TMINUS: Type = FontSizeType::MINUS; break; case TMULTIPLY: Type = FontSizeType::MULTIPLY; break; @@ -1989,42 +2204,32 @@ std::unique_ptr<SmStructureNode> SmParser::DoFontSize() if (Type != FontSizeType::ABSOLUT) { - NextToken(); - if (m_aCurToken.eType != TNUMBER) - return DoError(SmParseError::SizeExpected); + NextTokenFontSize(); + if (m_aCurToken.eType != THEX) return DoError(SmParseError::SizeExpected); } // get number argument Fraction aValue( 1 ); if (lcl_IsNumber( m_aCurToken.aText )) { - double fTmp = m_aCurToken.aText.toDouble(); - if (fTmp != 0.0) + aValue = m_aCurToken.aText.toDouble(); + //!! Reduce values in order to avoid numerical errors + if (aValue.GetDenominator() > 1000) { - aValue = fTmp; - - //!! keep the numerator and denominator from being too large - //!! otherwise ongoing multiplications may result in overflows - //!! (for example in SmNode::SetFontSize the font size calculated - //!! may become 0 because of this!!! Happens e.g. for ftmp = 2.9 with Linux - //!! or ftmp = 1.11111111111111111... (11/9) on every platform.) - if (aValue.GetDenominator() > 1000) + tools::Long nNum = aValue.GetNumerator(); + tools::Long nDenom = aValue.GetDenominator(); + while ( nDenom > 1000 ) //remove big denominator { - tools::Long nNum = aValue.GetNumerator(); - tools::Long nDenom = aValue.GetDenominator(); - while (nDenom > 1000) - { - nNum /= 10; - nDenom /= 10; - } - aValue = Fraction( nNum, nDenom ); + nNum /= 10; + nDenom /= 10; } + aValue = Fraction( nNum, nDenom ); } } - - NextToken(); + else return DoError(SmParseError::SizeExpected); pFontNode->SetSizeParameter(aValue, Type); + NextToken(); return pFontNode; } @@ -2169,45 +2374,16 @@ std::unique_ptr<SmBracebodyNode> SmParser::DoBracebody(bool bIsLeftRight) std::unique_ptr<SmTextNode> SmParser::DoFunction() { DepthProtect aDepthGuard(m_nParseDepth); - if (aDepthGuard.TooDeep()) - throw std::range_error("parser depth limit"); - - switch (m_aCurToken.eType) + if (aDepthGuard.TooDeep()) throw std::range_error("parser depth limit"); + if( m_aCurToken.eType == TFUNC ) { - case TFUNC: - NextToken(); // skip "FUNC"-statement - m_aCurToken.eType = TFUNC; - [[fallthrough]]; - - case TSIN : - case TCOS : - case TTAN : - case TCOT : - case TASIN : - case TACOS : - case TATAN : - case TACOT : - case TSINH : - case TCOSH : - case TTANH : - case TCOTH : - case TASINH : - case TACOSH : - case TATANH : - case TACOTH : - case TLN : - case TLOG : - case TEXP : - { - auto pNode = std::make_unique<SmTextNode>(m_aCurToken, FNT_FUNCTION); - NextToken(); - return pNode; - } - - default: - assert(false); - return nullptr; + NextToken(); // skip "FUNC"-statement + m_aCurToken.eType = TFUNC; + m_aCurToken.nGroup = TG::Function; } + auto pNode = std::make_unique<SmTextNode>(m_aCurToken, FNT_FUNCTION); + NextToken(); + return pNode; } std::unique_ptr<SmTableNode> SmParser::DoBinom() @@ -2459,6 +2635,7 @@ void SmParser::AddError(SmParseError Type, SmNode *pNode) case SmParseError::SizeExpected: pRID = RID_ERR_SIZEEXPECTED; break; case SmParseError::DoubleAlign: pRID = RID_ERR_DOUBLEALIGN; break; case SmParseError::DoubleSubsupscript: pRID = RID_ERR_DOUBLESUBSUPSCRIPT; break; + case SmParseError::NumberExpected: pRID = RID_ERR_NUMBEREXPECTED; break; default: assert(false); return; diff --git a/starmath/source/visitors.cxx b/starmath/source/visitors.cxx index 3704abc18c32..f6e030b298d7 100644 --- a/starmath/source/visitors.cxx +++ b/starmath/source/visitors.cxx @@ -2077,8 +2077,8 @@ void SmNodeToTextVisitor::Visit( SmAttributNode* pNode ) void SmNodeToTextVisitor::Visit( SmFontNode* pNode ) { - sal_Int32 nc; - sal_Int16 nr, ng, nb; + sal_uInt32 nc; + sal_uInt8 nr, ng, nb; switch ( pNode->GetToken( ).eType ) { case TBOLD: @@ -2180,7 +2180,7 @@ void SmNodeToTextVisitor::Visit( SmFontNode* pNode ) break; case TRGB: Append( "color rgb " ); - nc = pNode->GetToken().aText.toInt32(); + nc = pNode->GetToken().aText.toUInt32(); nb = nc % 256; nc /= 256; ng = nc % 256; @@ -2193,6 +2193,30 @@ void SmNodeToTextVisitor::Visit( SmFontNode* pNode ) Append(OUString::number(nb)); Separate(); break; + case TRGBA: + Append( "color rgba " ); + nc = pNode->GetToken().aText.toUInt32(); + nb = nc % 256; + nc /= 256; + ng = nc % 256; + nc /= 256; + nr = nc % 256; + nc /= 256; + Append(OUString::number(nr)); + Separate(); + Append(OUString::number(ng)); + Separate(); + Append(OUString::number(nb)); + Separate(); + Append(OUString::number(nc)); + Separate(); + break; + case THEX: + Append( "color hex " ); + nc = pNode->GetToken().aText.toUInt32(); + Append(OUString::number(nc,16)); + Separate(); + break; case TSANS: Append( "font sans " ); break; @@ -2370,6 +2394,10 @@ void SmNodeToTextVisitor::Visit( SmTextNode* pNode ) Append("func "); Append( pNode->GetToken().aText ); break; + case THEX: + Append("hex "); + Append( pNode->GetToken().aText ); + break; default: Append( pNode->GetToken().aText ); } |