char *GetResStr(const char *id, const char *strTable) { const char *pos; // Default sprintf(strResult, "[Undefined:%s]", id); // Compose identifier with operator char idExt[256 + 1 + 1]; SCopy(id, idExt, 256); SAppendChar('=', idExt); // String table present and id not empty if (strTable && id && id[0]) // Search for identifier with operator if ((pos = SSearch(strTable, idExt))) // Get string until end of line SCopyUntil(pos, strResult, "\r\n", ResStrMaxLen); // Compile line feeds ("\n" -> 0D0A) pos = strResult; while ((pos = SSearch(pos, "\\n"))) { ((char*)pos)[-2] = 0x0D; ((char*)pos)[-1] = 0x0A; } #ifdef _DEBUG #ifdef _MSC_VER if (SEqual2(strResult, "[Undefined:")) if (!SEqual(id, "IDS_LANG_CHARSET")) { /* __asm int 3 */ } #endif #endif // Return string return strResult; }
void C4MusicSystem::LoadMoreMusic() { StdStrBuf MoreMusicFile; // load MoreMusic.txt if (!MoreMusicFile.LoadFromFile(Config.AtUserDataPath(C4CFN_MoreMusic))) return; // read contents char *pPos = MoreMusicFile.getMData(); while (pPos && *pPos) { // get line char szLine[1024 + 1]; SCopyUntil(pPos, szLine, '\n', 1024); pPos = strchr(pPos, '\n'); if (pPos) pPos++; // remove leading whitespace char *pLine = szLine; while (*pLine == ' ' || *pLine == '\t' || *pLine == '\r') pLine++; // and whitespace at end char *p = pLine + strlen(pLine) - 1; while (*p == ' ' || *p == '\t' || *p == '\r') { *p = 0; --p; } // comment? if (*pLine == '#') { // might be a "directive" if (SEqual(pLine, "#clear")) ClearSongs(); continue; } // try to load file(s) LoadDir(pLine); } }
bool C4GameSave::SaveDesc(C4Group &hToGroup) { // Unfortunately, there's no way to prealloc the buffer in an appropriate size StdStrBuf sBuffer; // Header sBuffer.AppendFormat("{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1031{\\fonttbl {\\f0\\fnil\\fcharset%d Times New Roman;}}", 0 /*FIXME: a number for UTF-8 here*/); sBuffer.Append(LineFeed); // Scenario title sBuffer.AppendFormat("\\uc1\\pard\\ulnone\\b\\f0\\fs20 %s\\par",Game.ScenarioTitle.getData()); sBuffer.Append(LineFeed "\\b0\\fs16\\par" LineFeed); // OK; each specializations has its own desc format WriteDesc(sBuffer); // End of file sBuffer.Append(LineFeed "}" LineFeed); // Generate Filename StdStrBuf sFilename; char szLang[3]; SCopyUntil(Config.General.Language, szLang, ',', 2); sFilename.Format(C4CFN_ScenarioDesc,szLang); // Save to file return !!hToGroup.Add(sFilename.getData(),sBuffer,false,true); }
void C4GraphicsOverlay::Read(const char **ppInput) { // deprecated assert(false && "C4GraphicsOverlay::Read: deprecated"); #if 0 const char *szReadFrom = *ppInput; // defaults eMode = MODE_None; pSourceGfx = NULL; *Action=0; dwBlitMode = 0; iPhase = 0; iID=0; // read ID SCopyUntil(szReadFrom, OSTR, ',', C4MaxName); szReadFrom += strlen(OSTR); if (*szReadFrom) ++szReadFrom; sscanf(OSTR, "%i", &iID); // read C4ID::Gfxname int32_t iLineLength = SLen(szReadFrom); // not C4ID::Name? if (iLineLength < 6 || szReadFrom[4]!=':' || szReadFrom[5]!=':') { DebugLog("C4Compiler error: Malformed graphics overlay definition!"); return; } // get ID char id[5]; SCopy(szReadFrom, id, 4); szReadFrom += 6; C4Def *pSrcDef = ::Definitions.ID2Def(C4Id(id)); // defaults to NULL for unloaded def if (pSrcDef) { char GfxName[C4MaxName+1]; SCopyUntil(szReadFrom, GfxName, ',', C4MaxName); szReadFrom += strlen(GfxName); if (*szReadFrom) ++szReadFrom; // get graphics - "C4ID::" leads to *szLine == NULL, and thus the default graphic of pSrcDef! pSourceGfx = pSrcDef->Graphics.Get(GfxName); } // read mode DWORD dwRead; SCopyUntil(szReadFrom, OSTR, ',', C4MaxName); szReadFrom += strlen(OSTR); if (*szReadFrom) ++szReadFrom; sscanf(OSTR, "%i", &dwRead); eMode = (Mode) dwRead; // read action SCopyUntil(szReadFrom, Action, ',', C4MaxName); szReadFrom += strlen(Action); if (*szReadFrom) ++szReadFrom; // read blit mode SCopyUntil(szReadFrom, OSTR, ',', C4MaxName); szReadFrom += strlen(OSTR); if (*szReadFrom) ++szReadFrom; sscanf(OSTR, "%i", &dwBlitMode); // read phase SCopyUntil(szReadFrom, OSTR, ',', C4MaxName); szReadFrom += strlen(OSTR); if (*szReadFrom) ++szReadFrom; sscanf(OSTR, "%i", &iPhase); // read transform if (*szReadFrom) ++szReadFrom; // '(' int32_t iScanCnt = sscanf(szReadFrom, "%f,%f,%f,%f,%f,%f,%d", &Transform.mat[0], &Transform.mat[1], &Transform.mat[2], &Transform.mat[3], &Transform.mat[4], &Transform.mat[5], &Transform.FlipDir); if (iScanCnt != 7) { DebugLog("C4Compiler: malformed C4CV_Transform"); } iScanCnt = SCharPos(')', szReadFrom); if (iScanCnt>=0) szReadFrom += iScanCnt+1; // assign ptr immediately after read overlay *ppInput = szReadFrom; // update used facet according to read data UpdateFacet(); #endif }
bool C4GameSave::SaveDesc(C4Group &hToGroup) { // Unfortunately, there's no way to prealloc the buffer in an appropriate size StdStrBuf sBuffer; // Scenario title sBuffer.Append(Game.ScenarioTitle.getData()); sBuffer.Append("\n\n"); // OK; each specializations has its own desc format WriteDesc(sBuffer); // Generate Filename StdStrBuf sFilename; char szLang[3]; SCopyUntil(Config.General.Language, szLang, ',', 2); sFilename.Format(C4CFN_ScenarioDesc,szLang); // Save to file return !!hToGroup.Add(sFilename.getData(),sBuffer,false,true); }
bool C4MessageInput::ProcessCommand(const char *szCommand) { C4GameLobby::MainDlg *pLobby = Game.Network.GetLobby(); // command char szCmdName[C4MaxName + 1]; SCopyUntil(szCommand + 1, szCmdName, ' ', C4MaxName); // parameter const char *pCmdPar = SSearch(szCommand, " "); if (!pCmdPar) pCmdPar = ""; // dev-scripts if (SEqual(szCmdName, "help")) { LogF(LoadResStr("IDS_TEXT_COMMANDSAVAILABLEDURINGGA")); LogF("/private [player] [message] - %s", LoadResStr("IDS_MSG_SENDAPRIVATEMESSAGETOTHES")); LogF("/team [message] - %s", LoadResStr("IDS_MSG_SENDAPRIVATEMESSAGETOYOUR")); LogF("/me [action] - %s", LoadResStr("IDS_TEXT_PERFORMANACTIONINYOURNAME")); LogF("/sound [sound] - %s", LoadResStr("IDS_TEXT_PLAYASOUNDFROMTHEGLOBALSO")); LogF("/kick [client] - %s", LoadResStr("IDS_TEXT_KICKTHESPECIFIEDCLIENT")); LogF("/observer [client] - %s", LoadResStr("IDS_TEXT_SETTHESPECIFIEDCLIENTTOOB")); LogF("/fast [x] - %s", LoadResStr("IDS_TEXT_SETTOFASTMODESKIPPINGXFRA")); LogF("/slow - %s", LoadResStr("IDS_TEXT_SETTONORMALSPEEDMODE")); LogF("/chart - %s", LoadResStr("IDS_TEXT_DISPLAYNETWORKSTATISTICS")); LogF("/nodebug - %s", LoadResStr("IDS_TEXT_PREVENTDEBUGMODEINTHISROU")); LogF("/set comment [comment] - %s", LoadResStr("IDS_TEXT_SETANEWNETWORKCOMMENT")); LogF("/set password [password] - %s", LoadResStr("IDS_TEXT_SETANEWNETWORKPASSWORD")); LogF("/set faircrew [on/off] - %s", LoadResStr("IDS_TEXT_ENABLEORDISABLEFAIRCREW")); LogF("/set maxplayer [4] - %s", LoadResStr("IDS_TEXT_SETANEWMAXIMUMNUMBEROFPLA")); LogF("/script [script] - %s", LoadResStr("IDS_TEXT_EXECUTEASCRIPTCOMMAND")); LogF("/clear - %s", LoadResStr("IDS_MSG_CLEARTHEMESSAGEBOARD")); return TRUE; } // dev-scripts if (SEqual(szCmdName, "script")) { if (!Game.IsRunning) return FALSE; if (!Game.DebugMode) return FALSE; if (!Game.Network.isEnabled() && !SEqual(Game.ScenarioFile.GetMaker(), Config.General.Name) && Game.ScenarioFile.GetStatus() != GRPF_Folder) return FALSE; if (Game.Network.isEnabled() && !Game.Network.isHost()) return FALSE; Game.Control.DoInput( CID_Script, new C4ControlScript(pCmdPar, C4ControlScript::SCOPE_Console, false), CDT_Decide); return TRUE; } // set runtimte properties if (SEqual(szCmdName, "set")) { if (SEqual2(pCmdPar, "maxplayer ")) { if (Game.Control.isCtrlHost()) { if (atoi(pCmdPar + 10) == 0 && !SEqual(pCmdPar + 10, "0")) { Log("Syntax: /set maxplayer count"); return FALSE; } Game.Control.DoInput( CID_Set, new C4ControlSet(C4CVT_MaxPlayer, atoi(pCmdPar + 10)), CDT_Decide); return TRUE; } } if (SEqual2(pCmdPar, "comment ") || SEqual(pCmdPar, "comment")) { if (!Game.Network.isEnabled() || !Game.Network.isHost()) return FALSE; // Set in configuration, update reference Config.Network.Comment.CopyValidated(pCmdPar[7] ? (pCmdPar + 8) : ""); Game.Network.InvalidateReference(); Log(LoadResStr("IDS_NET_COMMENTCHANGED")); return TRUE; } if (SEqual2(pCmdPar, "password ") || SEqual(pCmdPar, "password")) { if (!Game.Network.isEnabled() || !Game.Network.isHost()) return FALSE; Game.Network.SetPassword(pCmdPar[8] ? (pCmdPar + 9) : NULL); if (pLobby) pLobby->UpdatePassword(); return TRUE; } if (SEqual2(pCmdPar, "faircrew ")) { if (!Game.Control.isCtrlHost() || Game.Parameters.isLeague()) return FALSE; C4ControlSet *pSet = NULL; if (SEqual(pCmdPar + 9, "on")) pSet = new C4ControlSet(C4CVT_FairCrew, Config.General.FairCrewStrength); else if (SEqual(pCmdPar + 9, "off")) pSet = new C4ControlSet(C4CVT_FairCrew, -1); else if (isdigit((unsigned char)pCmdPar[9])) pSet = new C4ControlSet(C4CVT_FairCrew, atoi(pCmdPar + 9)); else return FALSE; Game.Control.DoInput(CID_Set, pSet, CDT_Decide); return TRUE; } // unknown property return FALSE; } // get szen from network folder - not in lobby; use res tab there if (SEqual(szCmdName, "netgetscen")) { if (Game.Network.isEnabled() && !Game.Network.isHost() && !pLobby) { const C4Network2ResCore *pResCoreScen = Game.Parameters.Scenario.getResCore(); if (pResCoreScen) { C4Network2Res::Ref pScenario = Game.Network.ResList.getRefRes(pResCoreScen->getID()); if (pScenario) if (C4Group_CopyItem( pScenario->getFile(), Config.AtExePath(GetFilename(Game.ScenarioFilename)))) { LogF(LoadResStr("IDS_MSG_CMD_NETGETSCEN_SAVED"), Config.AtExePath(GetFilename(Game.ScenarioFilename))); return TRUE; } } } return FALSE; } // clear message board if (SEqual(szCmdName, "clear")) { // lobby if (pLobby) { pLobby->ClearLog(); } // fullscreen else if (Game.GraphicsSystem.MessageBoard.Active) Game.GraphicsSystem.MessageBoard.ClearLog(); else { // EM mode Console.ClearLog(); } return TRUE; } // kick client if (SEqual(szCmdName, "kick")) { if (Game.Network.isEnabled() && Game.Network.isHost()) { // find client C4Client *pClient = Game.Clients.getClientByName(pCmdPar); if (!pClient) { LogF(LoadResStr("IDS_MSG_CMD_NOCLIENT"), pCmdPar); return FALSE; } // league: Kick needs voting if (Game.Parameters.isLeague() && Game.Players.GetAtClient(pClient->getID())) Game.Network.Vote(VT_Kick, true, pClient->getID()); else // add control Game.Clients.CtrlRemove(pClient, LoadResStr("IDS_MSG_KICKFROMMSGBOARD")); } return TRUE; } // set fast mode if (SEqual(szCmdName, "fast")) { if (!Game.IsRunning) return FALSE; if (Game.Parameters.isLeague()) { Log(LoadResStr("IDS_LOG_COMMANDNOTALLOWEDINLEAGUE")); return FALSE; } int32_t iFS; if ((iFS = atoi(pCmdPar)) == 0) return FALSE; // set frameskip and fullspeed flag Game.FrameSkip = BoundBy<int32_t>(iFS, 1, 500); Game.FullSpeed = TRUE; // start calculation immediatly Application.NextTick(false); return TRUE; } // reset fast mode if (SEqual(szCmdName, "slow")) { if (!Game.IsRunning) return FALSE; Game.FullSpeed = FALSE; Game.FrameSkip = 1; return TRUE; } if (SEqual(szCmdName, "nodebug")) { if (!Game.IsRunning) return FALSE; Game.Control.DoInput(CID_Set, new C4ControlSet(C4CVT_AllowDebug, false), CDT_Decide); return TRUE; } if (SEqual(szCmdName, "msgboard")) { if (!Game.IsRunning) return FALSE; // get line cnt int32_t iLineCnt = BoundBy(atoi(pCmdPar), 0, 20); if (iLineCnt == 0) Game.GraphicsSystem.MessageBoard.ChangeMode(2); else if (iLineCnt == 1) Game.GraphicsSystem.MessageBoard.ChangeMode(0); else { Game.GraphicsSystem.MessageBoard.iLines = iLineCnt; Game.GraphicsSystem.MessageBoard.ChangeMode(1); } return TRUE; } // kick/activate/deactivate/observer if (SEqual(szCmdName, "activate") || SEqual(szCmdName, "deactivate") || SEqual(szCmdName, "observer")) { if (!Game.Network.isEnabled() || !Game.Network.isHost()) { Log(LoadResStr("IDS_MSG_CMD_HOSTONLY")); return FALSE; } // search for client C4Client *pClient = Game.Clients.getClientByName(pCmdPar); if (!pClient) { LogF(LoadResStr("IDS_MSG_CMD_NOCLIENT"), pCmdPar); return FALSE; } // what to do? C4ControlClientUpdate *pCtrl = NULL; if (szCmdName[0] == 'a') // activate pCtrl = new C4ControlClientUpdate(pClient->getID(), CUT_Activate, true); else if (szCmdName[0] == 'd' && !Game.Parameters.isLeague()) // deactivate pCtrl = new C4ControlClientUpdate(pClient->getID(), CUT_Activate, false); else if (szCmdName[0] == 'o' && !Game.Parameters.isLeague()) // observer pCtrl = new C4ControlClientUpdate(pClient->getID(), CUT_SetObserver); // perform it if (pCtrl) Game.Control.DoInput(CID_ClientUpdate, pCtrl, CDT_Sync); else Log(LoadResStr("IDS_LOG_COMMANDNOTALLOWEDINLEAGUE")); return TRUE; } // control mode if (SEqual(szCmdName, "centralctrl") || SEqual(szCmdName, "decentralctrl") || SEqual(szCmdName, "asyncctrl")) { if (!Game.Network.isEnabled() || !Game.Network.isHost()) { Log(LoadResStr("IDS_MSG_CMD_HOSTONLY")); return FALSE; } if (Game.Parameters.isLeague() && *szCmdName == 'a') { Log(LoadResStr("IDS_LOG_COMMANDNOTALLOWEDINLEAGUE")); return FALSE; } Game.Network.SetCtrlMode( *szCmdName == 'c' ? CNM_Central : *szCmdName == 'd' ? CNM_Decentral : CNM_Async); return TRUE; } // show chart if (Game.IsRunning) if (SEqual(szCmdName, "chart")) return Game.ToggleChart(); // custom command C4MessageBoardCommand *pCmd; if (Game.IsRunning) if (pCmd = GetCommand(szCmdName)) { StdStrBuf Script, CmdScript; // replace %player% by calling player number if (SSearch(pCmd->Script, "%player%")) { int32_t iLocalPlr = NO_OWNER; C4Player *pLocalPlr = Game.Players.GetLocalByIndex(0); if (pLocalPlr) iLocalPlr = pLocalPlr->Number; StdStrBuf sLocalPlr; sLocalPlr.Format("%d", iLocalPlr); CmdScript.Copy(pCmd->Script); CmdScript.Replace("%player%", sLocalPlr.getData()); } else { CmdScript.Ref(pCmd->Script); } // insert parameters if (SSearch(CmdScript.getData(), "%d")) { // make sure it's a number by converting Script.Format(CmdScript.getData(), (int)atoi(pCmdPar)); } else if (SSearch(CmdScript.getData(), "%s")) { // Unrestricted parameters? // That's kind of a security risk as it will allow anyone to execute // code switch (pCmd->eRestriction) { case C4MessageBoardCommand::C4MSGCMDR_Escaped: { // escape strings StdStrBuf Par; Par.Copy(pCmdPar); Par.EscapeString(); // compose script Script.Format(CmdScript.getData(), Par.getData()); } break; case C4MessageBoardCommand::C4MSGCMDR_Plain: // unescaped Script.Format(CmdScript.getData(), pCmdPar); break; case C4MessageBoardCommand::C4MSGCMDR_Identifier: { // only allow identifier-characters StdStrBuf Par; while (IsIdentifier(*pCmdPar) || isspace((unsigned char)*pCmdPar)) Par.AppendChar(*pCmdPar++); // compose script Script.Format(CmdScript.getData(), Par.getData()); } break; } } else Script = CmdScript.getData(); // add script Game.Control.DoInput(CID_Script, new C4ControlScript(Script.getData()), CDT_Decide); // ok return TRUE; } // unknown command StdStrBuf sErr; sErr.Format(LoadResStr("IDS_ERR_UNKNOWNCMD"), szCmdName); if (pLobby) pLobby->OnError(sErr.getData()); else Log(sErr.getData()); return FALSE; }
bool C4MessageInput::ProcessInput(const char *szText) { // helper variables C4ControlMessageType eMsgType; const char *szMsg = NULL; int32_t iToPlayer = -1; // Starts with '^', "team:" or "/team ": Team message if (szText[0] == '^' || SEqual2NoCase(szText, "team:") || SEqual2NoCase(szText, "/team ")) { if (!Game.Teams.IsTeamVisible()) { // team not known; can't send! Log(LoadResStr("IDS_MSG_CANTSENDTEAMMESSAGETEAMSN")); return FALSE; } else { eMsgType = C4CMT_Team; szMsg = szText[0] == '^' ? szText + 1 : szText[0] == '/' ? szText + 6 : szText + 5; } } // Starts with "/private ": Private message (running game only) else if (Game.IsRunning && SEqual2NoCase(szText, "/private ")) { // get target name char szTargetPlr[C4MaxName + 1]; SCopyUntil(szText + 9, szTargetPlr, ' ', C4MaxName); // search player C4Player *pToPlr = Game.Players.GetByName(szTargetPlr); if (!pToPlr) return FALSE; // set eMsgType = C4CMT_Private; iToPlayer = pToPlr->Number; szMsg = szText + 10 + SLen(szTargetPlr); if (szMsg > szText + SLen(szText)) return FALSE; } // Starts with "/me ": Me-Message else if (SEqual2NoCase(szText, "/me ")) { eMsgType = C4CMT_Me; szMsg = szText + 4; } // Starts with "/sound ": Sound-Message else if (SEqual2NoCase(szText, "/sound ")) { eMsgType = C4CMT_Sound; szMsg = szText + 7; } // Starts with "/alert": Taskbar flash (message optional) else if (SEqual2NoCase(szText, "/alert ") || SEqualNoCase(szText, "/alert")) { eMsgType = C4CMT_Alert; szMsg = szText + 6; if (*szMsg) ++szMsg; } // Starts with '"': Let the clonk say it else if (Game.IsRunning && szText[0] == '"') { eMsgType = C4CMT_Say; // Append '"', if neccessary SCopy(szText, OSTR, 400); char *pEnd = OSTR + SLen(OSTR) - 1; if (*pEnd != '"') { *++pEnd = '"'; *++pEnd = 0; } szMsg = OSTR; } // Starts with '/': Command else if (szText[0] == '/') return ProcessCommand(szText); // Regular message else { eMsgType = C4CMT_Normal; szMsg = szText; } // message? if (szMsg) { char szMessage[C4MaxMessage + 1]; // go over whitespaces, check empty message while (IsWhiteSpace(*szMsg)) szMsg++; if (!*szMsg) { if (eMsgType != C4CMT_Alert) return TRUE; *szMessage = '\0'; } else { // trim right const char *szEnd = szMsg + SLen(szMsg) - 1; while (IsWhiteSpace(*szEnd) && szEnd >= szMsg) szEnd--; // Say: Strip quotation marks in cinematic film mode if (Game.C4S.Head.Film == C4SFilm_Cinematic) { if (eMsgType == C4CMT_Say) { ++szMsg; szEnd--; } } // get message SCopy(szMsg, szMessage, Min<unsigned long>(C4MaxMessage, szEnd - szMsg + 1)); } // get sending player (if any) C4Player *pPlr = Game.IsRunning ? Game.Players.GetLocalByIndex(0) : NULL; // send Game.Control.DoInput( CID_Message, new C4ControlMessage(eMsgType, szMessage, pPlr ? pPlr->Number : -1, iToPlayer), CDT_Private); } return TRUE; }
bool C4Application::DoInit() { assert(AppState == C4AS_None); // Config overwrite by parameter StdStrBuf sConfigFilename; char szParameter[_MAX_PATH + 1]; for (int32_t iPar = 0; SGetParameter(GetCommandLine(), iPar, szParameter, _MAX_PATH); iPar++) if (SEqual2NoCase(szParameter, "/config:")) sConfigFilename.Copy(szParameter + 8); // Config check Config.Init(); Config.Load(true, sConfigFilename.getData()); Config.Save(); // sometimes, the configuration can become corrupted due to loading errors or // w/e // check this and reset defaults if necessary if (Config.IsCorrupted()) { if (sConfigFilename) { // custom config corrupted: Fail Log("Warning: Custom configuration corrupted - program abort!\n"); return false; } else { // default config corrupted: Restore default Log("Warning: Configuration corrupted - restoring default!\n"); Config.Default(); Config.Save(); Config.Load(); } } MMTimer = Config.General.MMTimer != 0; // Init C4Group C4Group_SetMaker(Config.General.Name); C4Group_SetProcessCallback(&ProcessCallback); C4Group_SetTempPath(Config.General.TempPath); C4Group_SetSortList(C4CFN_FLS); // Open log if (!OpenLog()) return false; // init system group if (!SystemGroup.Open(C4CFN_System)) { // Error opening system group - no LogFatal, because it needs language // table. // This will *not* use the FatalErrors stack, but this will cause the game // to instantly halt, anyway. Log("Error opening system group file (System.c4g)!"); return false; } // Language override by parameter const char *pLanguage; if (pLanguage = SSearchNoCase(GetCommandLine(), "/Language:")) SCopyUntil(pLanguage, Config.General.LanguageEx, ' ', CFG_MaxString); // Init external language packs Languages.Init(); // Load language string table if (!Languages.LoadLanguage(Config.General.LanguageEx)) // No language table was loaded - bad luck... if (!IsResStrTableLoaded()) Log("WARNING: No language string table loaded!"); // Set unregistered user name C4Group_SetMaker(LoadResStr("IDS_PRC_UNREGUSER")); // Parse command line Game.ParseCommandLine(GetCommandLine()); #ifdef WIN32 // Windows: handle incoming updates directly, even before starting up the gui // because updates will be applied in the console anyway. if (Application.IncomingUpdate) if (C4UpdateDlg::ApplyUpdate(Application.IncomingUpdate.getData(), false, NULL)) return true; #endif // activate Active = TRUE; // Init carrier window if (isFullScreen) { if (!(pWindow = FullScreen.Init(this))) { Clear(); return false; } } else { if (!(pWindow = Console.Init(this))) { Clear(); return false; } } // init timers (needs window) if (!InitTimer()) { LogFatal(LoadResStr("IDS_ERR_TIMER")); Clear(); return false; } // Engine header message Log(C4ENGINEINFOLONG); LogF("Version: %s %s", C4VERSION, C4_OS); #if defined(USE_DIRECTX) && defined(_WIN32) // DDraw emulation warning DWORD DDrawEmulationState; if (GetRegistryDWord(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\DirectDraw", "EmulationOnly", &DDrawEmulationState)) if (DDrawEmulationState) Log("WARNING: DDraw Software emulation is activated!"); #endif // Initialize D3D/OpenGL DDraw = DDrawInit(this, isFullScreen, FALSE, Config.Graphics.BitDepth, Config.Graphics.Engine, Config.Graphics.Monitor); if (!DDraw) { LogFatal(LoadResStr("IDS_ERR_DDRAW")); Clear(); return false; } #if defined(_WIN32) && !defined(USE_CONSOLE) // Register clonk file classes - notice: under Vista this will only work if we // have administrator rights char szModule[_MAX_PATH + 1]; GetModuleFileName(NULL, szModule, _MAX_PATH); SetC4FileClasses(szModule); #endif // Initialize gamepad if (!pGamePadControl && Config.General.GamepadEnabled) pGamePadControl = new C4GamePadControl(); AppState = C4AS_PreInit; return true; }
bool C4FontLoader::InitFont(CStdFont &rFont, const char *szFontName, FontType eType, int32_t iSize, C4GroupSet *pGfxGroups, bool fDoShadow) { // safety if (!szFontName || !*szFontName) { LogFatal(LoadResStr("IDS_ERR_INITFONTS")); return false; } // get font to load // pFontDefs may be NULL if no fonts are loaded; but then iFontDefCount is zero as well // the function must not be aborted, because a standard windows font may be loaded std::vector<C4FontDef>::iterator pFontDefC = FontDefs.begin(), pFontDef = FontDefs.end(); while (pFontDefC != FontDefs.end()) { // check font if (pFontDefC->Name == szFontName) { int32_t iSizeDiff = Abs(pFontDefC->iSize - iSize); // better match than last font? if (pFontDef == FontDefs.end() || Abs(pFontDef->iSize - iSize) >= iSizeDiff) pFontDef = pFontDefC; } // check next one ++pFontDefC; } // if def has not been found, use the def as font name // determine font def string const char *szFontString = szFontName; // special: Fonts without shadow are always newly rendered if (!fDoShadow) { pFontDef=FontDefs.end(); } if (pFontDef!=FontDefs.end()) switch (eType) { case C4FT_Log: szFontString = pFontDef->LogFont.getData(); break; case C4FT_MainSmall:szFontString = pFontDef->SmallFont.getData(); break; case C4FT_Main: szFontString = pFontDef->Font.getData(); break; case C4FT_Caption: szFontString = pFontDef->CaptionFont.getData(); break; case C4FT_Title: szFontString = pFontDef->TitleFont.getData(); break; default: LogFatal(LoadResStr("IDS_ERR_INITFONTS")); return false; // invalid call } // font not assigned? if (!*szFontString) { // invalid call or spec LogFatal(LoadResStr("IDS_ERR_INITFONTS")); return false; } // get font name char FontFaceName[C4MaxName+1], FontParam[C4MaxName+1]; SCopyUntil(szFontString, FontFaceName, ',', C4MaxName); // is it an image file? const char *szExt = GetExtension(FontFaceName); if (SEqualNoCase(szExt, "png") || SEqualNoCase(szExt, "bmp")) { // image file name: load bitmap font from image file // if no graphics group is given, do not load yet if (!pGfxGroups) { LogFatal(LoadResStr("IDS_ERR_INITFONTS")); return false; } // indent given? int32_t iIndent = 0; if (SCopySegment(szFontString, 1, FontParam, ',', C4MaxName)) sscanf(FontParam, "%i", &iIndent); // load font face from gfx group int32_t iGrpId; C4Group *pGrp = pGfxGroups->FindEntry(FontFaceName, NULL, &iGrpId); if (!pGrp) { LogFatal(LoadResStr("IDS_ERR_INITFONTS")); return false; } // check if it's already loaded from that group with that parameters if (!rFont.IsSameAsID(FontFaceName, iGrpId, iIndent)) { // it's not; so (re-)load it now! if (rFont.IsInitialized()) { // reloading rFont.Clear(); LogF(LoadResStr("IDS_PRC_UPDATEFONT"), FontFaceName, iIndent, 0); } C4Surface sfc; if (!sfc.Load(*pGrp, FontFaceName)) { LogFatal(LoadResStr("IDS_ERR_INITFONTS")); return false; } // init font from face try { rFont.Init(GetFilenameOnly(FontFaceName), &sfc, iIndent); } catch (std::runtime_error & e) { LogFatal(e.what()); LogFatal(LoadResStr("IDS_ERR_INITFONTS")); return false; } rFont.id = iGrpId; } } else { int32_t iDefFontSize; DWORD dwDefWeight=FW_NORMAL; #if defined(_WIN32) && !defined(HAVE_FREETYPE) switch (eType) { case C4FT_Log: iDefFontSize = 8; break; case C4FT_MainSmall:iDefFontSize = iSize+1; break; case C4FT_Main: iDefFontSize = iSize+4; break; case C4FT_Caption: iDefFontSize = iSize+6; dwDefWeight = FW_BOLD; break; case C4FT_Title: iDefFontSize = iSize*3; break; default: LogFatal(LoadResStr("IDS_ERR_INITFONTS")); return false; // invalid call } #else switch (eType) { case C4FT_Log: iDefFontSize = iSize*12/14; break; case C4FT_MainSmall:iDefFontSize = iSize*13/14; break; case C4FT_Main: iDefFontSize = iSize; break; case C4FT_Caption: iDefFontSize = iSize*16/14; /*dwDefWeight = FW_MEDIUM;*/ break; case C4FT_Title: iDefFontSize = iSize*22/14; /*dwDefWeight = FW_MEDIUM;*/ break; default: LogFatal(LoadResStr("IDS_ERR_INITFONTS")); return false; // invalid call } #endif // regular font name: let WinGDI or Freetype draw a font with the given parameters // font size given? if (SCopySegment(szFontString, 1, FontParam, ',', C4MaxName)) sscanf(FontParam, "%i", &iDefFontSize); // font weight given? if (SCopySegment(szFontString, 2, FontParam, ',', C4MaxName)) sscanf(FontParam, "%i", &dwDefWeight); // check if it's already loaded from that group with that parameters if (!rFont.IsSameAs(FontFaceName, iDefFontSize, dwDefWeight)) { // it's not; so (re-)load it now! if (rFont.IsInitialized()) { // reloading rFont.Clear(); LogF(LoadResStr("IDS_PRC_UPDATEFONT"), FontFaceName, iDefFontSize, dwDefWeight); } // init with given font name try { // check if one of the internally listed fonts should be used C4VectorFont * pFont = pVectorFonts; while (pFont) { if (SEqual(pFont->Name.getData(), FontFaceName)) { if (InitFont(rFont, pFont, iDefFontSize, dwDefWeight, fDoShadow)) break; } pFont = pFont->pNext; } // no internal font matching? Then create one using the given face/filename (using a system font) if (!pFont) { pFont = new C4VectorFont(); if (pFont->Init(FontFaceName, iDefFontSize, dwDefWeight, Config.General.LanguageCharset)) { AddVectorFont(pFont); if (!InitFont(rFont, pFont, iDefFontSize, dwDefWeight, fDoShadow)) throw std::runtime_error(FormatString("Error initializing font %s", FontFaceName).getData()); } else { delete pFont; // no match for font face found throw std::runtime_error(FormatString("Font face %s undefined", FontFaceName).getData()); } } } catch (std::runtime_error & e) { LogFatal(e.what()); LogFatal(LoadResStr("IDS_ERR_INITFONTS")); return false; } rFont.id = 0; } } // done, success return true; }