Пример #1
0
/**
 * @brief Initialize a node behaviour memory, after registration, and before unsing it.
 * @param behaviour Behaviour to initialize
 */
void UI_InitializeNodeBehaviour (uiBehaviour_t* behaviour)
{
	if (behaviour->isInitialized)
		return;

	/* everything inherits 'abstractnode' */
	if (behaviour->extends == NULL && !Q_streq(behaviour->name, "abstractnode")) {
		behaviour->extends = "abstractnode";
	}

	if (behaviour->extends) {
		int i = 0;

		/** TODO Find a way to remove that, if possible */
		behaviour->super = UI_GetNodeBehaviour(behaviour->extends);
		UI_InitializeNodeBehaviour(behaviour->super);

		while (qtrue) {
			const size_t pos = virtualFunctions[i];
			uintptr_t superFunc;
			uintptr_t func;
			if (pos == -1)
				break;

			/* cache super function if we don't overwrite it */
			superFunc = *(uintptr_t*)((byte*)behaviour->super + pos);
			func = *(uintptr_t*)((byte*)behaviour + pos);
			if (func == 0 && superFunc != 0)
				*(uintptr_t*)((byte*)behaviour + pos) = superFunc;

			i++;
		}
	}

	/* sort properties by alphabet */
	if (behaviour->localProperties) {
		int i = 0;
		const value_t* previous;
		const value_t** oldmemory = behaviour->localProperties;
		behaviour->localProperties = UI_AllocHunkMemory(sizeof(value_t*) * (behaviour->propertyCount+1), STRUCT_MEMORY_ALIGN, qfalse);
		if (behaviour->localProperties == NULL) {
			Com_Error(ERR_FATAL, "UI_InitializeNodeBehaviour: UI memory hunk exceeded - increase the size");
		}

		previous = NULL;
		for (i = 0; i < behaviour->propertyCount; i++) {
			const value_t* better = NULL;
			const value_t** current;
			/* search the next element after previous */
			for (current = oldmemory; *current != NULL; current++) {
				if (previous != NULL && Q_strcasecmp(previous->string, (*current)->string) >= 0) {
					continue;
				}
				if (better == NULL || Q_strcasecmp(better->string, (*current)->string) >= 0) {
					better = *current;
				}
			}
			previous = better;
			behaviour->localProperties[i] = better;
		}
		behaviour->localProperties[behaviour->propertyCount] = NULL;
		Mem_Free(oldmemory);
	}

	/* property must not overwrite another property */
	if (behaviour->super && behaviour->localProperties) {
		const value_t** property = behaviour->localProperties;
		while (*property) {
			const value_t *p = UI_GetPropertyFromBehaviour(behaviour->super, (*property)->string);
#if 0	/**< @todo not possible at the moment, not sure its the right way */
			const uiBehaviour_t *b = UI_GetNodeBehaviour(current->string);
#endif
			if (p != NULL)
				Com_Error(ERR_FATAL, "UI_InitializeNodeBehaviour: property '%s' from node behaviour '%s' overwrite another property", (*property)->string, behaviour->name);
#if 0	/**< @todo not possible at the moment, not sure its the right way */
			if (b != NULL)
				Com_Error(ERR_FATAL, "UI_InitializeNodeBehaviour: property '%s' from node behaviour '%s' use the name of an existing node behaviour", (*property)->string, behaviour->name);
#endif
			property++;
		}
	}

	/* Sanity: A property must not be outside the node memory */
	if (behaviour->localProperties) {
		const int size = sizeof(uiNode_t) + behaviour->extraDataSize;
		const value_t** property = behaviour->localProperties;
		while (*property) {
			if ((*property)->type != V_UI_NODEMETHOD && (*property)->ofs + (*property)->size > size)
				Com_Error(ERR_FATAL, "UI_InitializeNodeBehaviour: property '%s' from node behaviour '%s' is outside the node memory. The C code need a fix.", (*property)->string, behaviour->name);
			property++;
		}
	}

	behaviour->isInitialized = qtrue;
}
Пример #2
0
/**
 * @brief Replace injection identifiers (e.g. &lt;eventParam&gt;) by a value
 * @note The injection identifier can be every node value - e.g. &lt;image&gt; or &lt;width&gt;.
 * It's also possible to do something like
 * @code
 * cmd "set someCvar &lt;min&gt;/&lt;max&gt;"
 * @endcode
 */
