bool TranslationManager::openTranslationsFile(const FSNode &node, File &inFile, int depth) { if (!node.exists() || !node.isReadable() || !node.isDirectory()) return false; // Check if we can find the file in this directory // Since File::open(FSNode) makes all the needed tests, it is not really // necessary to make them here. But it avoid printing warnings. FSNode fileNode = node.getChild("translations.dat"); if (fileNode.exists() && fileNode.isReadable() && !fileNode.isDirectory()) { if (inFile.open(fileNode)) { if (checkHeader(inFile)) return true; inFile.close(); } } // Check if we exceeded the given recursion depth if (depth - 1 == -1) return false; // Otherwise look for it in sub-directories FSList fileList; if (!node.getChildren(fileList, FSNode::kListDirectoriesOnly)) return false; for (FSList::iterator i = fileList.begin(); i != fileList.end(); ++i) { if (openTranslationsFile(*i, inFile, depth == -1 ? - 1 : depth - 1)) return true; } // Not found in this directory or its sub-directories return false; }
void TranslationManager::loadLanguageDat(int index) { _currentTranslationMessages.clear(); _currentCharset.clear(); // Sanity check if (index < 0 || index >= (int)_langs.size()) { if (index != -1) warning("Invalid language index %d passed to TranslationManager::loadLanguageDat", index); return; } File in; if (!openTranslationsFile(in)) return; if (!checkHeader(in)) return; char buf[1024]; int len; // Get number of translations int nbTranslations = in.readUint16BE(); if (nbTranslations != (int)_langs.size()) { warning("The 'translations.dat' file has changed since starting ScummVM. GUI translation will not be available"); return; } // Get size of blocks to skip. int skipSize = 0; for (int i = 0; i < index + 2; ++i) skipSize += in.readUint16BE(); // We also need to skip the remaining block sizes skipSize += 2 * (nbTranslations - index); // Seek to start of block we want to read in.seek(skipSize, SEEK_CUR); // Read number of translated messages int nbMessages = in.readUint16BE(); _currentTranslationMessages.resize(nbMessages); // Read charset len = in.readUint16BE(); in.read(buf, len); _currentCharset = String(buf, len - 1); // Read messages for (int i = 0; i < nbMessages; ++i) { _currentTranslationMessages[i].msgid = in.readUint16BE(); len = in.readUint16BE(); in.read(buf, len); _currentTranslationMessages[i].msgstr = String(buf, len - 1); len = in.readUint16BE(); if (len > 0) { in.read(buf, len); _currentTranslationMessages[i].msgctxt = String(buf, len - 1); } } }
void TranslationManager::loadTranslationsInfoDat() { File in; if (!openTranslationsFile(in)) { warning("You are missing a valid 'translations.dat' file. GUI translation will not be available"); return; } char buf[256]; int len; // Get number of translations int nbTranslations = in.readUint16BE(); // Get number of codepages int nbCodepages = in.readUint16BE(); // Determine where the codepages start _charmapStart = 0; for (int i = 0; i < nbTranslations + 3; ++i) _charmapStart += in.readUint16BE(); _charmapStart += in.pos(); // Read list of languages _langs.resize(nbTranslations); _langNames.resize(nbTranslations); for (int i = 0; i < nbTranslations; ++i) { len = in.readUint16BE(); in.read(buf, len); _langs[i] = String(buf, len - 1); len = in.readUint16BE(); in.read(buf, len); _langNames[i] = String(buf, len - 1); } // Read list of codepages _charmaps.resize(nbCodepages); for (int i = 0; i < nbCodepages; ++i) { len = in.readUint16BE(); in.read(buf, len); _charmaps[i] = String(buf, len - 1); } // Read messages int numMessages = in.readUint16BE(); _messageIds.resize(numMessages); for (int i = 0; i < numMessages; ++i) { len = in.readUint16BE(); String msg; while (len > 0) { in.read(buf, len > 256 ? 256 : len); msg += String(buf, len > 256 ? 256 : len - 1); len -= 256; } _messageIds[i] = msg; } }
bool TranslationManager::openTranslationsFile(File& inFile) { // First try to open it directly (i.e. using the SearchMan). if (inFile.open("translations.dat")) return true; // Then look in the Themepath if we can find the file. if (ConfMan.hasKey("themepath")) return openTranslationsFile(FSNode(ConfMan.get("themepath")), inFile); return false; }
bool TranslationManager::openTranslationsFile(File &inFile) { // First look in the Themepath if we can find the file. if (ConfMan.hasKey("themepath") && openTranslationsFile(FSNode(ConfMan.get("themepath")), inFile)) return true; // Then try to open it using the SearchMan. ArchiveMemberList fileList; SearchMan.listMatchingMembers(fileList, "translations.dat"); for (ArchiveMemberList::iterator it = fileList.begin(); it != fileList.end(); ++it) { SeekableReadStream *stream = it->get()->createReadStream(); if (stream && inFile.open(stream, it->get()->getName())) { if (checkHeader(inFile)) return true; inFile.close(); } } return false; }
void TranslationManager::loadTranslationsInfoDat() { File in; if (!openTranslationsFile(in)) { warning("You are missing the 'translations.dat' file. GUI translation will not be available"); return; } if (!checkHeader(in)) return; char buf[256]; int len; // Get number of translations int nbTranslations = in.readUint16BE(); // Skip all the block sizes for (int i = 0; i < nbTranslations + 2; ++i) in.readUint16BE(); // Read list of languages _langs.resize(nbTranslations); _langNames.resize(nbTranslations); for (int i = 0; i < nbTranslations; ++i) { len = in.readUint16BE(); in.read(buf, len); _langs[i] = String(buf, len - 1); len = in.readUint16BE(); in.read(buf, len); _langNames[i] = String(buf, len - 1); } // Read messages int numMessages = in.readUint16BE(); _messageIds.resize(numMessages); for (int i = 0; i < numMessages; ++i) { len = in.readUint16BE(); in.read(buf, len); _messageIds[i] = String(buf, len - 1); } }
void TranslationManager::loadLanguageDat(int index) { _currentTranslationMessages.clear(); _currentCharset.clear(); // Sanity check if (index < 0 || index >= (int)_langs.size()) { if (index != -1) warning("Invalid language index %d passed to TranslationManager::loadLanguageDat", index); return; } File in; if (!openTranslationsFile(in)) return; char buf[1024]; int len; // Get number of translations int nbTranslations = in.readUint16BE(); if (nbTranslations != (int)_langs.size()) { warning("The 'translations.dat' file has changed since starting ResidualVM. GUI translation will not be available"); return; } // Get the number of codepages int nbCodepages = in.readUint16BE(); if (nbCodepages != (int)_charmaps.size()) { warning("The 'translations.dat' file has changed since starting ResidualVM. GUI translation will not be available"); return; } // Get size of blocks to skip. int skipSize = 0; for (int i = 0; i < index + 3; ++i) skipSize += in.readUint16BE(); // We also need to skip the remaining block sizes skipSize += 2 * (nbTranslations - index); // Seek to start of block we want to read in.seek(skipSize, SEEK_CUR); // Read number of translated messages int nbMessages = in.readUint16BE(); _currentTranslationMessages.resize(nbMessages); // Read charset len = in.readUint16BE(); in.read(buf, len); _currentCharset = String(buf, len - 1); // Read messages for (int i = 0; i < nbMessages; ++i) { _currentTranslationMessages[i].msgid = in.readUint16BE(); len = in.readUint16BE(); String msg; while (len > 0) { in.read(buf, len > 256 ? 256 : len); msg += String(buf, len > 256 ? 256 : len - 1); len -= 256; } _currentTranslationMessages[i].msgstr = msg; len = in.readUint16BE(); if (len > 0) { in.read(buf, len); _currentTranslationMessages[i].msgctxt = String(buf, len - 1); } } // Find the charset int charmapNum = -1; for (uint i = 0; i < _charmaps.size(); ++i) { if (_charmaps[i].equalsIgnoreCase(_currentCharset)) { charmapNum = i; break; } } // Setup the new charset mapping if (charmapNum == -1) { delete[] _charmap; _charmap = nullptr; } else { if (!_charmap) _charmap = new uint32[256]; in.seek(_charmapStart + charmapNum * 256 * 4, SEEK_SET); for (int i = 0; i < 256; ++i) _charmap[i] = in.readUint32BE(); } }