Example #1
0
/**
 * @brief Read a path and return every we can use (node and property)
 * @details The path token must be a window name, and then node child.
 * Reserved token 'root' and 'parent' can be used to navigate.
 * If relativeNode is set, the path can start with reserved token
 * 'this', 'root' and 'parent' (relative to this node).
 * The function can return a node property by using a '\@',
 * the path 'foo\@pos' will return the window foo and the property 'pos'
 * from the 'window' behaviour.
 * @param[in] path Path to read. Contain a node location with dot seprator and a facultative property
 * @param[in] relativeNode relative node where the path start. It allow to use facultative command to start the path (this, parent, root).
 * @param[out] resultNode Node found. Else NULL.
 * @param[out] resultProperty Property found. Else NULL.
 * TODO Speed up, evilly used function, use strncmp instead of using buffer copy (name[MAX_VAR])
 */
void UI_ReadNodePath (const char* path, const uiNode_t *relativeNode, uiNode_t **resultNode, const value_t **resultProperty)
{
	char name[MAX_VAR];
	uiNode_t* node = NULL;
	const char* nextName;
	char nextCommand = '^';

	*resultNode = NULL;
	if (resultProperty)
		*resultProperty = NULL;

	nextName = path;
	while (nextName && nextName[0] != '\0') {
		const char* begin = nextName;
		char command = nextCommand;
		nextName = strpbrk(begin, ".@#");
		if (!nextName) {
			Q_strncpyz(name, begin, sizeof(name));
			nextCommand = '\0';
		} else {
			assert(nextName - begin + 1 <= sizeof(name));
			Q_strncpyz(name, begin, nextName - begin + 1);
			nextCommand = *nextName;
			nextName++;
		}

		switch (command) {
		case '^':	/* first string */
			if (Q_streq(name, "this")) {
				if (relativeNode == NULL)
					return;
				/** @todo find a way to fix the bad cast. only here to remove "discards qualifiers" warning */
				node = *(uiNode_t**) ((void*)&relativeNode);
			} else if (Q_streq(name, "parent")) {
				if (relativeNode == NULL)
					return;
				node = relativeNode->parent;
			} else if (Q_streq(name, "root")) {
				if (relativeNode == NULL)
					return;
				node = relativeNode->root;
			} else
				node = UI_GetWindow(name);
			break;
		case '.':	/* child node */
			if (Q_streq(name, "parent"))
				node = node->parent;
			else if (Q_streq(name, "root"))
				node = node->root;
			else
				node = UI_GetNode(node, name);
			break;
		case '#':	/* window index */
			/** @todo FIXME use a warning instead of an assert */
			assert(node->behaviour == ui_windowBehaviour);
			node = UI_WindowNodeGetIndexedChild(node, name);
			break;
		case '@':	/* property */
			assert(nextCommand == '\0');
			*resultProperty = UI_GetPropertyFromBehaviour(node->behaviour, name);
			*resultNode = node;
			return;
		}

		if (!node)
			return;
	}

	*resultNode = node;
	return;
}
Example #2
0
/**
 * @brief Read a path and return every we can use (node and property)
 * @details The path token must be a window name, and then node child.
 * Reserved token 'root' and 'parent' can be used to navigate.
 * If relativeNode is set, the path can start with reserved token
 * 'this', 'root', 'parent' and 'child' (relative to this node).
 * The function can return a node property by using a '\@',
 * the path 'foo\@pos' will return the window foo and the property 'pos'
 * from the 'window' behaviour.
 * @param[in] path Path to read. Contain a node location with dot seprator and a facultative property
 * @param[in] relativeNode relative node where the path start. It allow to use facultative command to start the path (this, parent, root).
 * @param[in] iterationNode relative node referencing child in 'forchildin' iteration, mapped to '*node:child', can be nullptr
 * @param[out] resultNode Node found. Else nullptr.
 * @param[out] resultProperty Property found. Else nullptr.
 * @param[in,out] luaMethod A pointer to a value_t structure that is filled with a lua based method identification, can be nullptr
 * @note If luaMethod is set, the method will scan the known lua methods defined on the behaviour. If luaMethod is not set, only
 * registered local properties are scanned.
 * @todo Speed up, evilly used function, use strncmp instead of using buffer copy (name[MAX_VAR])
 * @note If luaMethod is set, make sure to release the allocated .name string.
 */
void UI_ReadNodePath (const char* path, const uiNode_t* relativeNode, const uiNode_t* iterationNode, uiNode_t** resultNode, const value_t** resultProperty, value_t *luaMethod) {
	char name[MAX_VAR];
	uiNode_t* node = nullptr;
	uiNode_t* childnode = nullptr;
	const char* nextName;
	char nextCommand = '^';

	*resultNode = nullptr;
	if (resultProperty)
		*resultProperty = nullptr;

	nextName = path;
	while (nextName && nextName[0] != '\0') {
		const char* begin = nextName;
		char command = nextCommand;
		nextName = strpbrk(begin, ".@#");
		if (!nextName) {
			Q_strncpyz(name, begin, sizeof(name));
			nextCommand = '\0';
		} else {
			assert(nextName - begin + 1 <= sizeof(name));
			Q_strncpyz(name, begin, nextName - begin + 1);
			nextCommand = *nextName;
			nextName++;
		}

		switch (command) {
		case '^':	/* first string */
			if (Q_streq(name, "this")) {
				if (relativeNode == nullptr)
					return;
				node = const_cast<uiNode_t *>(relativeNode);
			} else if (Q_streq(name, "parent")) {
				if (relativeNode == nullptr)
					return;
				node = relativeNode->parent;
			} else if (Q_streq(name, "root")) {
				if (relativeNode == nullptr)
					return;
				node = relativeNode->root;
			} else if (Q_streq(name, "child")) {
				if (iterationNode == nullptr)
					return;
				node = const_cast<uiNode_t *>(iterationNode);
			} else
				node = UI_GetWindow(name);
			break;
		case '.':	/* child node */
			if (Q_streq(name, "parent"))
				childnode = node->parent;
			else if (Q_streq(name, "root"))
				childnode = node->root;
			else {
				childnode = UI_GetNode(node, name);
				/* if no node found and if we need it, then it is possible we call a lua based function */
				if (luaMethod && !childnode) {
					*resultProperty = UI_GetPropertyOrLuaMethod(node, name, luaMethod);
					if (luaMethod->type) {
						childnode = node;
					}
				}
			}
			node = childnode;
			break;
		case '#':	/* window index */
			/** @todo FIXME use a warning instead of an assert */
			assert(UI_Node_IsWindow(node));
			node = UI_WindowNodeGetIndexedChild(node, name);
			break;
		case '@':	/* property */
			assert(nextCommand == '\0');
			*resultProperty = UI_GetPropertyOrLuaMethod(node, name, luaMethod);
			*resultNode = node;
			return;
		}

		if (!node)
			return;
	}

	*resultNode = node;
	return;
}