diff options
Diffstat (limited to 'glcdskin/string.c')
-rw-r--r-- | glcdskin/string.c | 155 |
1 files changed, 129 insertions, 26 deletions
diff --git a/glcdskin/string.c b/glcdskin/string.c index dc9d9dc..3966449 100644 --- a/glcdskin/string.c +++ b/glcdskin/string.c @@ -55,18 +55,23 @@ std::string tSkinToken::Token(const tSkinToken & Token) return result; } +#if 0 cSkinString::tStringList cSkinString::mStrings; +#endif cSkinString::cSkinString(cSkinObject *Parent, bool Translate) : mObject(Parent), mSkin(Parent->Skin()), mTranslate(Translate) { +#if 0 mStrings.push_back(this); +#endif } cSkinString::~cSkinString() { +#if 0 tStringList::iterator it = mStrings.begin(); for (; it != mStrings.end(); ++it) { if ((*it) == this) { @@ -74,8 +79,10 @@ cSkinString::~cSkinString() break; } } +#endif } +#if 0 void cSkinString::Reparse(void) { tStringList::iterator it = mStrings.begin(); @@ -84,6 +91,14 @@ void cSkinString::Reparse(void) (*it)->Parse((*it)->mOriginal, true); } } +#endif + + +// copied from xml.c (should be valid for parsing variable names too ...) +static bool IsTokenChar(bool start, int c) { + return isalpha(c) || c == '_' || (!start && isdigit(c)); +} + bool cSkinString::Parse(const std::string & Text, bool Translate) { @@ -93,16 +108,6 @@ bool cSkinString::Parse(const std::string & Text, bool Translate) bool inAttrib = false; int offset = 0; - if (trans[0] == '#') - { - cSkinVariable * variable = mSkin->GetVariable(trans.substr(1)); - if (variable) - { - trans = (std::string) variable->Value(); - syslog(LOG_ERR, "string variable %s", trans.c_str()); - } - } - //Dprintf("parsing: %s\n", Text.c_str()); mOriginal = Text; mText = ""; @@ -113,16 +118,39 @@ bool cSkinString::Parse(const std::string & Text, bool Translate) for (; *ptr; ++ptr) { if (inToken && *ptr == '\\') { if (*(ptr + 1) == '\0') { - syslog(LOG_ERR, "ERROR: Stray \\ in token attribute\n"); + syslog(LOG_ERR, "ERROR: graphlcd/skin/string: Stray \\ in token attribute\n"); return false; } ++ptr; continue; } + else if (*ptr == '#') { + if (inToken) { + syslog(LOG_ERR, "ERROR: graphlcd/skin/string: Unexpected '#' in token"); + return false; + } + + mText.append(last, ptr - last); + + bool isStartChar = true; + const char * varNameStart = ptr; + ptr++; + while (*ptr && IsTokenChar(isStartChar, *ptr)) { + isStartChar = false; + ptr++; + offset++; + } + // add #VARNAME# + mText.append(varNameStart, (ptr - varNameStart)); + mText.append("#"); + offset +=2; // adds two '#' -> fix offset + ptr--; // we'd be at the correct position now but the for-loop does a ++ptr -> fix it by stepping back one char + last = ptr + 1; + } else if (*ptr == '{') { if (inToken) { - syslog(LOG_ERR, "ERROR: Unexpected '{' in token"); + syslog(LOG_ERR, "ERROR: graphlcd/skin/string: Unexpected '{' in token"); return false; } @@ -132,13 +160,13 @@ bool cSkinString::Parse(const std::string & Text, bool Translate) } else if (*ptr == '}' || (inToken && *ptr == ':')) { if (!inToken) { - syslog(LOG_ERR, "ERROR: Unexpected '}' outside of token"); + syslog(LOG_ERR, "ERROR: graphlcd/skin/string: Unexpected '}' outside of token"); return false; } if (inAttrib) { if (*ptr == ':') { - syslog(LOG_ERR, "ERROR: Unexpected ':' inside of token attribute"); + syslog(LOG_ERR, "ERROR: graphlcd/skin/string: Unexpected ':' inside of token attribute"); return false; } @@ -179,12 +207,14 @@ bool cSkinString::Parse(const std::string & Text, bool Translate) { std::string tmp; tmp.assign(last, ptr - last); - tSkinToken token(mSkin->Config().GetTokenId(tmp), tmp, offset, ""); - mTokens.push_back(token); + if (tmp != "") { // ignore empty token + tSkinToken token(mSkin->Config().GetTokenId(tmp), tmp, offset, ""); + mTokens.push_back(token); + } } else { - syslog(LOG_ERR, "ERROR: Unexpected token {%.*s}", (int)(ptr - last), last); + syslog(LOG_ERR, "ERROR: graphlcd/skin/string: Unexpected token {%.*s}", (int)(ptr - last), last); return false; } @@ -201,7 +231,7 @@ bool cSkinString::Parse(const std::string & Text, bool Translate) } if (inToken) { - syslog(LOG_ERR, "ERROR: Expecting '}' in token"); + syslog(LOG_ERR, "ERROR: graphlcd/skin/string: Expecting '}' in token"); return false; } @@ -214,19 +244,92 @@ bool cSkinString::Parse(const std::string & Text, bool Translate) cType cSkinString::Evaluate(void) const { - std::string result; - int offset = 0; - if (mText.length() == 0 && mTokens.size() == 1) return mSkin->Config().GetToken(mTokens[0]); - for (uint32_t i = 0; i < mTokens.size(); ++i) { - result.append(mText.c_str() + offset, mTokens[i].Offset - offset); - result.append(mSkin->Config().GetToken(mTokens[i])); + std::string result_raw = ""; + int offset = 0; + for (uint32_t i = 0; i < mTokens.size(); i++) { + result_raw.append(mText.substr(offset, mTokens[i].Offset - offset) ); + result_raw.append(mSkin->Config().GetToken(mTokens[i])); offset = mTokens[i].Offset; } - result.append(mText.c_str() + offset); - return result; + result_raw.append(mText.c_str() + offset); + + // replace variable placeholders (#VARNAME#) with corresponding values + std::string result_trans = ""; + size_t idxstart = 0, idxend = 0; + size_t pos = 0; + while ( (idxstart=result_raw.find("#", idxstart)) != std::string::npos ) { + result_trans.append(result_raw.substr(pos, idxstart-pos)); + idxend = result_raw.find("#", idxstart+1); + if (idxend != std::string::npos) { + cSkinVariable * variable = mSkin->GetVariable(result_raw.substr(idxstart+1, idxend-idxstart-1)); + if (variable) { + std::string val = (std::string) variable->Value(); + + // if value of variable contains token definions: reparse value + if (val.find("{") != std::string::npos) { + cSkinString *result = new cSkinString(Object(), false); + if (result->Parse(val)) { + val = (std::string) result->Evaluate(); + } + delete result; + } + result_trans.append (val); + // syslog(LOG_ERR, "string variable %s", trans.c_str()); + } else { + result_trans.append (result_raw.substr(idxstart, idxend-idxstart)); // no variable found: print as raw text + } + idxstart = idxend+1; + pos = idxstart; + } else { + result_trans.append ("#"); // no closing '#' -> print # as raw text + idxstart ++; + pos = idxstart; + } + } + result_trans.append(result_raw.substr(pos)); + + // re-evaluate resulting string + if ((mText.size() > 0) && mText[0] != '#' && mObject != NULL ) { + cSkinFunction *result = new cSkinFunction(mObject); + if (result->Parse(result_trans, true)) { + std::string result_rescan = (std::string)result->Evaluate(); + if (result_rescan != "") + result_trans = result_rescan; + } + delete result; + } + + // look for $(..)$-expressions + result_raw = result_trans; + result_trans = ""; + idxstart = 0; + pos = 0; + bool err = false; + while ( !err && ((idxstart = result_raw.find("$(", idxstart)) != std::string::npos) ) { + result_trans.append (result_raw.substr(pos, idxstart - pos) ); + idxend = result_raw.find(")$", idxstart + 2); + if ( idxend == std::string::npos ) { // no $) found: ignore leading $( and pass rest of whole string unparsed + result_trans.append(result_raw.substr(pos)); + err = true; + } else { + std::string func = result_raw.substr( idxstart + 2, idxend - idxstart - 2 ); + cSkinFunction *result = new cSkinFunction(mObject); + if (result->Parse(func, true)) { + std::string result_rescan = (std::string)result->Evaluate(); + if (result_rescan != "") + result_trans.append( result_rescan ); + } + delete result; + + idxstart = idxend + 2; + pos = idxstart; + } + } + result_trans.append( result_raw.substr(pos) ); + return result_trans; } } // end of namespace |