summaryrefslogtreecommitdiff
path: root/starmath
diff options
context:
space:
mode:
Diffstat (limited to 'starmath')
-rw-r--r--starmath/inc/error.hxx3
-rw-r--r--starmath/inc/parse.hxx3
-rw-r--r--starmath/inc/strings.hrc5
-rw-r--r--starmath/inc/strings.hxx2
-rw-r--r--starmath/inc/token.hxx28
-rw-r--r--starmath/source/ElementsDockingWindow.cxx7
-rw-r--r--starmath/source/node.cxx41
-rw-r--r--starmath/source/parse.cxx601
-rw-r--r--starmath/source/visitors.cxx34
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 );
}