bool C4Network2Res::SetByCore(const C4Network2ResCore &nCore, bool fSilent, const char *szAsFilename, int32_t iRecursion) // by main thread { StdStrBuf sFilename; // try open local file const char *szFilename = szAsFilename ? szAsFilename : GetC4Filename(nCore.getFileName()); if (SetByFile(szFilename, false, nCore.getType(), nCore.getID(), nCore.getFileName(), fSilent)) { // check contents checksum if (Core.getContentsCRC() == nCore.getContentsCRC()) { // set core fDirty = true; Core = nCore; // ok then return true; } } // get and search for filename without specified folder (e.g., Castle.ocs when the opened game is Easy.ocf\Castle.ocs) const char *szFilenameOnly = GetFilename(szFilename); const char *szFilenameC4 = GetC4Filename(szFilename); if (szFilenameOnly != szFilenameC4) { sFilename.Copy(szFilename, SLen(szFilename) - SLen(szFilenameC4)); sFilename.Append(szFilenameOnly); if (SetByCore(nCore, fSilent, szFilenameOnly, Config.Network.MaxResSearchRecursion)) return true; } // if it could still not be set, try within all folders of root (ignoring special folders), and try as file outside the folder // but do not recurse any deeper than set by config (default: One folder) if (iRecursion >= Config.Network.MaxResSearchRecursion) return false; StdStrBuf sSearchPath; const char *szSearchPath; if (!iRecursion) szSearchPath = Config.General.ExePath.getData(); else { sSearchPath.Copy(szFilename, SLen(szFilename) - SLen(szFilenameC4)); szSearchPath = sSearchPath.getData(); } StdStrBuf sNetPath; sNetPath.Copy(Config.Network.WorkPath); char *szNetPath = sNetPath.GrabPointer(); TruncateBackslash(szNetPath); sNetPath.Take(szNetPath); for (DirectoryIterator i(szSearchPath); *i; ++i) if (DirectoryExists(*i)) if (!*GetExtension(*i)) // directories without extension only if (!szNetPath || !*szNetPath || !ItemIdentical(*i, szNetPath)) // ignore network path { // search for complete name at subpath (e.g. MyFolder\Easy.ocf\Castle.ocs) sFilename.Format("%s%c%s", *i, DirectorySeparator, szFilenameC4); if (SetByCore(nCore, fSilent, sFilename.getData(), iRecursion + 1)) return true; } // file could not be found locally return false; }
bool C4MusicSystem::InitForScenario(C4Group & hGroup) { // check if the scenario contains music bool fLocalMusic = false; StdStrBuf MusicDir; if (GrpContainsMusic(hGroup)) { // clear global songs ClearSongs(); fLocalMusic = true; // add songs MusicDir.Take(Game.ScenarioFile.GetFullName()); LoadDir(MusicDir.getData()); // log LogF(LoadResStr("IDS_PRC_LOCALMUSIC"), MusicDir.getData()); } // check for music folders in group set C4Group *pMusicFolder = NULL; while ((pMusicFolder = Game.GroupSet.FindGroup(C4GSCnt_Music, pMusicFolder))) { if (!fLocalMusic) { // clear global songs ClearSongs(); fLocalMusic = true; } // add songs MusicDir.Take(pMusicFolder->GetFullName()); MusicDir.AppendChar(DirectorySeparator); MusicDir.Append(C4CFN_Music); LoadDir(MusicDir.getData()); // log LogF(LoadResStr("IDS_PRC_LOCALMUSIC"), MusicDir.getData()); } // no music? if (!SongCount) return false; // set play list SetPlayList(0); // ok return true; }
StdStrBuf C4PropListStatic::GetDataString() const { StdStrBuf r; if (Parent) { r.Take(Parent->GetDataString()); r.AppendChar('.'); } assert(ParentKeyName); if (ParentKeyName) r.Append(ParentKeyName->GetData()); return r; }
bool C4Scenario::Save(C4Group &hGroup, bool fSaveSection) { StdStrBuf Buf; try { Buf.Take(DecompileToBuf<StdCompilerINIWrite>(mkParAdapt(*this, fSaveSection))); } catch (StdCompiler::Exception *) { return false; } if (!hGroup.Add(C4CFN_ScenarioCore,Buf,false,true)) { return false; } return true; }
void C4InteractiveThread::ProcessEvents() // by main thread { C4InteractiveEventType eEventType; void *pEventData; while (PopEvent(&eEventType, &pEventData)) switch (eEventType) { // Logging case Ev_Log: case Ev_LogSilent: case Ev_LogFatal: case Ev_LogDebug: { // Reconstruct the StdStrBuf which allocated the data. StdStrBuf pLog; pLog.Take(reinterpret_cast<char *>(pEventData)); switch (eEventType) { case Ev_Log: Log(pLog.getData()); break; case Ev_LogSilent: LogSilent(pLog.getData()); break; case Ev_LogFatal: LogFatal(pLog.getData()); break; case Ev_LogDebug: DebugLog(pLog.getData()); break; default: assert(eEventType == Ev_Log || eEventType == Ev_LogSilent || eEventType == Ev_LogFatal || eEventType == Ev_LogDebug); // obviously will not happen, but someone tell gcc } } break; case Ev_Function: { std::unique_ptr<std::function<void ()> > func(static_cast<std::function<void()>*>(pEventData)); (*func)(); } // Other events: check for a registered handler default: if (eEventType >= Ev_None && eEventType <= Ev_Last) if (pCallbacks[eEventType]) pCallbacks[eEventType]->OnThreadEvent(eEventType, pEventData); // Note that memory might leak if the event wasn't processed.... } }
C4FileSelDlg::DefaultListItem::DefaultListItem(const char *szFilename, bool fTruncateExtension, bool fCheckbox, bool fGrayed, C4GUI::Icons eIcon) : C4FileSelDlg::ListItem(szFilename), pLbl(NULL), pCheck(NULL), pKeyCheck(NULL), fGrayed(fGrayed) { StdStrBuf sLabel; if (szFilename) sLabel.Ref(::GetFilename(szFilename)); else sLabel.Ref(LoadResStr("IDS_CTL_NONE")); if (szFilename && fTruncateExtension) { sLabel.Copy(); char *szFilename = sLabel.GrabPointer(); RemoveExtension(szFilename); sLabel.Take(szFilename); } rcBounds.Hgt = C4GUI::GetRes()->TextFont.GetLineHeight(); UpdateSize(); C4GUI::ComponentAligner caMain(GetContainedClientRect(), 0, 0); int32_t iHeight = caMain.GetInnerHeight(); if (fCheckbox) { pCheck = new C4GUI::CheckBox(caMain.GetFromLeft(iHeight), NULL, false); if (fGrayed) pCheck->SetEnabled(false); AddElement(pCheck); pKeyCheck = new C4KeyBinding( C4KeyCodeEx(K_SPACE), "FileSelToggleFileActive", KEYSCOPE_Gui, new C4GUI::ControlKeyCB<ListItem>(*this, &ListItem::UserToggleCheck), C4CustomKey::PRIO_Ctrl); } C4GUI::Icon *pIco = new C4GUI::Icon(caMain.GetFromLeft(iHeight), eIcon); AddElement(pIco); pLbl = new C4GUI::Label( sLabel.getData(), caMain.GetAll(), ALeft, fGrayed ? C4GUI_CheckboxDisabledFontClr : C4GUI_CheckboxFontClr); AddElement(pLbl); }
StdStrBuf C4ObjectList::GetDataString() { StdStrBuf Output; // Compose info text by selected object(s) switch (ObjectCount()) { // No selection case 0: Output = LoadResStr("IDS_CNS_NOOBJECT"); break; // One selected object case 1: Output.Take(GetObject()->GetDataString()); break; // Multiple selected objects default: Output.Format(LoadResStr("IDS_CNS_MULTIPLEOBJECTS"),ObjectCount()); break; } return Output; }
void C4GameOptionsList::OptionTeamDist::Update() { StdStrBuf sOption; sOption.Take(Game.Teams.GetTeamDistString()); pDropdownList->SetText(sOption.getData()); }
void C4KeyCodeEx::CompileFunc(StdCompiler *pComp, StdStrBuf *pOutBuf) { if (pComp->isCompiler()) { // reading from file StdStrBuf sCode; bool is_scan_code; // read shifts DWORD dwSetShift = 0; for (;;) { is_scan_code = pComp->Separator(StdCompiler::SEP_DOLLAR); if (!is_scan_code) pComp->NoSeparator(); pComp->Value(mkParAdapt(sCode, StdCompiler::RCT_Idtf)); if (is_scan_code) // scan codes start with $. Reassamble the two tokens that were split by StdCompiler { sCode.Take(FormatString("$%s", sCode.getData())); break; } if (!pComp->Separator(StdCompiler::SEP_PLUS)) break; // no more separator: Parse this as keyboard code // try to convert to shift state C4KeyShiftState eAddState = String2KeyShift(sCode); if (eAddState == KEYS_Undefined) pComp->excCorrupt("undefined key shift state: %s", sCode.getData()); dwSetShift |= eAddState; } // any code given? Otherwise, keep default if (sCode.getLength()) { // last section: convert to key code C4KeyCode eCode = String2KeyCode(sCode); if (eCode == KEY_Undefined) { if (pOutBuf) { // unknown key, but an output buffer for unknown keys was provided. No failure; caller might resolve key. eCode = KEY_Default; } else { pComp->excCorrupt("undefined key code: %s", sCode.getData()); } } dwShift = dwSetShift; Key = eCode; if (pOutBuf) pOutBuf->Take(std::move(sCode)); } } else { // write shift states for (DWORD dwShiftCheck = KEYS_First; dwShiftCheck <= KEYS_Max; dwShiftCheck <<= 1) if (dwShiftCheck & dwShift) { pComp->Value(mkDecompileAdapt(KeyShift2String((C4KeyShiftState) dwShiftCheck))); pComp->Separator(StdCompiler::SEP_PLUS); } // write key pComp->Value(mkDecompileAdapt(KeyCode2String(Key, false, false))); } }
StdStrBuf C4KeyCodeEx::KeyCode2String(C4KeyCode wCode, bool fHumanReadable, bool fShort) { // Gamepad keys if (Key_IsGamepad(wCode)) { int iGamepad = Key_GetGamepad(wCode); int gamepad_event = Key_GetGamepadEvent(wCode); switch (gamepad_event) { case KEY_JOY_Left: return FormatString("Joy%dLeft", iGamepad+1); case KEY_JOY_Up: return FormatString("Joy%dUp", iGamepad+1); case KEY_JOY_Down: return FormatString("Joy%dDown", iGamepad+1); case KEY_JOY_Right: return FormatString("Joy%dRight", iGamepad+1); default: if (Key_IsGamepadAxis(wCode)) { if (fHumanReadable) // This is still not great, but it is not really possible to assign unknown axes to "left/right" "up/down"... return FormatString("[%d] %s", int(1 + Key_GetGamepadAxisIndex(wCode)), Key_IsGamepadAxisHigh(wCode) ? "Max" : "Min"); else return FormatString("Joy%dAxis%d%s", iGamepad+1, static_cast<int>(Key_GetGamepadAxisIndex(wCode)+1), Key_IsGamepadAxisHigh(wCode) ? "Max" : "Min"); } else { // button if (fHumanReadable) // If there should be gamepads around with A B C D... on the buttons, we might create a display option to show letters instead... return FormatString("< %d >", int(1 + Key_GetGamepadButtonIndex(wCode))); else return FormatString("Joy%d%c", iGamepad+1, static_cast<char>(Key_GetGamepadButtonIndex(wCode) + 'A')); } } } // Mouse keys if (Key_IsMouse(wCode)) { int mouse_id = Key_GetMouse(wCode); int mouse_event = Key_GetMouseEvent(wCode); const char *mouse_str = "Mouse"; switch (mouse_event) { case KEY_MOUSE_Move: return FormatString("%s%dMove", mouse_str, mouse_id); case KEY_MOUSE_Wheel1Up: return FormatString("%s%dWheel1Up", mouse_str, mouse_id); case KEY_MOUSE_Wheel1Down: return FormatString("%s%dWheel1Down", mouse_str, mouse_id); case KEY_MOUSE_ButtonLeft: return FormatString("%s%dLeft", mouse_str, mouse_id); case KEY_MOUSE_ButtonRight: return FormatString("%s%dRight", mouse_str, mouse_id); case KEY_MOUSE_ButtonMiddle: return FormatString("%s%dMiddle", mouse_str, mouse_id); case KEY_MOUSE_ButtonLeftDouble: return FormatString("%s%dLeftDouble", mouse_str, mouse_id); case KEY_MOUSE_ButtonRightDouble: return FormatString("%s%dRightDouble", mouse_str, mouse_id); case KEY_MOUSE_ButtonMiddleDouble:return FormatString("%s%dMiddleDouble", mouse_str, mouse_id); default: // extended mouse button { uint8_t btn = Key_GetMouseEvent(wCode); if (btn >= KEY_MOUSE_Button1Double) return FormatString("%s%dButton%dDouble", mouse_str, mouse_id, int(btn-KEY_MOUSE_Button1Double)); else return FormatString("%s%dButton%d", mouse_str, mouse_id, int(btn-KEY_MOUSE_Button1)); } } } // it's a keyboard key if (!fHumanReadable) { // for config files and such: dump scancode return FormatString("$%x", static_cast<unsigned int>(wCode)); } #if defined(_WIN32) // TODO: Works? // StdStrBuf Name; Name.SetLength(1000); // int res = GetKeyNameText(wCode, Name.getMData(), Name.getSize()); // if(!res) // // not found: Compose as direct code // return FormatString("\\x%x", (DWORD) wCode); // // Set size // Name.SetLength(res); // return Name; wchar_t buf[100]; int len = GetKeyNameText(wCode<<16, buf, 100); if (len > 0) { // buf is nullterminated name return StdStrBuf(buf); } #elif defined (USE_COCOA) // query map const C4KeyCodeMapEntry *pCheck = KeyCodeMap; while (pCheck->szName) if (wCode == pCheck->wCode) return StdStrBuf((pCheck->szShortName && fShort) ? pCheck->szShortName : pCheck->szName); else ++pCheck; // not found: Compose as direct code return FormatString("\\x%x", static_cast<unsigned int>(wCode)); #elif defined(USE_X11) Display * const dpy = gdk_x11_display_get_xdisplay(gdk_display_get_default()); KeySym keysym = (KeySym)XkbKeycodeToKeysym(dpy,wCode+8,0,0); char* name = NULL; if (keysym != NoSymbol) { // is the keycode without shift modifiers mapped to a symbol? #if defined(USE_GTK3) name = gtk_accelerator_get_label_with_keycode(dpy, keysym, wCode+8, (GdkModifierType)0); #else name = gtk_accelerator_get_label(keysym, (GdkModifierType)0); #endif } if (name) { // is there a string representation of the keysym? // prevent memleak StdStrBuf buf; buf.Take(name); return buf; } #elif defined(USE_SDL_MAINLOOP) return StdStrBuf(getKeyName(wCode).c_str()); #endif return FormatString("$%x", static_cast<unsigned int>(wCode)); }
bool C4MainMenu::DoRefillInternal(bool &rfRefilled) { // Variables C4FacetSurface fctSymbol; C4Player *pPlayer; C4IDList ListItems; C4Facet fctTarget; bool fWasEmpty = !GetItemCount(); // Refill switch (Identification) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case C4MN_Hostility: { // Clear items ClearItems(); // Refill player if (!(pPlayer = ::Players.Get(Player))) return false; // Refill items C4Player *pPlr; int32_t iIndex; for (iIndex=0; (pPlr = ::Players.GetByIndex(iIndex)); iIndex++) // Ignore player self and invisible if (pPlr != pPlayer) if (!pPlr->IsInvisible()) { // Symbol fctSymbol.Create(C4SymbolSize,C4SymbolSize); pPlayer->DrawHostility(fctSymbol,iIndex); // Message StdStrBuf sMsg; bool isFriendly = pPlayer->Hostility.find(pPlr) == pPlayer->Hostility.end(); if (isFriendly) sMsg.Format(LoadResStr("IDS_MENU_ATTACK"),pPlr->GetName()); else sMsg.Format(LoadResStr("IDS_MENU_NOATTACK"),pPlr->GetName()); // Command char szCommand[1000]; sprintf(szCommand,"SetHostility:%i",pPlr->Number); // Info caption char szInfoCaption[C4MaxTitle+1],szFriendly[50],szNot[30]=""; SCopy(LoadResStr(isFriendly ? "IDS_MENU_ATTACKHOSTILE" : "IDS_MENU_ATTACKFRIENDLY"),szFriendly); if (!isFriendly) SCopy(LoadResStr("IDS_MENU_ATTACKNOT"),szNot); sprintf(szInfoCaption,LoadResStr("IDS_MENU_ATTACKINFO"),pPlr->GetName(),szFriendly,szNot); if (iIndex==pPlayer->Number) SCopy(LoadResStr("IDS_MENU_ATTACKSELF"),szInfoCaption); // Add item Add(sMsg.getData(),fctSymbol,szCommand,C4MN_Item_NoCount,NULL,szInfoCaption); fctSymbol.Default(); } break; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case C4MN_TeamSelection: case C4MN_TeamSwitch: { // Clear items ClearItems(); // add all teams as menu items // 2do: Icon C4Team *pTeam; int32_t i=0; bool fAddNewTeam=Game.Teams.IsAutoGenerateTeams(); for (;;) { pTeam = Game.Teams.GetTeamByIndex(i); if (pTeam) { // next regular team ++i; // do not add a new team if an empty team exists if (!pTeam->GetPlayerCount()) fAddNewTeam = false; } else if (fAddNewTeam) { // join new team fAddNewTeam = false; } else { // all teams done break; } // create team symbol: Icon spec if specified; otherwise flag for empty and crew for nonempty team fctSymbol.Create(C4SymbolSize,C4SymbolSize); const char *szIconSpec = pTeam ? pTeam->GetIconSpec() : NULL; bool fHasIcon = false; if (szIconSpec && *szIconSpec) { fHasIcon = Game.DrawTextSpecImage(fctSymbol, szIconSpec, NULL, pTeam->GetColor()); } if (!fHasIcon) { if (pTeam && pTeam->GetPlayerCount()) ::GraphicsResource.fctCrewClr.DrawClr(fctSymbol, true, pTeam->GetColor()); else C4GUI::Icon::GetIconFacet(C4GUI::Ico_Team).Draw(fctSymbol, true); } StdStrBuf sTeamName; if (pTeam) { sTeamName.Take(pTeam->GetNameWithParticipants()); } else sTeamName.Ref(LoadResStr("IDS_PRC_NEWTEAM")); const char *szOperation = (Identification == C4MN_TeamSwitch) ? "TeamSwitch" : "TeamSel"; Add(sTeamName.getData(), fctSymbol,FormatString("%s:%d", szOperation, pTeam ? pTeam->GetID() : TEAMID_New).getData(), C4MN_Item_NoCount,NULL,FormatString(LoadResStr("IDS_MSG_JOINTEAM"), sTeamName.getData()).getData(), C4ID(pTeam ? pTeam->GetID() : 0)); fctSymbol.Default(); } break; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case C4MN_Observer: // observer menu { // Clear items ClearItems(); // Check validity C4Viewport *pVP = ::Viewports.GetViewport(NO_OWNER); if (!pVP) return false; int32_t iInitialSelection = 0; // Add free view AddRefSym(LoadResStr("IDS_MSG_FREEVIEW"), C4GUI::Icon::GetIconFacet(C4GUI::Ico_Star), "Observe:Free", C4MN_Item_NoCount, NULL, LoadResStr("IDS_MSG_FREELYSCROLLAROUNDTHEMAP")); // Add players C4Player *pPlr; int32_t iIndex; for (iIndex=0; (pPlr = ::Players.GetByIndex(iIndex)); iIndex++) { // Ignore invisible if (!pPlr->IsInvisible()) { // Symbol fctSymbol.Create(C4SymbolSize,C4SymbolSize); ::GraphicsResource.fctPlayerClr.DrawClr(fctSymbol, true, pPlr->ColorDw); // Message StdStrBuf sMsg; DWORD dwClr = pPlr->ColorDw; sMsg.Format("<c %x>%s</c>", (unsigned int)C4GUI::MakeColorReadableOnBlack(dwClr), pPlr->GetName()); // Command StdStrBuf sCommand; sCommand.Format("Observe:%d", (int)pPlr->Number); // Info caption StdStrBuf sInfo; sInfo.Format(LoadResStr("IDS_TEXT_FOLLOWVIEWOFPLAYER"), pPlr->GetName()); // Add item Add(sMsg.getData(),fctSymbol,sCommand.getData(),C4MN_Item_NoCount,NULL,sInfo.getData()); fctSymbol.Default(); // check if this is the currently selected player if (pVP->GetPlayer() == pPlr->Number) iInitialSelection = GetItemCount()-1; } // Initial selection on followed player if (fWasEmpty) SetSelection(iInitialSelection, false, true); } } break; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - default: // No internal refill needed return true; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - } // Successfull internal refill rfRefilled = true; return true; }