/* Parser.cc Copyright © 2003 David Reveman. This file is part of Waimea. Waimea is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. Waimea is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Waimea; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include "../config.h" #endif // HAVE_CONFIG_H extern "C" { #include #ifdef STDC_HEADERS # include # include # include #endif // STDC_HEADERS #ifdef HAVE_SYS_TYPES_H # include #endif // HAVE_SYS_TYPES_H #ifdef HAVE_SYS_STAT_H # include #endif // HAVE_SYS_STAT_H #ifdef HAVE_UNISTD_H # include #endif // HAVE_UNISTD_H #ifdef HAVE_SYS_WAIT_H # include #endif // HAVE_SYS_WAIT_H #ifdef HAVE_FCNTL_H # include #endif // HAVE_FCNTL_H } #include "Parser.hh" #include "Util.hh" #include "Action.hh" #include "Style.hh" #include "Screen.hh" Tst *win_state_tst; Tst *x11_modifier_tst; Tst *wa_modifier_tst; Tst *dynamic_try_tst; Tst *cfg_element_tst; Tst *actionlist_element_tst; Tst *action_element_tst; Tst *menu_element_tst; Tst *menuitem_element_tst; Tst *rendergroup_element_tst; Tst *renderopdynamic_element_tst; Tst *renderpattern_element_tst; Tst *renderpath_element_tst; Tst *rendertext_element_tst; static void parser_start_element(void *userdata, const XML_Char *name, const XML_Char **attr) { Parser *parser; ElementHandler *handler; ParserElement element; parser = (Parser *) userdata; if (parser->unknown_element_depth) { parser->unknown_element_depth++; return; } if (! parser->waimea_element_found) { if ( ! strcmp((char *) name, "waimea")) { Tst *attr_tst = new Tst(attr); char *version = parser->attrGetString(attr_tst, "version", NULL); if (version) { if (strcmp(version, VERSION) < 0) parser->warning("detected an old configuration file " "version %s. waimea version is " VERSION "\n", version); else if (strcmp(version, VERSION) > 0) parser->warning("detected an old version of waimea " VERSION ". configuration file version is " "%s\n", version); } parser->waimea_element_found = true; delete attr_tst; return; } } handler = parser->element_handler_stack.back(); if (handler) { element = handler->elementMap(name); if (element == ParserElementNone) { parser->unknown_element_depth++; } else { Tst *attr_trie = new Tst(attr); if (! handler->startElement(element, name, attr_trie)) parser->unknown_element_depth++; delete attr_trie; } } } static void parser_end_element(void *userdata, const XML_Char *name) { Parser *parser; ElementHandler *handler; parser = (Parser *) userdata; if (parser->unknown_element_depth) { parser->unknown_element_depth--; return; } handler = parser->element_handler_stack.back(); if (handler) { handler->endElement(name); parser->popElementHandler(); } } static void parser_characters(void *userdata, const XML_Char *chars, int len) { Parser *parser; ElementHandler *handler; parser = (Parser *) userdata; handler = parser->element_handler_stack.back(); if (! len || ! handler) return; handler->characters(chars, len); } static void parser_start_doctype_decl(void *userdata, const XML_Char *doctypename, const XML_Char *, const XML_Char *, int) { Parser *parser = (Parser *) userdata; if (strcmp((char *) doctypename, "waimea") != 0) parser->warning("invalid doctype: %s", doctypename); } static void parser_end_doctype_decl(void *) {} StringBuffer::~StringBuffer(void) { while (! strbuf.empty()) { delete [] strbuf.back(); strbuf.pop_back(); } } void StringBuffer::addString(char *chars, int len) { if (len < 1) return; strbuf_length += (len); char *substr = new char[len + 1]; strncpy(substr, chars, len); substr[len] = '\0'; strbuf.push_back(substr); } char *StringBuffer::getString(void) { char *str = new char[strbuf_length + 1]; char *str_ptr = str; str[strbuf_length] = '\0'; list::iterator it = strbuf.begin(); for (; it != strbuf.end(); it++) str_ptr += sprintf(str_ptr, "%s", *it); return str; } Parser::Parser(WaScreen *_ws, int _include_depth, bool cr_xml_parser) { if (cr_xml_parser) { xml_parser = XML_ParserCreate("UTF-8"); if (! xml_parser) { ERROR_FUNC << "failed to create xml parser context" << endl; exit(1); } XML_SetDoctypeDeclHandler(xml_parser, parser_start_doctype_decl, parser_end_doctype_decl); XML_SetElementHandler(xml_parser, parser_start_element, parser_end_element); XML_SetCharacterDataHandler(xml_parser, parser_characters); XML_SetUserData(xml_parser, this); } else xml_parser = NULL; include_depth = _include_depth; unknown_element_depth = 0; filename = WA_STRDUP(""); waimea_element_found = false; ws = _ws; } Parser::~Parser(void) { char *warnings = strbuf.getString(); if (*warnings != '\0') ws->showWarningMessage(__FUNCTION__, warnings); delete [] warnings; if (xml_parser) XML_ParserFree(xml_parser); while (! element_handler_stack.empty()) { element_handler_stack.back()->unref(); element_handler_stack.pop_back(); } delete [] filename; Tst::iterator it = constants.begin(); for (; it != constants.end(); it++) delete [] *it; } void Parser::pushElementHandler(ElementHandler *handler) { element_handler_stack.push_back(handler); } void Parser::popElementHandler(void) { if (! element_handler_stack.empty()) { element_handler_stack.back()->unref(); element_handler_stack.pop_back(); } } void Parser::setFilename(const char *name) { delete [] filename; filename = WA_STRDUP((char *) name); } bool Parser::parseChunk(const char *data, int len) { if (! xml_parser) return false; if (! XML_Parse(xml_parser, data, len, len == 0)) { warning("%s", XML_ErrorString(XML_GetErrorCode(xml_parser))); return false; } return true; } bool Parser::parseChunkEnd(void) { if (! xml_parser) return false; if (! XML_Parse(xml_parser, NULL, 0, true)) { warning("%s", XML_ErrorString(XML_GetErrorCode(xml_parser))); return false; } return true; } bool Parser::parseFile(const char *file, bool ignore_missing) { if (! xml_parser) return false; FILE *fd = fopen(file, "r"); if (fd == NULL) { if (! ignore_missing) { warning("%s: %s", file, strerror(errno)); } } else { int len; delete [] filename; filename = WA_STRDUP((char *) file); do { void *buf = XML_GetBuffer(xml_parser, PARSE_BUFFER_SIZE); if (! buf) { WARNING_FUNC << "cannot get parse buffer" << endl; return false; } len = fread(buf, 1, PARSE_BUFFER_SIZE, fd); if (len < 0) { WARNING_FUNC << "failed reading config file" << endl; return false; } if (! XML_ParseBuffer(xml_parser, len, len == 0)) { warning("%s", XML_ErrorString(XML_GetErrorCode(xml_parser))); return false; } } while (len != 0); fclose(fd); return true; } return false; } bool Parser::parseCommand(const char *command, bool ignore_missing) { int m_pipe[2]; int pid, waitstatus; struct sigaction action; FILE *fd; bool status = false; if (! xml_parser) return false; if (pipe(m_pipe) < 0) { WARNING_FUNC; perror("pipe"); goto bail; } action.sa_handler = SIG_DFL; action.sa_mask = sigset_t(); action.sa_flags = 0; sigaction(SIGCHLD, &action, NULL); pid = fork(); if (pid == 0) { dup2(m_pipe[1], STDOUT_FILENO); close(m_pipe[0]); close(m_pipe[1]); putenv(waimea_pathenv); if (execl("/bin/sh", "/bin/sh", "-c", command, NULL) < 0) WARNING_FUNC; perror("/bin/sh"); close(STDOUT_FILENO); exit(127); } close(m_pipe[1]); fd = fdopen(m_pipe[0], "r"); if (fd == NULL) { WARNING_FUNC; perror("fdopen"); } else { int len; if (filename) delete [] filename; filename = WA_STRDUP("STDOUT"); do { void *buf = XML_GetBuffer(xml_parser, PARSE_BUFFER_SIZE); if (! buf) { WARNING_FUNC << "cannot get parse buffer" << endl; goto bail; } len = fread(buf, 1, PARSE_BUFFER_SIZE, fd); if (len < 0) { WARNING_FUNC << "failed reading command output" << endl; goto bail; } if (! XML_ParseBuffer(xml_parser, len, len == 0)) { warning("%s", XML_ErrorString(XML_GetErrorCode(xml_parser))); goto bail; } } while (len != 0); action.sa_handler = signalhandler; action.sa_flags = SA_NOCLDSTOP | SA_NODEFER; sigaction(SIGCHLD, &action, NULL); if (waitpid(pid, &waitstatus, 0) == -1) { WARNING_FUNC; perror("waitpid"); } else if (waitstatus) { if (! ignore_missing) { warning("execution failed"); } } status = true; } bail: return status; } void Parser::warning(const char *msg, ...) { va_list args; char message[8192]; char linenr[32]; char *line; int len; va_start(args, msg); vsnprintf(message, 8192, msg, args); va_end(args); snprintf(linenr, 32, "%d", XML_GetCurrentLineNumber(xml_parser)); len = strlen(filename) + strlen(linenr) + strlen(message) + 5; line = new char[len + 1]; sprintf(line, "%s: %s: %s", filename, linenr, message); if (strbuf.strbuf.empty()) { char *error_head = "The following parsing errors occured:\n"; strbuf.addString(error_head, strlen(error_head)); } strbuf.addString(line, len); delete [] line; } char *Parser::attrGetString(Tst *attr, char *name, char *default_value) { if (attr) { Tst::iterator it = attr->find(name); if (it != attr->end()) return attrValue(*it); } return default_value; } bool Parser::attrGetBool(Tst *attr, char *name, bool default_value) { if (attr) { Tst::iterator it = attr->find(name); if (it != attr->end()) { if (! strcasecmp(attrValue(*it), "true")) return true; else return false; } } return default_value; } double Parser::attrGetDouble(Tst *attr, char *name, double default_value) { if (attr) { Tst::iterator it = attr->find(name); if (it != attr->end()) return strtod(attrValue(*it), NULL); } return default_value; } int Parser::attrGetInt(Tst *attr, char *name, int default_value) { if (attr) { Tst::iterator it = attr->find(name); if (it != attr->end()) return (int) strtol(attrValue(*it), NULL, 0); } return default_value; } unsigned int Parser::attrGetUint(Tst *attr, char *name, unsigned int default_value) { if (attr) { Tst::iterator it = attr->find(name); if (it != attr->end()) return (unsigned int) strtol(attrValue(*it), NULL, 0); } return default_value; } double Parser::attrGetLength(Tst *attr, char *name, double default_value, LenghtUnitType *unit) { if (attr) { Tst::iterator it = attr->find(name); if (it != attr->end()) return get_double_and_unit(attrValue(*it), unit); } return default_value; } void Parser::attrGetWindowregexContent(Tst *attr, WindowRegex *wreg) { char *value = attrGetString(attr, "name", NULL); if (value) wreg->addIDRegex(WindowIDName, value); value = attrGetString(attr, "class", NULL); if (value) wreg->addIDRegex(WindowIDClass, value); value = attrGetString(attr, "classname", NULL); if (value) wreg->addIDRegex(WindowIDClassName, value); value = attrGetString(attr, "pid", NULL); if (value) wreg->addIDRegex(WindowIDPID, value); value = attrGetString(attr, "host", NULL); if (value) wreg->addIDRegex(WindowIDHost, value); value = attrGetString(attr, "resourceid", NULL); if (value) wreg->addIDRegex(WindowIDWinID, value); } char *Parser::attrValue(char *value) { Tst::iterator it = constants.find(value); if (it != constants.end()) { return *it; } else { it = ws->constants.find(value); if (it != ws->constants.end()) return *it; } return value; } ElementHandler::ElementHandler(Parser *_parser) : RefCounted(this) { parser = _parser; } IncludeElementHandler::IncludeElementHandler(Parser *_parser, ElementHandler *_handler, bool _ignore_missing) : ElementHandler(_parser) { previous_handler = _handler; ignore_missing = _ignore_missing; } void IncludeElementHandler::characters(const XML_Char *chars, int len) { strbuf.addString((char *) chars, len); } void IncludeElementHandler::endElement(const XML_Char *) { char *fname = strbuf.getString(); if (parser->include_depth >= MAX_INCLUDE_DEPTH) { parser->warning("%s: cannot be included because maximum include " "depth of %d reached", fname, MAX_INCLUDE_DEPTH); delete [] fname; return; } if (*fname == '|') { Parser *command_parser = new Parser(parser->ws, parser->include_depth + 1); previous_handler->parser = command_parser; command_parser->pushElementHandler(previous_handler->ref()); command_parser->parseCommand(fname + 1, ignore_missing); previous_handler->parser = parser; delete command_parser; } else { char *filename = smartfile(fname, parser->filename, false); if (filename) { Parser *include_parser = new Parser(parser->ws, parser->include_depth + 1); previous_handler->parser = include_parser; include_parser->pushElementHandler(previous_handler->ref()); include_parser->parseFile(filename, ignore_missing); previous_handler->parser = parser; delete include_parser; delete [] filename; } else { if (! ignore_missing) parser->warning("unable to open file: %s\n", fname); } } if (fname) delete [] fname; } InheritElementHandler::InheritElementHandler(CfgElementHandler *_cfg_handler, Tst *attr) : ElementHandler(_cfg_handler->parser) { ignore_missing = parser->attrGetBool(attr, "ignore_missing", false); } void InheritElementHandler::characters(const XML_Char *chars, int len) { strbuf.addString((char *) chars, len); } static const ParserElementMap cfg_element_map[] = { { "constant", ParserElementConstant }, { "include", ParserElementInclude }, { "do", ParserElementDo }, { "actionlist", ParserElementActionList }, { "match", ParserElementMatch }, { "menu", ParserElementMenu }, { "style", ParserElementStyle }, { "group", ParserElementRenderGroup }, { "path", ParserElementRenderPath }, { "pattern", ParserElementRenderPattern }, { "text", ParserElementRenderText } }; ParserElement CfgElementHandler::elementMap(const XML_Char *name) { Tst::iterator it = cfg_element_tst->find((char *) name); if (it != cfg_element_tst->end()) return *it; else return ParserElementNone; } static const struct WindowStateMap { char *name; int state; } win_state_map[] = { { "passive", WIN_STATE_PASSIVE }, { "active", WIN_STATE_ACTIVE }, { "hover", WIN_STATE_HOVER }, { "pressed", WIN_STATE_PRESSED } }; bool CfgElementHandler::startElement(ParserElement element, const XML_Char *, Tst *attr) { switch (element) { case ParserElementConstant: { char *cname = parser->attrGetString(attr, "name", NULL); char *cvalue = parser->attrGetString(attr, "value", NULL); if (cname && cvalue) { Tst *cons = &parser->ws->constants; char *storage = parser->attrGetString(attr, "scope", NULL); if (storage && ((! strcmp(storage, "local")))) cons = &parser->constants; Tst::iterator it = cons->find(cname); if (it == cons->end()) cons->insert(cname, WA_STRDUP(cvalue)); } else { parser->warning("required attribute=name or attribute=value " "is missing\n"); } } break; case ParserElementInclude: { bool ignore_missing = parser->attrGetBool(attr, "ignore_missing", false); IncludeElementHandler *handler = new IncludeElementHandler(parser, this, ignore_missing); parser->pushElementHandler(handler); return true; } break; case ParserElementDo: { Doing *doing = new Doing(parser->ws); doing->applyAttributes(parser, attr); parser->ws->waimea->eh->doings.push_back(doing); } break; case ParserElementActionList: { ActionList *actionlist = NULL; char *name = parser->attrGetString(attr, "name", NULL); if (name) { actionlist = parser->ws->getActionListNamed(name, false); if (actionlist) { if (! parser->attrGetBool(attr, "extend", false)) actionlist->clear(); } else { actionlist = new ActionList(parser->ws, name); parser->ws->actionlists.insert(actionlist->name, actionlist); } } else { parser->warning("required attribute=name is missing\n"); return false; } ActionListElementHandler *handler = new ActionListElementHandler(this, actionlist); parser->pushElementHandler(handler); return true; } break; case ParserElementMenu: { Menu *menu = NULL; char *name = parser->attrGetString(attr, "name", NULL); if (name) { menu = parser->ws->getMenuNamed(name, false); if (menu) { if (! parser->attrGetBool(attr, "extend", false)) menu->clear(); } else { menu = new Menu(parser->ws, name); menu->commonStyleUpdate(); parser->ws->menus.insert(menu->name, menu); } menu->applyAttributes(parser, attr); } else { parser->warning("required attribute=name is missing\n"); return false; } MenuElementHandler *handler = new MenuElementHandler(this, menu); parser->pushElementHandler(handler); return true; } break; case ParserElementRenderGroup: { RenderGroup *rendergroup = NULL; char *name = parser->attrGetString(attr, "name", NULL); if (name) { rendergroup = parser->ws->getRenderGroupNamed(name, false); if (rendergroup) { if (! parser->attrGetBool(attr, "extend", false)) rendergroup->clear(); } else { rendergroup = new RenderGroup(parser->ws, name); parser->ws->rendergroups.insert(rendergroup->name, rendergroup); } } else { parser->warning("group without attribute=name outside of a " "style tag does not make any sense\n"); return false; } rendergroup->applyAttributes(parser, attr); RenderGroupElementHandler *handler = new RenderGroupElementHandler(this, rendergroup, NULL); parser->pushElementHandler(handler); return true; } break; case ParserElementStyle: { Style *style = NULL; char *name = parser->attrGetString(attr, "name", NULL); if (name) { style = parser->ws->getStyleNamed(name, false); if (style) { if (! parser->attrGetBool(attr, "extend", false)) style->clear(); } else { style = new Style(parser->ws, name); parser->ws->styles.insert(style->name, style); parser->ws->rendergroups.insert(style->name, (Style *) style->ref()); } } else { parser->warning("required attribute=name is missing\n"); return false; } style->applyAttributes(parser, attr); RenderGroupElementHandler *handler = new RenderGroupElementHandler(this, (RenderGroup *) style, NULL); parser->pushElementHandler(handler); return true; } break; case ParserElementRenderPattern: { RenderPattern *pattern = NULL; char *name = parser->attrGetString(attr, "name", NULL); if (name) { pattern = parser->ws->getPatternNamed(name, false); if (pattern) { if (! parser->attrGetBool(attr, "extend", false)) pattern->clear(); } else { pattern = new RenderPattern(); parser->ws->patterns.insert(name, pattern); } } else { parser->warning("path without attribute=name\n"); return false; } pattern->applyAttributes(parser, attr); RenderPatternElementHandler *handler = new RenderPatternElementHandler(this, pattern); parser->pushElementHandler(handler); return true; } break; case ParserElementRenderPath: { RenderOpPath *path = NULL; char *name = parser->attrGetString(attr, "name", NULL); if (name) { path = parser->ws->getPathNamed(name, false); if (path) { if (! parser->attrGetBool(attr, "extend", false)) path->clear(); } else { path = new RenderOpPath(name); parser->ws->paths.insert(path->name, path); } } else { parser->warning("path without attribute=name outside of a " "group or style tag does not make any " "sense\n"); return false; } path->applyAttributes(parser, attr); RenderPathElementHandler *handler = new RenderPathElementHandler(this, path, NULL); parser->pushElementHandler(handler); return true; } break; case ParserElementRenderText: { RenderOpText *text = NULL; char *name = parser->attrGetString(attr, "name", NULL); if (name) { text = parser->ws->getTextNamed(name, false); if (text) { if (! parser->attrGetBool(attr, "extend", false)) text->clear(); } else { text = new RenderOpText(name); parser->ws->texts.insert(text->name, (RenderOpText *) text->ref()); } } else { parser->warning("text object without attribute=name " "outside of a group or style tag does not " "make any sense\n"); return false; } text->applyAttributes(parser, attr); RenderOpTextElementHandler *handler = new RenderOpTextElementHandler(this, text, NULL); parser->pushElementHandler(handler); return true; } break; case ParserElementMatch: { char *a_name = parser->attrGetString(attr, "actionlist", NULL); char *s_name = parser->attrGetString(attr, "style", NULL); if (a_name || s_name) { list *a_tolist = NULL; list *s_tolist = NULL; char *t = parser->attrGetString(attr, "target", "window"); if (t) { if (a_name) a_tolist = parser->ws->getRegexActionList(t); if (s_name) s_tolist = parser->ws->getRegexStyleList(t); if (a_tolist || s_tolist) { int state = WIN_STATE_PASSIVE; char *s = parser->attrGetString(attr, "state", NULL); if (s) { Tst::iterator it = win_state_tst->find(s); if (it != win_state_tst->end()) state = *it; } char *w = parser->attrGetString(attr, "window", NULL); if (a_tolist) { ActionRegex *areg = new ActionRegex(state, w); parser->attrGetWindowregexContent(attr, areg); areg->actionlist = parser->ws->getActionListNamed(a_name, false); if (! areg->actionlist) { parser->warning("undefined actionlist: %s\n", a_name); delete areg; } else a_tolist->push_front(areg); } if (s_tolist) { StyleRegex *sreg = new StyleRegex(state, w); parser->attrGetWindowregexContent(attr, sreg); sreg->style = parser->ws->getStyleNamed(s_name, false); if (! sreg->style) { parser->warning("undefined style: %s\n", s_name); delete sreg; } else s_tolist->push_front(sreg); } } } else parser->warning("missing required attribute=target\n"); } } break; default: break; } return false; } ActionListElementHandler::ActionListElementHandler( CfgElementHandler *_cfg_handler, ActionList *_actionlist) : ElementHandler(_cfg_handler->parser) { actionlist = _actionlist; cfg_handler = _cfg_handler; } static const ParserElementMap actionlist_element_map[] = { { "inherit", ParserElementInherit }, { "action", ParserElementAction } }; ParserElement ActionListElementHandler::elementMap(const XML_Char *name) { if (! actionlist) return ParserElementNone; Tst::iterator it = actionlist_element_tst->find((char *) name); if (it != actionlist_element_tst->end()) return *it; else return ParserElementNone; } bool ActionListElementHandler::startElement(ParserElement element, const XML_Char *, Tst *attr) { switch (element) { case ParserElementAction: { Action *action = new Action(); action->applyAttributes(parser, attr); ActionElementHandler *handler = new ActionElementHandler(cfg_handler, actionlist, action); parser->pushElementHandler(handler); return true; } break; case ParserElementInherit: { ActionListInheritElementHandler *handler = new ActionListInheritElementHandler(cfg_handler, actionlist, attr); parser->pushElementHandler(handler); return true; } break; default: break; } return false; } void ActionListElementHandler::endElement(const XML_Char *) { parser->ws->propagateActionlistUpdate(actionlist); } ActionListInheritElementHandler::ActionListInheritElementHandler( CfgElementHandler *_cfg_handler, ActionList *_actionlist, Tst *attr) : InheritElementHandler(_cfg_handler, attr) { actionlist = _actionlist; } void ActionListInheritElementHandler::endElement(const XML_Char *) { char *actionlistname = strbuf.getString(); ActionList *inherit_list = parser->ws->getActionListNamed(actionlistname, false); if (inherit_list == actionlist) { parser->warning("actionlist %s cannot inherit itself\n", actionlist->name); } else if (inherit_list) { actionlist->inheritContent(inherit_list); } else { if (! ignore_missing) parser->warning("undefined actionlist: %s\n", actionlistname); } delete [] actionlistname; } ActionElementHandler::ActionElementHandler( CfgElementHandler *_cfg_handler, ActionList *_actionlist, Action *_action) : ElementHandler(_cfg_handler->parser) { cfg_handler = _cfg_handler; actionlist = _actionlist; action = _action; } static const ParserElementMap action_element_map[] = { { "modifier", ParserElementModifier } }; ParserElement ActionElementHandler::elementMap(const XML_Char *name) { Tst::iterator it = action_element_tst->find((char *) name); if (it != action_element_tst->end()) return *it; else return ParserElementNone; } static ModifierMap x11_modifier_map[] = { { "shift", ShiftMask }, { "lock", LockMask }, { "control", ControlMask }, { "mod1", Mod1Mask }, { "mod2", Mod2Mask }, { "mod3", Mod3Mask }, { "mod4", Mod4Mask }, { "mod5", Mod5Mask }, { "button1", Button1Mask }, { "button2", Button2Mask }, { "button3", Button3Mask }, { "button4", Button4Mask }, { "button5", Button5Mask } }; static ModifierMap wa_modifier_map[] = { { "moveresize", MoveResizeMask }, { "statetrue", StateTrueMask } }; bool ActionElementHandler::startElement(ParserElement element, const XML_Char *, Tst *attr) { switch (element) { case ParserElementModifier: { unsigned int *x11_modifier_value = &action->x11mod; unsigned int *wa_modifier_value = &action->wamod; char *value = parser->attrGetString(attr, "constraint", NULL); if (value && (! strcasecmp(value, "must_not_exist"))) { x11_modifier_value = &action->x11nmod; wa_modifier_value = &action->wanmod; } value = parser->attrGetString(attr, "name", NULL); if (value) { bool mod_set = false; Tst::iterator it = x11_modifier_tst->find(value); if (it != x11_modifier_tst->end()) { *x11_modifier_value = *it; mod_set = true; } if (! mod_set) { it = wa_modifier_tst->find(value); if (it != wa_modifier_tst->end()) { *wa_modifier_value = *it; mod_set = true; } } if (! mod_set) { it = client_window_state_tst->find(value); if (it != client_window_state_tst->end()) { *wa_modifier_value = *it; mod_set = true; } } if (! mod_set) { parser->warning("modifier=%s doesn't exist\n", value); } } else { value = parser->attrGetString(attr, "key", NULL); if (value) { list::iterator it = parser->ws->waimea->modmaps.begin(); for (; it != parser->ws->waimea->modmaps.end(); it++) { if (! strcasecmp(value, (*it)->name)) { *x11_modifier_value |= (*it)->modifier; break; } } if (it == parser->ws->waimea->modmaps.end()) parser->warning("no modifier mapping to key: %s\n", value); } else parser->warning("required attribute missing, neither " "name or key specified\n"); } } break; default: break; } return false; } void ActionElementHandler::endElement(const XML_Char *) { if (! action) return; if (action->func && action->type) { actionlist->actionlist.push_back(action); } else { delete action; action = NULL; } } MenuInheritElementHandler::MenuInheritElementHandler( CfgElementHandler *_cfg_handler, Menu *_menu, Tst *attr) : InheritElementHandler(_cfg_handler, attr) { menu = _menu; } void MenuInheritElementHandler::endElement(const XML_Char *) { char *menuname = strbuf.getString(); Menu *inherit_menu = parser->ws->getMenuNamed(menuname, false); if (inherit_menu == menu) { parser->warning("menu %s cannot inherit itself\n", menu->name); } else if (inherit_menu) { menu->inheritContent(inherit_menu); } else { if (! ignore_missing) parser->warning("undefined menu: %s\n", menuname); } delete [] menuname; } MenuElementHandler::MenuElementHandler( CfgElementHandler *_cfg_handler, Menu *_menu) : ElementHandler(_cfg_handler->parser) { menu = _menu; cfg_handler = _cfg_handler; } static const ParserElementMap menu_element_map[] = { { "inherit", ParserElementInherit }, { "item", ParserElementMenuItem } }; ParserElement MenuElementHandler::elementMap(const XML_Char *name) { if (! menu) return ParserElementNone; Tst::iterator it = menu_element_tst->find((char *) name); if (it != menu_element_tst->end()) return *it; else return ParserElementNone; } bool MenuElementHandler::startElement(ParserElement element, const XML_Char *, Tst *attr) { switch (element) { case ParserElementMenuItem: { char *name = parser->attrGetString(attr, "name", "item"); MenuItem *menuitem = new MenuItem(parser->ws, menu, name); menuitem->commonStyleUpdate(); menu->items.push_back(menuitem); menuitem->applyAttributes(parser, attr); MenuItemElementHandler *handler = new MenuItemElementHandler(cfg_handler, menuitem); parser->pushElementHandler(handler); return true; } break; case ParserElementInherit: { MenuInheritElementHandler *handler = new MenuInheritElementHandler(cfg_handler, menu, attr); parser->pushElementHandler(handler); return true; } break; default: break; } return false; } void MenuElementHandler::endElement(const XML_Char *) { if (menu) menu->update(); } MenuItemElementHandler::MenuItemElementHandler( CfgElementHandler *_cfg_handler, MenuItem *_menuitem) : ElementHandler(_cfg_handler->parser) { menuitem = _menuitem; cfg_handler = _cfg_handler; } static const ParserElementMap menuitem_element_map[] = { { "menu", ParserElementMenu }, { "itemaction", ParserElementMenuItemAction } }; ParserElement MenuItemElementHandler::elementMap(const XML_Char *name) { Tst::iterator it = menuitem_element_tst->find((char *) name); if (it != menuitem_element_tst->end()) return *it; else return ParserElementNone; } bool MenuItemElementHandler::startElement(ParserElement element, const XML_Char *, Tst *attr) { switch (element) { case ParserElementMenu: { Menu *menu = NULL; char *name = parser->attrGetString(attr, "name", NULL); if (name) { menu = parser->ws->getMenuNamed(name, false); if (menu) { if (! parser->attrGetBool(attr, "extend", false)) menu->clear(); } else { menu = new Menu(parser->ws, name); menu->commonStyleUpdate(); parser->ws->menus.insert(menu->name, menu); } } else { menu = new Menu(parser->ws, NULL); menu->commonStyleUpdate(); parser->ws->menus.insert(menu->name, menu); } menu->applyAttributes(parser, attr); menuitem->submenu = (Menu *) menu->ref(); MenuElementHandler *handler = new MenuElementHandler(cfg_handler, menu); parser->pushElementHandler(handler); return true; } break; case ParserElementMenuItemAction: { MenuItemAction *itemaction = new MenuItemAction(); if (itemaction->applyAttributes(parser, attr)) menuitem->actions.push_back(itemaction); else delete itemaction; } break; default: break; } return false; } RenderGroupElementHandler::RenderGroupElementHandler( CfgElementHandler *_cfg_handler, RenderGroup *_rendergroup, RenderGroup *_parentgroup) : ElementHandler(_cfg_handler->parser) { rendergroup = _rendergroup; parentgroup = _parentgroup; cfg_handler = _cfg_handler; } static const ParserElementMap rendergroup_element_map[] = { { "inherit", ParserElementInherit }, { "group", ParserElementRenderGroup }, { "dynamic", ParserElementRenderDynamic }, { "shape_mask", ParserElementShapeMask }, { "path", ParserElementRenderPath }, { "line", ParserElementRenderLine }, { "rectangle", ParserElementRenderRectangle }, { "ellipse", ParserElementRenderEllipse }, { "solid", ParserElementRenderSolid }, { "image", ParserElementRenderImage }, #ifdef SVG { "svg", ParserElementRenderSvg }, #endif // SVG { "text", ParserElementRenderText }, { "window", ParserElementRenderWindow } }; ParserElement RenderGroupElementHandler::elementMap(const XML_Char *name) { Tst::iterator it = rendergroup_element_tst->find((char *) name); if (it != rendergroup_element_tst->end()) { if (*it == ParserElementRenderWindow) { if (rendergroup->is_a_style) return *it; else return ParserElementNone; } else return *it; } else return ParserElementNone; } bool RenderGroupElementHandler::startElement(ParserElement element, const XML_Char *, Tst *attr) { switch (element) { case ParserElementInherit: { RenderGroupInheritElementHandler *handler = new RenderGroupInheritElementHandler(cfg_handler, rendergroup, attr); parser->pushElementHandler(handler); return true; } break; case ParserElementRenderWindow: { bool raised = parser->attrGetBool(attr, "raised", false); WindowElementHandler *handler = new WindowElementHandler(cfg_handler, (Style *) rendergroup, raised); parser->pushElementHandler(handler); return true; } break; case ParserElementShapeMask: { if (! rendergroup->is_a_style) return false; if (((Style *) rendergroup)->shapemask) { parser->warning("shape mask allready set\n"); return false; } RenderGroup *subgroup = NULL; char *name = parser->attrGetString(attr, "name", NULL); if (name) { subgroup = parser->ws->getRenderGroupNamed(name, false); if (subgroup) { if (! parser->attrGetBool(attr, "extend", false)) subgroup->clear(); } else { subgroup = new RenderGroup(parser->ws, name); parser->ws->rendergroups.insert( subgroup->name, (RenderGroup *) subgroup->ref()); } } else subgroup = new RenderGroup(parser->ws, NULL); subgroup->applyAttributes(parser, attr); ((Style *) rendergroup)->shapemask = subgroup; ((Style *) rendergroup)->shaped = true; RenderGroupElementHandler *handler = new RenderGroupElementHandler(cfg_handler, subgroup, rendergroup); parser->pushElementHandler(handler); return true; } break; case ParserElementRenderGroup: { RenderGroup *subgroup = NULL; char *name = parser->attrGetString(attr, "name", NULL); if (name) { subgroup = parser->ws->getRenderGroupNamed(name, false); if (subgroup) { if (! parser->attrGetBool(attr, "extend", false)) subgroup->clear(); } else { subgroup = new RenderGroup(parser->ws, name); parser->ws->rendergroups.insert( subgroup->name, (RenderGroup *) subgroup->ref()); } } else subgroup = new RenderGroup(parser->ws, NULL); subgroup->applyAttributes(parser, attr); rendergroup->operations.push_back(subgroup); RenderGroupElementHandler *handler = new RenderGroupElementHandler(cfg_handler, subgroup, rendergroup); parser->pushElementHandler(handler); return true; } break; case ParserElementRenderDynamic: { RenderOpDynamic *dynamic = new RenderOpDynamic(); dynamic->applyAttributes(parser, attr); RenderOpDynamicElementHandler *handler = new RenderOpDynamicElementHandler(cfg_handler, rendergroup, dynamic); parser->pushElementHandler(handler); return true; } break; case ParserElementRenderPath: { RenderOpPath *path = NULL; char *name = parser->attrGetString(attr, "name", NULL); if (name) { path = parser->ws->getPathNamed(name, false); if (path) { if (! parser->attrGetBool(attr, "extend", false)) path->clear(); } else { path = new RenderOpPath(name); parser->ws->paths.insert(path->name, (RenderOpPath *) path->ref()); } } else path = new RenderOpPath(NULL); path->applyAttributes(parser, attr); rendergroup->operations.push_back(path); RenderPathElementHandler *handler = new RenderPathElementHandler(cfg_handler, path, rendergroup); parser->pushElementHandler(handler); return true; } break; case ParserElementRenderLine: { RenderOpLine *line = new RenderOpLine(); line->applyAttributes(parser, attr); rendergroup->operations.push_back(line); } break; case ParserElementRenderRectangle: case ParserElementRenderEllipse: { RenderOpRectangle *rectangle = new RenderOpRectangle(); rectangle->applyAttributes(parser, attr); if (element == ParserElementRenderEllipse) { rectangle->nw_rx = rectangle->nw_ry = rectangle->ne_rx = rectangle->ne_ry = rectangle->sw_rx = rectangle->sw_ry = rectangle->se_rx = rectangle->se_ry = 50.0; rectangle->nw_rx_u = rectangle->nw_ry_u = rectangle->ne_rx_u = rectangle->ne_ry_u = rectangle->sw_rx_u = rectangle->sw_ry_u = rectangle->se_rx_u = rectangle->se_ry_u = PCTLenghtUnitType; } rendergroup->operations.push_back(rectangle); } break; case ParserElementRenderSolid: { RenderOpSolid *solid = new RenderOpSolid(); solid->applyAttributes(parser, attr); rendergroup->operations.push_back(solid); } break; case ParserElementRenderImage: { RenderOpImage *image = new RenderOpImage(); if (image->applyAttributes(parser, attr)) { rendergroup->operations.push_back(image); } else delete image; } break; #ifdef SVG case ParserElementRenderSvg: { RenderOpSvg *svg = new RenderOpSvg(); if (svg->applyAttributes(parser, attr)) { rendergroup->operations.push_back(svg); } else delete svg; } break; #endif // SVG case ParserElementRenderText: { RenderOpText *text = NULL; char *name = parser->attrGetString(attr, "name", NULL); if (name) { text = parser->ws->getTextNamed(name, false); if (text) { if (! parser->attrGetBool(attr, "extend", false)) text->clear(); } else { text = new RenderOpText(name); parser->ws->texts.insert(text->name, (RenderOpText *) text->ref()); } } else text = new RenderOpText(NULL); text->applyAttributes(parser, attr); RenderOpTextElementHandler *handler = new RenderOpTextElementHandler(cfg_handler, text, rendergroup); parser->pushElementHandler(handler); return true; } break; default: break; } return false; } void RenderGroupElementHandler::endElement(const XML_Char *) { if (rendergroup->is_a_style) { ((Style *) rendergroup)->flattenTextOps( &((Style *) rendergroup)->textops); ((Style *) rendergroup)->serial++; parser->ws->propagateStyleUpdate((Style *) rendergroup); } if (parentgroup) { if (rendergroup->has_dynamic_op) parentgroup->has_dynamic_op = true; if (! rendergroup->cacheable) parentgroup->cacheable = false; } } RenderGroupInheritElementHandler::RenderGroupInheritElementHandler( CfgElementHandler *_cfg_handler, RenderGroup *_rendergroup, Tst *attr) : InheritElementHandler(_cfg_handler, attr) { rendergroup = _rendergroup; } void RenderGroupInheritElementHandler::endElement(const XML_Char *) { char *rendergroupname = strbuf.getString(); RenderGroup *inherit_rendergroup = parser->ws->getRenderGroupNamed(rendergroupname, false); if (inherit_rendergroup == rendergroup) { parser->warning("group/style %s cannot inherit itself\n", rendergroup->name); } else if (inherit_rendergroup) { if (inherit_rendergroup->is_a_style && rendergroup->is_a_style) ((Style *) rendergroup)->inheritContent( (Style *) inherit_rendergroup); else rendergroup->inheritContent(inherit_rendergroup); } else { if (! ignore_missing) parser->warning("undefined group/style: %s\n", rendergroupname); } delete [] rendergroupname; } WindowElementHandler::WindowElementHandler( CfgElementHandler *_cfg_handler, Style *_style, bool _raised) : ElementHandler(_cfg_handler->parser) { style = _style; cfg_handler = _cfg_handler; raised = _raised; } void WindowElementHandler::characters(const XML_Char *chars, int len) { strbuf.addString((char *) chars, len); } void WindowElementHandler::endElement(const XML_Char *) { char *windowname = strbuf.getString(); if (*windowname != '\0') { if (! style->subs) style->subs = new list; SubwinInfo *sinfo = new SubwinInfo(parser->ws->getSubwindowId(windowname), raised); style->subs->push_back(sinfo); } else { parser->warning("missing character data for window name"); } delete [] windowname; } static const ParserElementMap renderopdynamic_element_map[] = { { "try", ParserElementRenderDynamicTry } }; RenderOpDynamicElementHandler::RenderOpDynamicElementHandler( CfgElementHandler *_cfg_handler, RenderGroup *_rendergroup, RenderOpDynamic *_dynamic) : ElementHandler(_cfg_handler->parser) { dynamic = _dynamic; cfg_handler = _cfg_handler; rendergroup = _rendergroup; } ParserElement RenderOpDynamicElementHandler::elementMap(const XML_Char *name) { Tst::iterator it = renderopdynamic_element_tst->find((char *) name); if (it != renderopdynamic_element_tst->end()) return *it; else return ParserElementNone; } static const struct DynamicTryMap { char *name; int type; } dynamic_try_map[] = { { "static", DynamicGroupStaticType }, { "menuitemiconimage", DynamicGroupMenuItemIconImageType }, { "menuitemiconsvg", DynamicGroupMenuItemIconSvgType }, { "wmiconimage", DynamicGroupWmIconImageType }, { "wmiconsvg", DynamicGroupWmIconSvgType } }; bool RenderOpDynamicElementHandler::startElement(ParserElement element, const XML_Char *, Tst *attr) { switch (element) { case ParserElementRenderDynamicTry: { char *value = parser->attrGetString(attr, "type", NULL); if (value) { Tst::iterator it = dynamic_try_tst->find((char *) value); if (it != dynamic_try_tst->end()) { if (*it == DynamicGroupStaticType) { value = parser->attrGetString(attr, "name", NULL); if (value) { RenderGroup *rendergroup = parser->ws->getRenderGroupNamed(value, false); if (rendergroup) dynamic->dynamic_order.push_back(*it); else parser->warning("unknown static group: %s", value); } else parser->warning("static group name not defined"); } else dynamic->dynamic_order.push_back(*it); } } } default: break; } return false; } void RenderOpDynamicElementHandler::endElement(const XML_Char *) { if (! dynamic->dynamic_order.empty()) { rendergroup->operations.push_back(dynamic); rendergroup->has_dynamic_op = true; } else cfg_handler->parser->warning("missing group in dynamic operation"); } RenderPatternElementHandler::RenderPatternElementHandler( CfgElementHandler *_cfg_handler, RenderPattern *_pattern) : ElementHandler(_cfg_handler->parser) { pattern = _pattern; cfg_handler = _cfg_handler; } static const ParserElementMap renderpattern_element_map[] = { { "colorstop", ParserElementRenderColorStop } }; ParserElement RenderPatternElementHandler::elementMap(const XML_Char *name) { Tst::iterator it = renderpattern_element_tst->find((char *) name); if (it != renderpattern_element_tst->end()) return *it; else return ParserElementNone; } bool RenderPatternElementHandler::startElement(ParserElement element, const XML_Char *, Tst *attr) { WaColor *color = new WaColor(); double offset = 0.0; char *value = parser->attrGetString(attr, "color", NULL); if (value) { if (! color->parseColor(parser->ws, value)) parser->warning("error parsing color: %s\n", value); } if (color) color->setOpacity( parser->attrGetDouble(attr, "opacity", color->getOpacity())); offset = parser->attrGetDouble(attr, "offset", offset); pattern->color_stops.push_back(new WaColorStop(offset, color)); return false; } RenderPatternInheritElementHandler::RenderPatternInheritElementHandler( CfgElementHandler *_cfg_handler, RenderPattern *_pattern, Tst *attr) : InheritElementHandler(_cfg_handler, attr) { pattern = _pattern; } void RenderPatternInheritElementHandler::endElement(const XML_Char *) { char *patternname = strbuf.getString(); RenderPattern *inherit_pattern = parser->ws->getPatternNamed(patternname, false); if (inherit_pattern == pattern) { parser->warning("pattern %s cannot inherit itself\n", patternname); } else if (inherit_pattern) { pattern->inheritContent(inherit_pattern); } else { if (! ignore_missing) parser->warning("undefined pattern: %s\n", patternname); } delete [] patternname; } RenderPathElementHandler::RenderPathElementHandler( CfgElementHandler *_cfg_handler, RenderOpPath *_path, RenderGroup *_rendergroup) : ElementHandler(_cfg_handler->parser) { path = _path; cfg_handler = _cfg_handler; rendergroup = _rendergroup; } static const ParserElementMap renderpath_element_map[] = { { "inherit", ParserElementInherit }, { "moveto", ParserElementRenderPathMoveTo }, { "relmoveto", ParserElementRenderPathRelMoveTo }, { "lineto", ParserElementRenderPathLineTo }, { "rellineto", ParserElementRenderPathRelLineTo }, { "curveto", ParserElementRenderPathCurveTo }, { "relcurveto", ParserElementRenderPathRelCurveTo }, { "arcto", ParserElementRenderPathArcTo }, { "close", ParserElementRenderPathClose } }; ParserElement RenderPathElementHandler::elementMap(const XML_Char *name) { Tst::iterator it = renderpath_element_tst->find((char *) name); if (it != renderpath_element_tst->end()) return *it; else return ParserElementNone; } bool RenderPathElementHandler::startElement(ParserElement element, const XML_Char *, Tst *attr) { PathOperator *op = NULL; switch (element) { case ParserElementInherit: { RenderOpPathInheritElementHandler *handler = new RenderOpPathInheritElementHandler(cfg_handler, path, attr); parser->pushElementHandler(handler); return true; } break; case ParserElementRenderPathMoveTo: op = new PathOperator(PathOperatorMoveToType); op->applyAttributes(parser, attr); break; case ParserElementRenderPathRelMoveTo: op = new PathOperator(PathOperatorRelMoveToType); op->applyAttributes(parser, attr); break; case ParserElementRenderPathLineTo: op = new PathOperator(PathOperatorLineToType); op->applyAttributes(parser, attr); break; case ParserElementRenderPathRelLineTo: op = new PathOperator(PathOperatorRelLineToType); op->applyAttributes(parser, attr); break; case ParserElementRenderPathCurveTo: op = new PathOperator(PathOperatorCurveToType); op->applyAttributes(parser, attr); break; case ParserElementRenderPathRelCurveTo: op = new PathOperator(PathOperatorRelCurveToType); op->applyAttributes(parser, attr); break; case ParserElementRenderPathArcTo: op = new PathOperator(PathOperatorArcToType); op->applyAttributes(parser, attr); break; case ParserElementRenderPathRelArcTo: op = new PathOperator(PathOperatorRelArcToType); op->applyAttributes(parser, attr); break; case ParserElementRenderPathClose: op = new PathOperator(PathOperatorCloseType); op->applyAttributes(parser, attr); break; default: break; } if (op) path->ops.push_back(op); return false; } void RenderPathElementHandler::endElement(const XML_Char *) { if (path->ops.empty()) parser->warning("path element does not contain any operations\n"); } RenderOpPathInheritElementHandler::RenderOpPathInheritElementHandler( CfgElementHandler *_cfg_handler, RenderOpPath *_path, Tst *attr) : InheritElementHandler(_cfg_handler, attr) { path = _path; } void RenderOpPathInheritElementHandler::endElement(const XML_Char *) { char *pathname = strbuf.getString(); RenderOpPath *inherit_path = parser->ws->getPathNamed(pathname, false); if (inherit_path == path) { parser->warning("path %s cannot inherit itself\n", path->name); } else if (inherit_path) { path->inheritContent(inherit_path); } else { if (! ignore_missing) parser->warning("undefined path: %s\n", pathname); } delete [] pathname; } static const ParserElementMap rendertext_element_map[] = { { "inherit", ParserElementInherit } }; ParserElement RenderOpTextElementHandler::elementMap(const XML_Char *name) { Tst::iterator it = rendertext_element_tst->find((char *) name); if (it != rendertext_element_tst->end()) return *it; else return ParserElementNone; } RenderOpTextElementHandler::RenderOpTextElementHandler( CfgElementHandler *_cfg_handler, RenderOpText *_text, RenderGroup *_rendergroup) : ElementHandler(_cfg_handler->parser) { text = _text; rendergroup = _rendergroup; cfg_handler = _cfg_handler; } bool RenderOpTextElementHandler::startElement(ParserElement element, const XML_Char *, Tst *attr) { switch (element) { case ParserElementInherit: { RenderOpTextInheritElementHandler *handler = new RenderOpTextInheritElementHandler(cfg_handler, &strbuf, attr); parser->pushElementHandler(handler); return true; } break; default: break; } return false; } void RenderOpTextElementHandler::characters(const XML_Char *chars, int len) { strbuf.addString((char *) chars, len); } void RenderOpTextElementHandler::endElement(const XML_Char *) { char *utf8 = strbuf.getString(); bool dynamic; if (! text->is_static) { text->is_static = true; text->utf8 = preexpand(utf8, &dynamic); if (dynamic) { text->is_static = false; if (rendergroup) rendergroup->cacheable = false; } } else { text->is_static = true; text->utf8 = WA_STRDUP(utf8); } if (rendergroup) rendergroup->operations.push_back(text); delete [] utf8; } RenderOpTextInheritElementHandler::RenderOpTextInheritElementHandler( CfgElementHandler *_cfg_handler, StringBuffer *_textstrbuf, Tst *attr) : InheritElementHandler(_cfg_handler, attr) { textstrbuf = _textstrbuf; } void RenderOpTextInheritElementHandler::endElement(const XML_Char *) { char *textname = strbuf.getString(); RenderOpText *inherit_text = parser->ws->getTextNamed(textname, false); if (inherit_text) { if (inherit_text->utf8) textstrbuf->addString((char *) inherit_text->utf8, strlen(inherit_text->utf8)); } else { if (! ignore_missing) parser->warning("undefined text object: %s\n", textname); } delete [] textname; } double get_double_and_unit(char *s, LenghtUnitType *unit) { char *invalid_char; double value = strtod(s, &invalid_char); if (unit) if (invalid_char) { if (! strcasecmp(invalid_char, "%")) { *unit = PCTLenghtUnitType; } else if (! strcasecmp(invalid_char, "px")) { *unit = PXLenghtUnitType; } else if (! strcasecmp(invalid_char, "cm")) { *unit = CMLenghtUnitType; } else if (! strcasecmp(invalid_char, "mm")) { *unit = MMLenghtUnitType; } else if (! strcasecmp(invalid_char, "in")) { *unit = INLenghtUnitType; } else if (! strcasecmp(invalid_char, "pt")) { *unit = PTLenghtUnitType; } else if (! strcasecmp(invalid_char, "pc")) { *unit = PCLenghtUnitType; } else { *unit = PXLenghtUnitType; } } else *unit = PXLenghtUnitType; return value; } void parser_create_tsts(void) { int size, i; win_state_tst = new Tst; size = sizeof(win_state_map) / sizeof(WindowStateMap); for (i = 0; i < size; i++) win_state_tst->insert(win_state_map[i].name, win_state_map[i].state); x11_modifier_tst = new Tst; size = sizeof(x11_modifier_map) / sizeof(ModifierMap); for (i = 0; i < size; i++) x11_modifier_tst->insert(x11_modifier_map[i].name, x11_modifier_map[i].modifier); wa_modifier_tst = new Tst; size = sizeof(wa_modifier_map) / sizeof(ModifierMap); for (i = 0; i < size; i++) wa_modifier_tst->insert(wa_modifier_map[i].name, wa_modifier_map[i].modifier); dynamic_try_tst = new Tst; size = sizeof(dynamic_try_map) / sizeof(DynamicTryMap); for (i = 0; i < size; i++) dynamic_try_tst->insert(dynamic_try_map[i].name, dynamic_try_map[i].type); cfg_element_tst = new Tst; size = sizeof(cfg_element_map) / sizeof(ParserElementMap); for (i = 0; i < size; i++) cfg_element_tst->insert(cfg_element_map[i].name, cfg_element_map[i].element); actionlist_element_tst = new Tst; size = sizeof(actionlist_element_map) / sizeof(ParserElementMap); for (i = 0; i < size; i++) actionlist_element_tst->insert(actionlist_element_map[i].name, actionlist_element_map[i].element); action_element_tst = new Tst; size = sizeof(action_element_map) / sizeof(ParserElementMap); for (i = 0; i < size; i++) action_element_tst->insert(action_element_map[i].name, action_element_map[i].element); menu_element_tst = new Tst; size = sizeof(menu_element_map) / sizeof(ParserElementMap); for (i = 0; i < size; i++) menu_element_tst->insert(menu_element_map[i].name, menu_element_map[i].element); menuitem_element_tst = new Tst; size = sizeof(menuitem_element_map) / sizeof(ParserElementMap); for (i = 0; i < size; i++) menuitem_element_tst->insert(menuitem_element_map[i].name, menuitem_element_map[i].element); rendergroup_element_tst = new Tst; size = sizeof(rendergroup_element_map) / sizeof(ParserElementMap); for (i = 0; i < size; i++) rendergroup_element_tst->insert(rendergroup_element_map[i].name, rendergroup_element_map[i].element); renderopdynamic_element_tst = new Tst; size = sizeof(renderopdynamic_element_map) / sizeof(ParserElementMap); for (i = 0; i < size; i++) renderopdynamic_element_tst->insert( renderopdynamic_element_map[i].name, renderopdynamic_element_map[i].element); renderpath_element_tst = new Tst; size = sizeof(renderpath_element_map) / sizeof(ParserElementMap); for (i = 0; i < size; i++) renderpath_element_tst->insert(renderpath_element_map[i].name, renderpath_element_map[i].element); renderpattern_element_tst = new Tst; size = sizeof(renderpattern_element_map) / sizeof(ParserElementMap); for (i = 0; i < size; i++) renderpattern_element_tst->insert (renderpattern_element_map[i].name, renderpattern_element_map[i].element); rendertext_element_tst = new Tst; size = sizeof(rendertext_element_map) / sizeof(ParserElementMap); for (i = 0; i < size; i++) rendertext_element_tst->insert(rendertext_element_map[i].name, rendertext_element_map[i].element); }