BOOL C4ComponentHost::LoadEx(const char *szName, C4Group &hGroup, const char *szFilename, const char *szLanguage) { // Load from a group set containing the provided group and // alternative groups for cross-loading from a language pack C4GroupSet hGroups; hGroups.RegisterGroup( hGroup, false, 1000, C4GSCnt_Component); // Provided group gets highest priority hGroups.RegisterGroups(Languages.GetPackGroups(pConfig->AtExeRelativePath( hGroup.GetFullName().getData())), C4GSCnt_Language); // Load from group set return Load(szName, hGroups, szFilename, szLanguage); }
C4GroupSet C4Language::GetPackGroups(C4Group & hGroup) { // Build a group set containing the provided group and // alternative groups for cross-loading from a language pack char strRelativePath[_MAX_PATH + 1]; char strTargetLocation[_MAX_PATH + 1]; char strPackPath[_MAX_PATH + 1]; char strPackGroupLocation[_MAX_PATH + 1]; char strAdvance[_MAX_PATH + 1]; // Store wanted target location SCopy(Config.AtRelativePath(hGroup.GetFullName().getData()), strRelativePath, _MAX_PATH); SCopy(strRelativePath, strTargetLocation, _MAX_PATH); // Adjust location by scenario origin if (Game.C4S.Head.Origin.getLength() && SEqualNoCase(GetExtension(Game.C4S.Head.Origin.getData()), "ocs")) { const char *szScenarioRelativePath = GetRelativePathS(strRelativePath, Config.AtRelativePath(Game.ScenarioFilename)); if (szScenarioRelativePath != strRelativePath) { // this is a path within the scenario! Change to origin. size_t iRestPathLen = SLen(szScenarioRelativePath); if (Game.C4S.Head.Origin.getLength() + 1 + iRestPathLen <= _MAX_PATH) { SCopy(Game.C4S.Head.Origin.getData(), strTargetLocation); if (iRestPathLen) { SAppendChar(DirectorySeparator, strTargetLocation); SAppend(szScenarioRelativePath, strTargetLocation); } } } } // Process all language packs (and their respective pack groups) C4Group *pPack, *pPackGroup; for (int iPack = 0; (pPack = Packs.GetGroup(iPack)) && (pPackGroup = PackGroups.GetGroup(iPack)); iPack++) { // Get current pack group position within pack SCopy(pPack->GetFullName().getData(), strPackPath, _MAX_PATH); GetRelativePath(pPackGroup->GetFullName().getData(), strPackPath, strPackGroupLocation); // Pack group is at correct position within pack: continue with next pack if (SEqualNoCase(strPackGroupLocation, strTargetLocation)) continue; // Try to backtrack until we can reach the target location as a relative child while ( strPackGroupLocation[0] && !GetRelativePath(strTargetLocation, strPackGroupLocation, strAdvance) && pPackGroup->OpenMother() ) { // Update pack group location GetRelativePath(pPackGroup->GetFullName().getData(), strPackPath, strPackGroupLocation); } // We can reach the target location as a relative child if (strPackGroupLocation[0] && GetRelativePath(strTargetLocation, strPackGroupLocation, strAdvance)) { // Advance pack group to relative child pPackGroup->OpenChild(strAdvance); } // Cannot reach by advancing: need to close and reopen (rewinding group file) else { // Close pack group (if it is open at all) pPackGroup->Close(); // Reopen pack group to relative position in language pack if possible pPackGroup->OpenAsChild(pPack, strTargetLocation); } } // Store new target location SCopy(strTargetLocation, PackGroupLocation, _MAX_FNAME); C4GroupSet r; // Provided group gets highest priority r.RegisterGroup(hGroup, false, 1000, C4GSCnt_Component); // register currently open pack groups r.RegisterGroups(PackGroups, C4GSCnt_Language); return r; }