summaryrefslogtreecommitdiff
path: root/glcdskin/string.c
diff options
context:
space:
mode:
Diffstat (limited to 'glcdskin/string.c')
-rw-r--r--glcdskin/string.c232
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