diff options
Diffstat (limited to 'glcdskin/string.c')
-rw-r--r-- | glcdskin/string.c | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/glcdskin/string.c b/glcdskin/string.c new file mode 100644 index 0000000..dc9d9dc --- /dev/null +++ b/glcdskin/string.c @@ -0,0 +1,232 @@ +/* + * GraphLCD skin library + * + * string.h - skin string class + * + * This file is released under the GNU General Public License. Refer + * to the COPYING file distributed with this package. + * + * based on text2skin + * + */ + +#include <syslog.h> + +#include "skin.h" +#include "object.h" +#include "string.h" + +namespace GLCD +{ + +tSkinToken::tSkinToken(void) +: Index(-1) +{ +} + +tSkinToken::tSkinToken(int id, std::string n, uint32_t o, const std::string & a) +: Id(id), + Name(n), + Offset(o), + Attrib(a), + MaxItems(-1), + Index(-1) +{ +} + +bool operator< (const tSkinToken & A, const tSkinToken & B) +{ + return A.Id == B.Id + ? A.Name == B.Name + ? A.Attrib == B.Attrib + ? A.Index < B.Index + : A.Attrib < B.Attrib + : A.Name < B.Name + : A.Id < B.Id; +} + +std::string tSkinToken::Token(const tSkinToken & Token) +{ + std::string result = (std::string) "{" + Token.Name; + //if (Token.Attrib.length() > 0) + // result += ":" + Token.Attrib; + result += "}"; + + return result; +} + +cSkinString::tStringList cSkinString::mStrings; + +cSkinString::cSkinString(cSkinObject *Parent, bool Translate) +: mObject(Parent), + mSkin(Parent->Skin()), + mTranslate(Translate) +{ + mStrings.push_back(this); +} + +cSkinString::~cSkinString() +{ + tStringList::iterator it = mStrings.begin(); + for (; it != mStrings.end(); ++it) { + if ((*it) == this) { + mStrings.erase(it); + break; + } + } +} + +void cSkinString::Reparse(void) +{ + tStringList::iterator it = mStrings.begin(); + for (; it != mStrings.end(); ++it) { + if ((*it)->mTranslate && (*it)->mText.length() > 0) + (*it)->Parse((*it)->mOriginal, true); + } +} + +bool cSkinString::Parse(const std::string & Text, bool Translate) +{ + std::string trans = Translate ? mSkin->Config().Translate(Text) : Text; + const char * ptr, * last; + bool inToken = false; + 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 = ""; + mTokens.clear(); + + ptr = trans.c_str(); + last = trans.c_str(); + for (; *ptr; ++ptr) { + if (inToken && *ptr == '\\') { + if (*(ptr + 1) == '\0') { + syslog(LOG_ERR, "ERROR: Stray \\ in token attribute\n"); + return false; + } + + ++ptr; + continue; + } + else if (*ptr == '{') { + if (inToken) { + syslog(LOG_ERR, "ERROR: Unexpected '{' in token"); + return false; + } + + mText.append(last, ptr - last); + last = ptr + 1; + inToken = true; + } + else if (*ptr == '}' || (inToken && *ptr == ':')) { + if (!inToken) { + syslog(LOG_ERR, "ERROR: Unexpected '}' outside of token"); + return false; + } + + if (inAttrib) { + if (*ptr == ':') { + syslog(LOG_ERR, "ERROR: Unexpected ':' inside of token attribute"); + return false; + } + + int pos = -1; + std::string attr; + attr.assign(last, ptr - last); + while ((pos = attr.find('\\', pos + 1)) != -1) { + switch (attr[pos + 1]) { + case 'n': + attr.replace(pos, 2, "\n"); + break; + + default: + attr.erase(pos, 1); + } + } + + tSkinToken &lastToken = mTokens[mTokens.size() - 1]; + if (attr == "clean") + lastToken.Attrib = aClean; + else if (attr == "rest") + lastToken.Attrib = aRest; + else { + char *end; + int n = strtol(attr.c_str(), &end, 10); + //Dprintf("attr: %s, n: %d, end: |%s|\n", attr.c_str(), n, end); + if (end != attr.c_str() && *end == '\0') { + //Dprintf("a number\n"); + lastToken.Attrib = n; + } else + lastToken.Attrib = attr; + } + + inAttrib = false; + inToken = false; + } else { + if (true) + { + std::string tmp; + tmp.assign(last, ptr - last); + tSkinToken token(mSkin->Config().GetTokenId(tmp), tmp, offset, ""); + mTokens.push_back(token); + } + else + { + syslog(LOG_ERR, "ERROR: Unexpected token {%.*s}", (int)(ptr - last), last); + return false; + } + + if (*ptr == ':') + inAttrib = true; + else + inToken = false; + } + + last = ptr + 1; + } + else if (!inToken) + ++offset; + } + + if (inToken) { + syslog(LOG_ERR, "ERROR: Expecting '}' in token"); + return false; + } + + mText.append(last, ptr - last); + + if (mTranslate && !Translate && mText.length() > 0) + Parse(Text, true); + return true; +} + +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])); + offset = mTokens[i].Offset; + } + result.append(mText.c_str() + offset); + return result; +} + +} // end of namespace |