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;
}
Example #3
0
StdStrBuf C4PropListStatic::GetDataString() const
{
	StdStrBuf r;
	if (Parent)
	{
		r.Take(Parent->GetDataString());
		r.AppendChar('.');
	}
	assert(ParentKeyName);
	if (ParentKeyName)
		r.Append(ParentKeyName->GetData());
	return r;
}
Example #4
0
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....
		}
}
Example #6
0
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);
}
Example #7
0
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)));
    }
}
Example #10
0
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));
}
Example #11
0
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;
}