Ejemplo n.º 1
0
/* SAction::initActions
 * Loads and parses all SActions configured in actions.cfg in the
 * program resource archive
 *******************************************************************/
bool SAction::initActions()
{
	// Get actions.cfg from slade.pk3
	auto cfg_entry = theArchiveManager->programResourceArchive()->entryAtPath("actions.cfg");
	if (!cfg_entry)
		return false;

	Parser parser(cfg_entry->getParentDir());
	if (parser.parseText(cfg_entry->getMCData(), "actions.cfg"))
	{
		auto root = parser.parseTreeRoot();
		for (unsigned a = 0; a < root->nChildren(); a++)
		{
			auto node = root->getChildPTN(a);

			// Single action
			if (S_CMPNOCASE(node->type(), "action"))
			{
				auto action = new SAction(node->getName(), node->getName());
				if (action->parse(node))
					actions.push_back(action);
				else
					delete action;
			}

			// Group of actions
			else if (S_CMPNOCASE(node->getName(), "group"))
			{
				int group = newGroup();

				for (unsigned b = 0; b < node->nChildren(); b++)
				{
					auto group_node = node->getChildPTN(b);
					if (S_CMPNOCASE(group_node->type(), "action"))
					{
						auto action = new SAction(group_node->getName(), group_node->getName());
						if (action->parse(group_node))
						{
							action->group = group;
							actions.push_back(action);
						}
						else
							delete action;
					}
				}
			}
		}
	}

	return true;
}
Ejemplo n.º 2
0
vguard<TreeNodeIndex> Tree::rerootedChildren (TreeNodeIndex node, TreeNodeIndex parent) const {
  vguard<TreeNodeIndex> children;
  for (int c = 0; c < nChildren(node); ++c)
    if (getChild(node,c) != parent)
      children.push_back (getChild(node,c));
  if (parentNode(node) >= 0 && parentNode(node) != parent)
    children.push_back (parentNode(node));
  return children;
}
Ejemplo n.º 3
0
/* Executables::parse
 * Parses an executables configuration from [p]
 *******************************************************************/
void Executables::parse(Parser* p, bool custom)
{
	auto n = p->parseTreeRoot()->getChildPTN("executables");
	if (!n) return;

	for (unsigned a = 0; a < n->nChildren(); a++)
	{
		auto exe_node = n->getChildPTN(a);
		string type = exe_node->type();

		// Game Executable (if type is blank it's a game executable in old config format)
		if (type == "game_exe" || type.IsEmpty())
			parseGameExe(exe_node, custom);

		// External Executable
		else if (type == "external_exe")
			parseExternalExe(exe_node);
	}
}
Ejemplo n.º 4
0
/* EntryDataFormat::readDataFormatDefinition
 * Parses a user data format definition (unimplemented, currently)
 *******************************************************************/
