Example #1
0
void ThemeEngine::listUsableThemes(const Common::FSNode &node, Common::List<ThemeDescriptor> &list, int depth) {
	if (!node.exists() || !node.isReadable() || !node.isDirectory())
		return;

	ThemeDescriptor td;

	// Check whether we point to a valid theme directory.
	if (themeConfigUsable(node, td.name)) {
		td.filename = node.getPath();
		td.id = node.getName();

		list.push_back(td);

		// A theme directory should never contain any other themes
		// thus we just return to the caller here.
		return;
	}

	Common::FSList fileList;
	// Check all files. We need this to find all themes inside ZIP archives.
	if (!node.getChildren(fileList, Common::FSNode::kListFilesOnly))
		return;

	for (Common::FSList::iterator i = fileList.begin(); i != fileList.end(); ++i) {
		// We will only process zip files for now
		if (!i->getPath().matchString("*.zip", true))
			continue;

		td.name.clear();
		if (themeConfigUsable(*i, td.name)) {
			td.filename = i->getPath();
			td.id = i->getName();

			// If the name of the node object also contains
			// the ".zip" suffix, we will strip it.
			if (td.id.matchString("*.zip", true)) {
				for (int j = 0; j < 4; ++j)
					td.id.deleteLastChar();
			}

			list.push_back(td);
		}
	}

	fileList.clear();

	// Check if we exceeded the given recursion depth
	if (depth - 1 == -1)
		return;

	// As next step we will search all subdirectories
	if (!node.getChildren(fileList, Common::FSNode::kListDirectoriesOnly))
		return;

	for (Common::FSList::iterator i = fileList.begin(); i != fileList.end(); ++i)
		listUsableThemes(*i, list, depth == -1 ? - 1 : depth - 1);
}
Example #2
0
bool FilesPageHandler::listDirectory(Common::String path, Common::String &content, const Common::String &itemTemplate) {
	if (path == "" || path == "/") {
		if (ConfMan.hasKey("rootpath", "cloud"))
			addItem(content, itemTemplate, IT_DIRECTORY, "/root/", _("File system root"));
		addItem(content, itemTemplate, IT_DIRECTORY, "/saves/", _("Saved games"));
		return true;
	}

	if (HandlerUtils::hasForbiddenCombinations(path))
		return false;

	Common::String prefixToRemove = "", prefixToAdd = "";
	if (!transformPath(path, prefixToRemove, prefixToAdd))
		return false;

	Common::FSNode node = Common::FSNode(path);
	if (path == "/")
		node = node.getParent(); // absolute root

	if (!HandlerUtils::permittedPath(node.getPath()))
		return false;

	if (!node.isDirectory())
		return false;

	// list directory
	Common::FSList _nodeContent;
	if (!node.getChildren(_nodeContent, Common::FSNode::kListAll, false)) // do not show hidden files
		_nodeContent.clear();
	else
		Common::sort(_nodeContent.begin(), _nodeContent.end());

	// add parent directory link
	{
		Common::String filePath = path;
		if (filePath.hasPrefix(prefixToRemove))
			filePath.erase(0, prefixToRemove.size());
		if (filePath == "" || filePath == "/" || filePath == "\\")
			filePath = "/";
		else
			filePath = parentPath(prefixToAdd + filePath);
		addItem(content, itemTemplate, IT_PARENT_DIRECTORY, filePath, _("Parent directory"));
	}

	// fill the content
	for (Common::FSList::iterator i = _nodeContent.begin(); i != _nodeContent.end(); ++i) {
		Common::String name = i->getDisplayName();
		if (i->isDirectory())
			name += "/";

		Common::String filePath = i->getPath();
		if (filePath.hasPrefix(prefixToRemove))
			filePath.erase(0, prefixToRemove.size());
		filePath = prefixToAdd + filePath;

		addItem(content, itemTemplate, detectType(i->isDirectory(), name), filePath, name);
	}

	return true;
}
Example #3
0
void CELauncherDialog::automaticScanDirectory(const Common::FSNode &node) {
	// First check if we have a recognized game in the current directory
	Common::FSList files;
	node.getChildren(files, Common::FSNode::kListFilesOnly);
	// detect
	GameList candidates(EngineMan.detectGames(files));
	// insert
	if (candidates.size() >= 1) {
		GameDescriptor result = candidates[0];
		result["path"] = node.getPath();
		addGameToConf(result);
	}
	// Then recurse on the subdirectories
	Common::FSList dirs;
	node.getChildren(dirs, Common::FSNode::kListDirectoriesOnly);
	for (Common::FSList::const_iterator currentDir = dirs.begin(); currentDir != dirs.end(); ++currentDir)
		automaticScanDirectory(*currentDir);

}
Example #4
0
void MassAddDialog::handleTickle() {
	if (_scanStack.empty())
		return;	// We have finished scanning

	uint32 t = g_system->getMillis();

	// Perform a breadth-first scan of the filesystem.
	while (!_scanStack.empty() && (g_system->getMillis() - t) < kMaxScanTime) {
		Common::FSNode dir = _scanStack.pop();

		Common::FSList files;
		if (!dir.getChildren(files, Common::FSNode::kListAll)) {
			continue;
		}

		// Run the detector on the dir
		GameList candidates(EngineMan.detectGames(files));

		// Just add all detected games / game variants. If we get more than one,
		// that either means the directory contains multiple games, or the detector
		// could not fully determine which game variant it was seeing. In either
		// case, let the user choose which entries he wants to keep.
		//
		// However, we only add games which are not already in the config file.
		for (GameList::const_iterator cand = candidates.begin(); cand != candidates.end(); ++cand) {
			GameDescriptor result = *cand;
			Common::String path = dir.getPath();

			// Remove trailing slashes
			while (path != "/" && path.lastChar() == '/')
				path.deleteLastChar();

			// Check for existing config entries for this path/gameid/lang/platform combination
			if (_pathToTargets.contains(path)) {
				bool duplicate = false;
				const StringArray &targets = _pathToTargets[path];
				for (StringArray::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) {
					// If the gameid, platform and language match -> skip it
					Common::ConfigManager::Domain *dom = ConfMan.getDomain(*iter);
					assert(dom);

					if ((*dom)["gameid"] == result["gameid"] &&
					    (*dom)["platform"] == result["platform"] &&
					    (*dom)["language"] == result["language"]) {
						duplicate = true;
						break;
					}
				}
				if (duplicate) {
					_oldGamesCount++;
					break;	// Skip duplicates
				}
			}
			result["path"] = path;
			_games.push_back(result);

			_list->append(result.description());
		}


		// Recurse into all subdirs
		for (Common::FSList::const_iterator file = files.begin(); file != files.end(); ++file) {
			if (file->isDirectory()) {
				_scanStack.push(*file);
			}
		}

		_dirsScanned++;
	}


	// Update the dialog
	Common::String buf;

	if (_scanStack.empty()) {
		// Enable the OK button
		_okButton->setEnabled(true);

		buf = _("Scan complete!");
		_dirProgressText->setLabel(buf);

		buf = Common::String::format(_("Discovered %d new games, ignored %d previously added games."), _games.size(), _oldGamesCount);
		_gameProgressText->setLabel(buf);

	} else {
		buf = Common::String::format(_("Scanned %d directories ..."), _dirsScanned);
		_dirProgressText->setLabel(buf);

		buf = Common::String::format(_("Discovered %d new games, ignored %d previously added games ..."), _games.size(), _oldGamesCount);
		_gameProgressText->setLabel(buf);
	}

	if (_games.size() > 0) {
		_list->scrollToEnd();
	}

	drawDialog();
}
Example #5
0
// The following function tries to detect the language for COMI and DIG
static Common::Language detectLanguage(const Common::FSList &fslist, byte id) {
	// First try to detect Chinese translation
	Common::FSNode fontFile;

	if (searchFSNode(fslist, "chinese_gb16x12.fnt", fontFile)) {
		debug(0, "Chinese detected");
		return Common::ZH_CNA;
	}

	// Now try to detect COMI and Dig by language files
	if (id != GID_CMI && id != GID_DIG)
		return Common::UNK_LANG;

	// Check for LANGUAGE.BND (Dig) resp. LANGUAGE.TAB (CMI).
	// These are usually inside the "RESOURCE" subdirectory.
	// If found, we match based on the file size (should we
	// ever determine that this is insufficient, we can still
	// switch to MD5 based detection).
	const char *filename = (id == GID_CMI) ? "LANGUAGE.TAB" : "LANGUAGE.BND";
	Common::File tmp;
	Common::FSNode langFile;
	if (searchFSNode(fslist, filename, langFile))
		tmp.open(langFile);
	if (!tmp.isOpen()) {
		// try loading in RESOURCE sub dir...
		Common::FSNode resDir;
		Common::FSList tmpList;
		if (searchFSNode(fslist, "RESOURCE", resDir)
			&& resDir.isDirectory()
			&& resDir.getChildren(tmpList, Common::FSNode::kListFilesOnly)
			&& searchFSNode(tmpList, filename, langFile)) {
			tmp.open(langFile);
		}
	}
	if (tmp.isOpen()) {
		uint size = tmp.size();
		if (id == GID_CMI) {
			switch (size) {
			case 439080:	// 2daf3db71d23d99d19fc9a544fcf6431
				return Common::EN_ANY;
			case 322602:	// caba99f4f5a0b69963e5a4d69e6f90af
				return Common::ZH_TWN;
			case 493252:	// 5d59594b24f3f1332e7d7e17455ed533
				return Common::DE_DEU;
			case 461746:	// 35bbe0e4d573b318b7b2092c331fd1fa
				return Common::FR_FRA;
			case 443439:	// 4689d013f67aabd7c35f4fd7c4b4ad69
				return Common::IT_ITA;
			case 398613:	// d1f5750d142d34c4c8f1f330a1278709
				return Common::KO_KOR;
			case 440586:	// 5a1d0f4fa00917bdbfe035a72a6bba9d
				return Common::PT_BRA;
			case 454457:	// 0e5f450ec474a30254c0e36291fb4ebd
			case 394083:	// ad684ca14c2b4bf4c21a81c1dbed49bc
				return Common::RU_RUS;
			case 449787:	// 64f3fe479d45b52902cf88145c41d172
				return Common::ES_ESP;
			}
		} else { // The DIG
			switch (size) {
			case 248627:	// 1fd585ac849d57305878c77b2f6c74ff
				return Common::DE_DEU;
			case 257460:	// 04cf6a6ba6f57e517bc40eb81862cfb0
				return Common::FR_FRA;
			case 231402:	// 93d13fcede954c78e65435592182a4db
				return Common::IT_ITA;
			case 228772:	// 5d9ad90d3a88ea012d25d61791895ebe
				return Common::PT_BRA;
			case 229884:	// d890074bc15c6135868403e73c5f4f36
				return Common::ES_ESP;
			case 223107:	// 64f3fe479d45b52902cf88145c41d172
				return Common::JA_JPN;
			case 180730:	// 424fdd60822722cdc75356d921dad9bf
				return Common::ZH_TWN;
			}
		}
	}

	return Common::UNK_LANG;
}