/** * @brief Parse a property value * @todo don't read the next token (need to change the script language) */ static bool UI_ParseProperty (void* object, const value_t* property, const char* objectName, const char** text, const char** token) { const char* errhead = "UI_ParseProperty: unexpected end of file (object"; static const char* notWellFormedValue = "UI_ParseProperty: \"%s\" is not a well formed node name (it must be quoted, uppercase const, a number, or prefixed with '*')\n"; size_t bytes; int result; const int specialType = property->type & V_UI_MASK; if (property->type == V_NULL) { return false; } switch (specialType) { case V_NOT_UI: /* common type */ *token = Com_EParse(text, errhead, objectName); if (!*text) return false; if (!UI_TokenIsValue(*token, Com_GetType(text) == TT_QUOTED_WORD)) { Com_Printf(notWellFormedValue, *token); return false; } if (property->type == V_TRANSLATION_STRING) { /* selectbox values are static arrays */ char* const target = Com_GetValue<char[]>(object, property); const char* translatableToken = *token; assert(property->size); if (translatableToken[0] == '_') translatableToken++; Q_strncpyz(target, translatableToken, property->size); } else { result = Com_ParseValue(object, *token, property->type, property->ofs, property->size, &bytes); if (result != RESULT_OK) { Com_Printf("UI_ParseProperty: Invalid value for property '%s': %s\n", property->string, Com_GetLastParseError()); return false; } } break; case V_UI_REF: *token = Com_EParse(text, errhead, objectName); if (!*text) return false; if (!UI_TokenIsValue(*token, Com_GetType(text) == TT_QUOTED_WORD)) { Com_Printf(notWellFormedValue, *token); return false; } /* a reference to data is handled like this */ ui_global.curadata = (byte*) Com_AlignPtr(ui_global.curadata, (valueTypes_t) (property->type & V_BASETYPEMASK)); Com_GetValue<byte*>(object, property) = ui_global.curadata; /** @todo check for the moment its not a cvar */ assert((*token)[0] != '*'); /* sanity check */ if ((property->type & V_BASETYPEMASK) == V_STRING && strlen(*token) > MAX_VAR - 1) { Com_Printf("UI_ParseProperty: Value '%s' is too long (key %s)\n", *token, property->string); return false; } result = Com_ParseValue(ui_global.curadata, *token, (valueTypes_t) (property->type & V_BASETYPEMASK), 0, property->size, &bytes); if (result != RESULT_OK) { Com_Printf("UI_ParseProperty: Invalid value for property '%s': %s\n", property->string, Com_GetLastParseError()); return false; } ui_global.curadata += bytes; break; case V_UI_CVAR: /* common type */ *token = Com_EParse(text, errhead, objectName); if (!*text) return false; if (!UI_TokenIsValue(*token, Com_GetType(text) == TT_QUOTED_WORD)) { Com_Printf(notWellFormedValue, *token); return false; } /* references are parsed as string */ if ((*token)[0] == '*') { /* a reference to data */ ui_global.curadata = (byte*) Com_AlignPtr(ui_global.curadata, V_STRING); Com_GetValue<byte*>(object, property) = ui_global.curadata; /* sanity check */ if (strlen(*token) > MAX_VAR - 1) { Com_Printf("UI_ParseProperty: Value '%s' is too long (key %s)\n", *token, property->string); return false; } result = Com_ParseValue(ui_global.curadata, *token, V_STRING, 0, 0, &bytes); if (result != RESULT_OK) { Com_Printf("UI_ParseProperty: Invalid value for property '%s': %s\n", property->string, Com_GetLastParseError()); return false; } ui_global.curadata += bytes; } else { /* a reference to data */ ui_global.curadata = (byte*) Com_AlignPtr(ui_global.curadata, (valueTypes_t)(property->type & V_BASETYPEMASK)); Com_GetValue<byte*>(object, property) = ui_global.curadata; /* sanity check */ if ((property->type & V_BASETYPEMASK) == V_STRING && strlen(*token) > MAX_VAR - 1) { Com_Printf("UI_ParseProperty: Value '%s' is too long (key %s)\n", *token, property->string); return false; } result = Com_ParseValue(ui_global.curadata, *token, (valueTypes_t)(property->type & V_BASETYPEMASK), 0, property->size, &bytes); if (result != RESULT_OK) { Com_Printf("UI_ParseProperty: Invalid value for property '%s': %s\n", property->string, Com_GetLastParseError()); return false; } ui_global.curadata += bytes; } break; case V_UI: switch ((int)property->type) { case V_UI_ACTION: result = UI_ParseEventProperty(static_cast<uiNode_t*>(object), property, text, token, errhead); if (!result) return false; break; case V_UI_EXCLUDERECT: result = UI_ParseExcludeRect(static_cast<uiNode_t*>(object), text, token, errhead); if (!result) return false; break; case V_UI_SPRITEREF: { *token = Com_EParse(text, errhead, objectName); if (!*text) return false; uiSprite_t const*& sprite = Com_GetValue<uiSprite_t const*>(object, property); sprite = UI_GetSpriteByName(*token); if (!sprite) { Com_Printf("UI_ParseProperty: sprite '%s' not found (object %s)\n", *token, objectName); } } break; case V_UI_IF: { *token = Com_EParse(text, errhead, objectName); if (!*text) return false; uiAction_t*& expression = Com_GetValue<uiAction_t*>(object, property); expression = UI_AllocStaticStringCondition(*token); if (!expression) return false; } break; case V_UI_DATAID: { *token = Com_EParse(text, errhead, objectName); if (!*text) return false; int& dataId = Com_GetValue<int>(object, property); dataId = UI_GetDataIDByName(*token); if (dataId < 0) { Com_Printf("UI_ParseProperty: Could not find shared data ID '%s' (%s@%s)\n", *token, objectName, property->string); return false; } } break; default: Com_Printf("UI_ParseProperty: unknown property type '%d' (0x%X) (%s@%s)\n", property->type, property->type, objectName, property->string); return false; } break; default: Com_Printf("UI_ParseProperties: unknown property type '%d' (0x%X) (%s@%s)\n", property->type, property->type, objectName, property->string); return false; } return true; }
/** * @brief Set node property */ bool UI_NodeSetProperty (uiNode_t* node, const value_t* property, const char* value) { const int specialType = property->type & V_UI_MASK; int result; size_t bytes; switch (specialType) { case V_NOT_UI: /* common type */ result = Com_ParseValue(node, value, property->type, property->ofs, property->size, &bytes); if (result != RESULT_OK) { Com_Printf("UI_NodeSetProperty: Invalid value for property '%s': %s\n", property->string, Com_GetLastParseError()); return false; } UI_Node_PropertyChanged(node, property); return true; case V_UI_CVAR: /* cvar */ switch ((int)property->type) { case V_UI_CVAR: if (Q_strstart(value, "*cvar:")) { char*& b = Com_GetValue<char*>(node, property); UI_FreeStringProperty(b); b = Mem_PoolStrDup(value, ui_dynStringPool, 0); UI_Node_PropertyChanged(node, property); return true; } break; case V_CVAR_OR_FLOAT: { float f; if (Q_strstart(value, "*cvar:")) { char*& b = Com_GetValue<char*>(node, property); UI_FreeStringProperty(b); b = Mem_PoolStrDup(value, ui_dynStringPool, 0); UI_Node_PropertyChanged(node, property); return true; } result = Com_ParseValue(&f, value, V_FLOAT, 0, sizeof(f), &bytes); if (result != RESULT_OK) { Com_Printf("UI_NodeSetProperty: Invalid value for property '%s': %s\n", property->string, Com_GetLastParseError()); return false; } void* const b = Com_GetValue<void*>(node, property); if (char const* const cvar = Q_strstart((char const*)b, "*cvar:")) Cvar_SetValue(cvar, f); else *(float*) b = f; UI_Node_PropertyChanged(node, property); return true; } case V_CVAR_OR_LONGSTRING: case V_CVAR_OR_STRING: { char*& b = Com_GetValue<char*>(node, property); UI_FreeStringProperty(b); b = Mem_PoolStrDup(value, ui_dynStringPool, 0); UI_Node_PropertyChanged(node, property); return true; } } break; case V_UI: switch ((int)property->type) { case V_UI_SPRITEREF: { uiSprite_t* sprite = UI_GetSpriteByName(value); Com_GetValue<uiSprite_t const*>(node, property) = sprite; UI_Node_PropertyChanged(node, property); return true; } } break; } Com_Printf("UI_NodeSetProperty: Unimplemented type for property '%s@%s'\n", UI_GetPath(node), property->string); return false; }