bool EntryDataFormat::readDataFormatDefinition(MemChunk& mc)
{
	// Parse the definition
	Parser p;
	p.parseText(mc);

	// Get data_formats tree
	auto pt_formats = p.parseTreeRoot()->getChildPTN("data_formats");

	// Check it exists
	if (!pt_formats)
		return false;

	// Go through all parsed types
	for (unsigned a = 0; a < pt_formats->nChildren(); a++)
	{
		// Get child as ParseTreeNode
		auto formatnode = pt_formats->getChildPTN(a);

		// Create+add new data format
		EntryDataFormat* edf = new EntryDataFormat(formatnode->getName().Lower());

		/*
		// Copy from existing type if inherited
		if (!formatnode->getInherit().IsEmpty())
		{
			EntryType* parent_type = EntryType::getType(formatnode->getInherit());

			if (parent_type != EntryType::unknownType())
				parent_type->copyToType(ntype);
			else
				LOG_MESSAGE(1, "Warning: Entry type %s inherits from unknown type %s", ntype->getId(), typenode->getInherit());
		}
		*/
	}
	return true;
}
Ejemplo n.º 5
0
// ----------------------------------------------------------------------------
// TextLanguage::readLanguageDefinition
//
// Reads in a text definition of a language. See slade.pk3 for
// formatting examples
// ----------------------------------------------------------------------------
bool TextLanguage::readLanguageDefinition(MemChunk& mc, string source)
{
	Tokenizer tz;

	// Open the given text data
	if (!tz.openMem(mc, source))
	{
		Log::warning(1, S_FMT("Warning: Unable to open %s", source));
		return false;
	}

	// Parse the definition text
	ParseTreeNode root;
	if (!root.parse(tz))
		return false;

	// Get parsed data
	for (unsigned a = 0; a < root.nChildren(); a++)
	{
		auto node = root.getChildPTN(a);

		// Create language
		TextLanguage* lang = new TextLanguage(node->getName());

		// Check for inheritance
		if (!node->inherit().IsEmpty())
		{
			TextLanguage* inherit = fromId(node->inherit());
			if (inherit)
				inherit->copyTo(lang);
			else
				Log::warning(
					1,
					S_FMT("Warning: Language %s inherits from undefined language %s",
						  node->getName(),
						  node->inherit())
				);
		}

		// Parse language info
		for (unsigned c = 0; c < node->nChildren(); c++)
		{
			auto child = node->getChildPTN(c);

			// Language name
			if (S_CMPNOCASE(child->getName(), "name"))
				lang->setName(child->stringValue());

			// Comment begin
			else if (S_CMPNOCASE(child->getName(), "comment_begin"))
			{
				lang->setCommentBeginList(child->stringValues());
			}

			// Comment end
			else if (S_CMPNOCASE(child->getName(), "comment_end"))
			{
				lang->setCommentEndList(child->stringValues());
			}

			// Line comment
			else if (S_CMPNOCASE(child->getName(), "comment_line"))
			{
				lang->setLineCommentList(child->stringValues());
			}

			// Preprocessor
			else if (S_CMPNOCASE(child->getName(), "preprocessor"))
				lang->setPreprocessor(child->stringValue());

			// Case sensitive
			else if (S_CMPNOCASE(child->getName(), "case_sensitive"))
				lang->setCaseSensitive(child->boolValue());

			// Doc comment
			else if (S_CMPNOCASE(child->getName(), "comment_doc"))
				lang->setDocComment(child->stringValue());

			// Keyword lookup link
			else if (S_CMPNOCASE(child->getName(), "keyword_link"))
				lang->word_lists_[WordType::Keyword].lookup_url = child->stringValue();

			// Constant lookup link
			else if (S_CMPNOCASE(child->getName(), "constant_link"))
				lang->word_lists_[WordType::Constant].lookup_url = child->stringValue();

			// Function lookup link
			else if (S_CMPNOCASE(child->getName(), "function_link"))
				lang->f_lookup_url_ = child->stringValue();

			// Jump blocks
			else if (S_CMPNOCASE(child->getName(), "blocks"))
			{
				for (unsigned v = 0; v < child->nValues(); v++)
					lang->jump_blocks_.push_back(child->stringValue(v));
			}
			else if (S_CMPNOCASE(child->getName(), "blocks_ignore"))
			{
				for (unsigned v = 0; v < child->nValues(); v++)
					lang->jb_ignore_.push_back(child->stringValue(v));
			}

			// Block begin
			else if (S_CMPNOCASE(child->getName(), "block_begin"))
				lang->block_begin_ = child->stringValue();

			// Block end
			else if (S_CMPNOCASE(child->getName(), "block_end"))
				lang->block_end_ = child->stringValue();

			// Preprocessor block begin
			else if (S_CMPNOCASE(child->getName(), "pp_block_begin"))
			{
				for (unsigned v = 0; v < child->nValues(); v++)
					lang->pp_block_begin_.push_back(child->stringValue(v));
			}

			// Preprocessor block end
			else if (S_CMPNOCASE(child->getName(), "pp_block_end"))
			{
				for (unsigned v = 0; v < child->nValues(); v++)
					lang->pp_block_end_.push_back(child->stringValue(v));
			}

			// Word block begin
			else if (S_CMPNOCASE(child->getName(), "word_block_begin"))
			{
				for (unsigned v = 0; v < child->nValues(); v++)
					lang->word_block_begin_.push_back(child->stringValue(v));
			}

			// Word block end
			else if (S_CMPNOCASE(child->getName(), "word_block_end"))
			{
				for (unsigned v = 0; v < child->nValues(); v++)
					lang->word_block_end_.push_back(child->stringValue(v));
			}

			// Keywords
			else if (S_CMPNOCASE(child->getName(), "keywords"))
			{
				// Go through values
				for (unsigned v = 0; v < child->nValues(); v++)
				{
					string val = child->stringValue(v);

					// Check for '$override'
					if (S_CMPNOCASE(val, "$override"))
					{
						// Clear any inherited keywords
						lang->clearWordList(WordType::Keyword);
					}

					// Not a special symbol, add as keyword
					else
						lang->addWord(WordType::Keyword, val);
				}
			}

			// Constants
			else if (S_CMPNOCASE(child->getName(), "constants"))
			{
				// Go through values
				for (unsigned v = 0; v < child->nValues(); v++)
				{
					string val = child->stringValue(v);

					// Check for '$override'
					if (S_CMPNOCASE(val, "$override"))
					{
						// Clear any inherited constants
						lang->clearWordList(WordType::Constant);
					}

					// Not a special symbol, add as constant
					else
						lang->addWord(WordType::Constant, val);
				}
			}

			// Types
			else if (S_CMPNOCASE(child->getName(), "types"))
			{
				// Go through values
				for (unsigned v = 0; v < child->nValues(); v++)
				{
					string val = child->stringValue(v);

					// Check for '$override'
					if (S_CMPNOCASE(val, "$override"))
					{
						// Clear any inherited constants
						lang->clearWordList(WordType::Type);
					}

					// Not a special symbol, add as constant
					else
						lang->addWord(WordType::Type, val);
				}
			}

			// Properties
			else if (S_CMPNOCASE(child->getName(), "properties"))
			{
				// Go through values
				for (unsigned v = 0; v < child->nValues(); v++)
				{
					string val = child->stringValue(v);

					// Check for '$override'
					if (S_CMPNOCASE(val, "$override"))
					{
						// Clear any inherited constants
						lang->clearWordList(WordType::Property);
					}

					// Not a special symbol, add as constant
					else
						lang->addWord(WordType::Property, val);
				}
			}

			// Functions
			else if (S_CMPNOCASE(child->getName(), "functions"))
			{
				bool lang_has_void = lang->isWord(Keyword, "void") || lang->isWord(Type, "void");
				if (lang->id_ != "zscript")
				{
					// Go through children (functions)
					for (unsigned f = 0; f < child->nChildren(); f++)
					{
						auto   child_func = child->getChildPTN(f);
						string params;

						// Simple definition
						if (child_func->nChildren() == 0)
						{
							if (child_func->stringValue(0).empty())
							{
								if (lang_has_void)
									params = "void";
								else
									params = "";
							}
							else
							{
								params = child_func->stringValue(0);
							}

							// Add function
							lang->addFunction(
								child_func->getName(),
								params,
								"",
								"",
								!child_func->getName().Contains("."),
								child_func->type());

							// Add args
							for (unsigned v = 1; v < child_func->nValues(); v++)
								lang->addFunction(child_func->getName(), child_func->stringValue(v));
						}

						// Full definition
						else
						{
							string         name = child_func->getName();
							vector<string> args;
							string         desc       = "";
							string         deprecated = "";
							for (unsigned p = 0; p < child_func->nChildren(); p++)
							{
								auto child_prop = child_func->getChildPTN(p);
								if (child_prop->getName() == "args")
								{
									for (unsigned v = 0; v < child_prop->nValues(); v++)
										args.push_back(child_prop->stringValue(v));
								}
								else if (child_prop->getName() == "description")
									desc = child_prop->stringValue();
								else if (child_prop->getName() == "deprecated")
									deprecated = child_prop->stringValue();
							}

							if (args.empty() && lang_has_void)
								args.push_back("void");

							for (unsigned as = 0; as < args.size(); as++)
								lang->addFunction(name, args[as], desc, deprecated, as == 0, child_func->type());
						}
					}
				}
				// ZScript function info which cannot be parsed from (g)zdoom.pk3
				else
				{
					zfunc_ex_prop ex_prop;
					for (unsigned f = 0; f < child->nChildren(); f++)
					{
						auto child_func = child->getChildPTN(f);
						for (unsigned p = 0; p < child_func->nChildren(); ++p)
						{
							auto child_prop = child_func->getChildPTN(p);
							if (child_prop->getName() == "description")
								ex_prop.description = child_prop->stringValue();
							else if (child_prop->getName() == "deprecated_f")
								ex_prop.deprecated_f = child_prop->stringValue();
						}
						lang->zfuncs_ex_props_.emplace(child_func->getName(), ex_prop);
					}
				}
			}
		}
	}

	return true;
}
Ejemplo n.º 6
0
void Tree::assertBinary() const {
  for (TreeNodeIndex node = 0; node < nodes(); ++node)
    if (!isLeaf(node))
      Assert (nChildren(node) == 2, "Tree is not binary: node %d has %s\nSubtree rooted at %d: %s\n", node, plural(nChildren(node),"child","children").c_str(), node, toString(node).c_str());
}
Ejemplo n.º 7
0
TreeNodeIndex Tree::getSibling (TreeNodeIndex node) const {
  const TreeNodeIndex parent = parentNode(node);
  Assert (parent >= 0, "Attempt to find sibling of root node");
  Assert (nChildren(parent) == 2, "Attempt to find sibling in non-binary tree");
  return getChild(parent,0) == node ? getChild(parent,1) : getChild(parent,0);
}
Ejemplo n.º 8
0
bool Tree::isBinary() const {
  for (TreeNodeIndex node = 0; node < nodes(); ++node)
    if (!isLeaf(node) && nChildren(node) != 2)
      return false;
  return true;
}
Ejemplo n.º 9
0
// -----------------------------------------------------------------------------
// Automatically seek IWADs to populate the list
// -----------------------------------------------------------------------------
void BaseResourceArchivesPanel::autodetect()
{
	// List of known IWADs and common aliases
	ArchiveEntry* iwadlist = App::archiveManager().programResourceArchive()->entryAtPath("config/iwads.cfg");
	if (!iwadlist)
		return;
	Parser p;
	p.parseText(iwadlist->getMCData(), "slade.pk3:config/iwads.cfg");


	// Find IWADs from DOOMWADDIR and DOOMWADPATH
	// See http://doomwiki.org/wiki/Environment_variables
	string doomwaddir, doomwadpath, envvar;
	envvar = "DOOMWADDIR";
	wxGetEnv(envvar, &doomwaddir);
	envvar = "DOOMWADPATH";
	wxGetEnv(envvar, &doomwadpath);

	if (doomwaddir.length() || doomwadpath.length())
	{
#ifdef WIN32
		char separator = ';';
		doomwadpath.Replace("\\", "/", true);
		doomwaddir.Replace("\\", "/", true);
#else
		char separator = ':';
#endif

		wxArrayString paths = wxSplit(doomwadpath, separator);
		paths.Add(doomwaddir);
		wxArrayString iwadnames;
		auto          list = p.parseTreeRoot()->getChildPTN("iwads");
		for (size_t i = 0; i < list->nChildren(); ++i)
			iwadnames.Add(list->getChild(i)->getName());

		// Look for every known IWAD in every known IWAD directory
		for (size_t i = 0; i < paths.size(); ++i)
		{
			string folder = paths[i];
			if (folder.Last() != '/')
				folder += '/';
			for (size_t j = 0; j < iwadnames.size(); ++j)
			{
				string iwad = folder + iwadnames[j];
#ifndef WIN32
				// Try a couple variants before throwing the towel about a name
				if (!wxFileExists(iwad))
					iwad = folder + iwadnames[j].Capitalize();
				if (!wxFileExists(iwad))
					iwad = folder + iwadnames[j].Upper();
#endif
				// If a valid combo is found, add it to the list unless already present
				if (wxFileExists(iwad))
				{
					// Verify existence before adding it to the list
					if (list_base_archive_paths_->FindString(iwad) == wxNOT_FOUND)
					{
						App::archiveManager().addBaseResourcePath(iwad);
						list_base_archive_paths_->Append(iwad);
					}
				}
			}
		}
	}

	// Let's take a look at the registry
	wxArrayString paths;
	string        path;
	string        gamepath;

	// Now query GOG.com paths -- Windows only for now
#ifdef __WXMSW__
#ifdef _WIN64
	string gogregistrypath = "Software\\Wow6432Node\\GOG.com";
#else
	// If a 32-bit ZDoom runs on a 64-bit Windows, this will be transparently and
	// automatically redirected to the Wow6432Node address instead, so this address
	// should be safe to use in all cases.
	string gogregistrypath = "Software\\GOG.com";
#endif
	if (QueryPathKey(wxRegKey::HKLM, gogregistrypath, "DefaultPackPath", path))
	{
		auto list = p.parseTreeRoot()->getChildPTN("gog");
		for (size_t i = 0; i < list->nChildren(); ++i)
		{
			auto child = list->getChildPTN(i);
			gamepath   = gogregistrypath + (child->getChildPTN("id"))->stringValue();
			if (QueryPathKey(wxRegKey::HKLM, gamepath, "Path", path))
				paths.Add(path + (child->getChildPTN("path"))->stringValue());
		}
	}
#endif


	// Now query Steam paths -- Windows only for now as well
#ifdef __WXMSW__
	if (QueryPathKey(wxRegKey::HKCU, "Software\\Valve\\Steam", "SteamPath", gamepath)
		|| QueryPathKey(wxRegKey::HKLM, "Software\\Valve\\Steam", "InstallPath", gamepath))
	{
		gamepath += "/SteamApps/common/";
		auto list = p.parseTreeRoot()->getChildPTN("steam");
		for (size_t i = 0; i < list->nChildren(); ++i)
			paths.Add(gamepath + (list->getChildPTN(i))->stringValue());
	}
#else
	// TODO: Querying Steam registry on Linux and OSX. This involves parsing Steam's config.vdf file, which is found in
	// FSFindFolder(kUserDomain, kApplicationSupportFolderType, kCreateFolder, &folder) + "/Steam/config/config.vdf" on
	// OSX and in ~home/.local/share/Steam/config/config.vdf on Linux/BSD systems. There's also default install dirs in
	// appSupportPath + "/Steam/SteamApps/common" for OSX, ~home/.local/share/Steam/SteamApps/common for Linux/BSD.
#endif


	// Add GOG & Steam paths
	for (size_t i = 0; i < paths.size(); ++i)
	{
		string iwad = paths[i];
		iwad.Replace("\\", "/", true);
		if (wxFileExists(iwad))
		{
			// Verify existence before adding it to the list
			if (list_base_archive_paths_->FindString(iwad) == wxNOT_FOUND)
			{
				App::archiveManager().addBaseResourcePath(iwad);
				list_base_archive_paths_->Append(iwad);
			}
		}
	}
}
Ejemplo n.º 10
0
// -----------------------------------------------------------------------------
// Reads archive formats configuration file from [mc]
// -----------------------------------------------------------------------------
bool Archive::loadFormats(MemChunk& mc)
{
	Parser parser;
	if (!parser.parseText(mc))
		return false;

	auto root         = parser.parseTreeRoot();
	auto formats_node = root->child("archive_formats");
	for (unsigned a = 0; a < formats_node->nChildren(); a++)
	{
		auto          fmt_desc = (ParseTreeNode*)formats_node->child(a);
		ArchiveFormat fmt{ fmt_desc->name() };

		for (unsigned p = 0; p < fmt_desc->nChildren(); p++)
		{
			auto prop = (ParseTreeNode*)fmt_desc->child(p);

			// Format name
			if (StrUtil::equalCI(prop->name(), "name"))
				fmt.name = prop->stringValue();

			// Supports dirs
			else if (StrUtil::equalCI(prop->name(), "supports_dirs"))
				fmt.supports_dirs = prop->boolValue();

			// Entry names have extensions
			else if (StrUtil::equalCI(prop->name(), "names_extensions"))
				fmt.names_extensions = prop->boolValue();

			// Max entry name length
			else if (StrUtil::equalCI(prop->name(), "max_name_length"))
				fmt.max_name_length = prop->intValue();

			// Entry format (id)
			else if (StrUtil::equalCI(prop->name(), "entry_format"))
				fmt.entry_format = prop->stringValue();

			// Extensions
			else if (StrUtil::equalCI(prop->name(), "extensions"))
			{
				for (unsigned e = 0; e < prop->nChildren(); e++)
				{
					auto ext = (ParseTreeNode*)prop->child(e);
					fmt.extensions.emplace_back(ext->name(), ext->stringValue());
				}
			}

			// Prefer uppercase entry names
			else if (StrUtil::equalCI(prop->name(), "prefer_uppercase"))
				fmt.prefer_uppercase = prop->boolValue();
		}

		Log::info(3, wxString::Format("Read archive format %s: \"%s\"", fmt.id, fmt.name));
		if (fmt.supports_dirs)
			Log::info(3, "  Supports folders");
		if (fmt.names_extensions)
			Log::info(3, "  Entry names have extensions");
		if (fmt.max_name_length >= 0)
			Log::info(3, wxString::Format("  Max entry name length: %d", fmt.max_name_length));
		for (auto ext : fmt.extensions)
			Log::info(3, wxString::Format("  Extension \"%s\" = \"%s\"", ext.first, ext.second));

		formats.push_back(fmt);
	}

	// Add builtin 'folder' format
	ArchiveFormat fmt_folder("folder");
	fmt_folder.name             = "Folder";
	fmt_folder.names_extensions = true;
	fmt_folder.supports_dirs    = true;
	formats.push_back(fmt_folder);

	return true;
}
Ejemplo n.º 11
0
// -----------------------------------------------------------------------------
// Returns a list of entries matching the search criteria in [options]
// -----------------------------------------------------------------------------
vector<ArchiveEntry*> Archive::findAll(SearchOptions& options)
{
	// Init search variables
	auto dir = options.dir;
	if (!dir)
		dir = &dir_root_;
	vector<ArchiveEntry*> ret;
	StrUtil::upperIP(options.match_name); // Force case-insensitive

	// Begin search

	// Search entries
	for (unsigned a = 0; a < dir->numEntries(); a++)
	{
		auto entry = dir->entryAt(a);

		// Check type
		if (options.match_type)
		{
			if (entry->type() == EntryType::unknownType())
			{
				if (!options.match_type->isThisType(entry))
					continue;
			}
			else if (options.match_type != entry->type())
				continue;
		}

		// Check name
		if (!options.match_name.empty())
		{
			// Cut extension if ignoring
			auto check_name = options.ignore_ext ? entry->upperNameNoExt() : entry->upperName();
			if (!StrUtil::matches(check_name, options.match_name))
				continue;
		}

		// Check namespace
		if (!options.match_namespace.empty())
		{
			if (!StrUtil::equalCI(detectNamespace(entry), options.match_namespace))
				continue;
		}

		// Entry passed all checks so far, so we found a match
		ret.push_back(entry);
	}

	// Search subdirectories (if needed)
	if (options.search_subdirs)
	{
		for (unsigned a = 0; a < dir->nChildren(); a++)
		{
			auto opt = options;
			opt.dir  = (ArchiveTreeNode*)dir->child(a);

			// Add any matches to the list
			auto vec = findAll(opt);
			ret.insert(ret.end(), vec.begin(), vec.end());
		}
	}

	// Return matches
	return ret;
}
Ejemplo n.º 12
0
// -----------------------------------------------------------------------------
// Returns the last entry matching the search criteria in [options], or null if
// no matching entry was found
// -----------------------------------------------------------------------------
ArchiveEntry* Archive::findLast(SearchOptions& options)
{
	// Init search variables
	auto dir = options.dir;
	if (!dir)
		dir = &dir_root_;
	StrUtil::upperIP(options.match_name); // Force case-insensitive

	// Begin search

	// Search entries (bottom-up)
	for (int a = dir->numEntries() - 1; a >= 0; a--)
	{
		auto entry = dir->entryAt(a);

		// Check type
		if (options.match_type)
		{
			if (entry->type() == EntryType::unknownType())
			{
				if (!options.match_type->isThisType(entry))
					continue;
			}
			else if (options.match_type != entry->type())
				continue;
		}

		// Check name
		if (!options.match_name.empty())
		{
			// Cut extension if ignoring
			auto check_name = options.ignore_ext ? entry->upperNameNoExt() : entry->upperName();
			if (!StrUtil::matches(check_name, options.match_name))
				continue;
		}

		// Check namespace
		if (!options.match_namespace.empty())
		{
			if (!StrUtil::equalCI(detectNamespace(entry), options.match_namespace))
				continue;
		}

		// Entry passed all checks so far, so we found a match
		return entry;
	}

	// Search subdirectories (if needed) (bottom-up)
	if (options.search_subdirs)
	{
		for (int a = dir->nChildren() - 1; a >= 0; a--)
		{
			auto opt   = options;
			opt.dir    = (ArchiveTreeNode*)dir->child(a);
			auto match = findLast(opt);

			// If a match was found in this subdir, return it
			if (match)
				return match;
		}
	}

	// No matches found
	return nullptr;
}
Ejemplo n.º 13
0
// -----------------------------------------------------------------------------
// Reads a colour configuration from text data [mc]
// -----------------------------------------------------------------------------
bool ColourConfiguration::readConfiguration(MemChunk& mc)
{
	// Parse text
	Parser parser;
	parser.parseText(mc);

	// Get 'colours' block
	auto colours = parser.parseTreeRoot()->childPTN("colours");
	if (colours)
	{
		// Read all colour definitions
		for (unsigned a = 0; a < colours->nChildren(); a++)
		{
			auto def = colours->childPTN(a);

			// Read properties
			for (unsigned b = 0; b < def->nChildren(); b++)
			{
				auto  prop = def->childPTN(b);
				auto& col  = cc_colours[def->name()];
				col.exists = true;

				// Colour name
				if (prop->name() == "name")
					col.name = prop->stringValue();

				// Colour group (for config ui)
				else if (prop->name() == "group")
					col.group = prop->stringValue();

				// Colour
				else if (prop->name() == "rgb")
					col.colour.set(prop->intValue(0), prop->intValue(1), prop->intValue(2));

				// Alpha
				else if (prop->name() == "alpha")
					col.colour.a = prop->intValue();

				// Additive
				else if (prop->name() == "additive")
					col.blend_additive = prop->boolValue();

				else
					Log::warning(fmt::format("Unknown colour definition property \"{}\"", prop->name()));
			}
		}
	}

	// Get 'theme' block
	auto theme = parser.parseTreeRoot()->childPTN("theme");
	if (theme)
	{
		// Read all theme definitions
		for (unsigned a = 0; a < theme->nChildren(); a++)
		{
			auto prop = theme->childPTN(a);

			if (prop->name() == "line_hilight_width")
				line_hilight_width = prop->floatValue();

			else if (prop->name() == "line_selection_width")
				line_selection_width = prop->floatValue();

			else if (prop->name() == "flat_alpha")
				flat_alpha = prop->floatValue();

			else
				Log::warning(fmt::format("Unknown theme property \"{}\"", prop->name()));
		}
	}

	return true;
}