const char* UI_GenInjectedString (const char* input, qboolean addNewLine, const uiCallContext_t *context)
{
	static char cmd[256];
	int length = sizeof(cmd) - (addNewLine ? 2 : 1);
	static char propertyName[MAX_VAR];
	const char *cin = input;
	char *cout = cmd;

	while (length && cin[0] != '\0') {
		if (cin[0] == '<') {
			/* read propertyName between '<' and '>' */
			const char *next = UI_GenCommandReadProperty(cin, propertyName, sizeof(propertyName));
			if (next) {
				/* cvar injection */
				if (Q_strstart(propertyName, "cvar:")) {
					const cvar_t *cvar = Cvar_Get(propertyName + 5, "", 0, NULL);
					const int l = snprintf(cout, length, "%s", cvar->string);
					cout += l;
					cin = next;
					length -= l;
					continue;

				} else if (Q_strstart(propertyName, "node:")) {
					const char *path = propertyName + 5;
					uiNode_t *node;
					const value_t *property;
					const char* string;
					int l;
					UI_ReadNodePath(path, context->source, &node, &property);
					if (!node) {
						Com_Printf("UI_GenInjectedString: Node '%s' wasn't found; '' returned\n", path);
#ifdef DEBUG
						Com_Printf("UI_GenInjectedString: Path relative to '%s'\n", UI_GetPath(context->source));
#endif
						string = "";
					} else if (!property) {
						Com_Printf("UI_GenInjectedString: Property '%s' wasn't found; '' returned\n", path);
						string = "";
					} else {
						string = UI_GetStringFromNodeProperty(node, property);
						if (string == NULL) {
							Com_Printf("UI_GenInjectedString: String getter for '%s' property do not exists; '' injected\n", path);
							string = "";
						}
					}

					l = snprintf(cout, length, "%s", string);
					cout += l;
					cin = next;
					length -= l;
					continue;

				/* source path injection */
				} else if (Q_strstart(propertyName, "path:")) {
					if (context->source) {
						const char *command = propertyName + 5;
						const uiNode_t *node = NULL;
						if (Q_streq(command, "root"))
							node = context->source->root;
						else if (Q_streq(command, "this"))
							node = context->source;
						else if (Q_streq(command, "parent"))
							node = context->source->parent;
						else
							Com_Printf("UI_GenCommand: Command '%s' for path injection unknown\n", command);

						if (node) {
							const int l = snprintf(cout, length, "%s", UI_GetPath(node));
							cout += l;
							cin = next;
							length -= l;
							continue;
						}
					}

				/* no prefix */
				} else {
					/* source property injection */
					if (context->source) {
						/* find property definition */
						const value_t *property = UI_GetPropertyFromBehaviour(context->source->behaviour, propertyName);
						if (property) {
							const char* value;
							int l;
							/* inject the property value */
							value = UI_GetStringFromNodeProperty(context->source, property);
							if (value == NULL)
								value = "";
							l = snprintf(cout, length, "%s", value);
							cout += l;
							cin = next;
							length -= l;
							continue;
						}
					}

					/* param injection */
					if (UI_GetParamNumber(context) != 0) {
						int arg;
						const int checked = sscanf(propertyName, "%d", &arg);
						if (checked == 1 && arg >= 1 && arg <= UI_GetParamNumber(context)) {
							const int l = snprintf(cout, length, "%s", UI_GetParam(context, arg));
							cout += l;
							cin = next;
							length -= l;
							continue;
						}
					}
				}
			}
		}
		*cout++ = *cin++;
		length--;
	}

	/* is buffer too small? */
	assert(cin[0] == '\0');

	if (addNewLine)
		*cout++ = '\n';

	*cout++ = '\0';

	/* copy the result into a free va slot */
	return va("%s", cmd);
}