PageRenderTime 78ms CodeModel.GetById 17ms app.highlight 45ms RepoModel.GetById 0ms app.codeStats 1ms

/src/gui/C4StartupMainDlg.cpp

https://bitbucket.org/randrian/openclonk2
C++ | 469 lines | 327 code | 40 blank | 102 comment | 49 complexity | 7d497d8c080f583b6e48e08848b888c3 MD5 | raw file
Possible License(s): WTFPL, 0BSD, LGPL-2.1, CC-BY-3.0
  1/*
  2 * OpenClonk, http://www.openclonk.org
  3 *
  4 * Copyright (c) 2005-2007  Sven Eberhardt
  5 * Copyright (c) 2005-2008  Matthes Bender
  6 * Copyright (c) 2006  G?nther Brammer
  7 * Copyright (c) 2009  Nicolas Hake
  8 * Copyright (c) 2005-2009, RedWolf Design GmbH, http://www.clonk.de
  9 *
 10 * Portions might be copyrighted by other authors who have contributed
 11 * to OpenClonk.
 12 *
 13 * Permission to use, copy, modify, and/or distribute this software for any
 14 * purpose with or without fee is hereby granted, provided that the above
 15 * copyright notice and this permission notice appear in all copies.
 16 * See isc_license.txt for full license and disclaimer.
 17 *
 18 * "Clonk" is a registered trademark of Matthes Bender.
 19 * See clonk_trademark_license.txt for full license.
 20 */
 21// Startup screen for non-parameterized engine start (stub)
 22
 23#include <C4Include.h>
 24#include <C4StartupMainDlg.h>
 25#include <C4UpdateDlg.h>
 26#include <C4Version.h>
 27
 28#ifndef BIG_C4INCLUDE
 29#include <C4StartupNetDlg.h>
 30#include <C4StartupScenSelDlg.h>
 31#include <C4StartupOptionsDlg.h>
 32#include <C4StartupAboutDlg.h>
 33#include <C4StartupPlrSelDlg.h>
 34#include <C4Startup.h>
 35#include <C4Game.h>
 36#include <C4Log.h>
 37#include <C4Language.h>
 38#include <C4GraphicsResource.h>
 39#endif
 40
 41
 42C4StartupMainDlg::C4StartupMainDlg() : C4StartupDlg(NULL) // create w/o title; it is drawn in custom draw proc
 43	{
 44	// ctor
 45	fFirstShown = true;
 46	// screen calculations
 47	int iButtonPadding = 2;
 48	int iButtonHeight = C4GUI_BigButtonHgt;
 49	C4GUI::ComponentAligner caMain(rcBounds, 0,0,true);
 50	C4GUI::ComponentAligner caRightPanel(caMain.GetFromLeft(rcBounds.Wdt*2/5), rcBounds.Wdt/26,40+rcBounds.Hgt/8);
 51	//C4GUI::ComponentAligner caButtons(caRightPanel.GetCentered(caRightPanel.GetWidth(), (iButtonHeight+iButtonPadding) * iButtonCount - iButtonPadding), 0, iButtonPadding);
 52	C4GUI::ComponentAligner caButtons(caRightPanel.GetAll(), 0, iButtonPadding);
 53	// main menu buttons
 54	C4GUI::CallbackButton<C4StartupMainDlg> *btn;
 55	AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_BTN_LOCALGAME"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnStartBtn));
 56	btn->SetToolTip(LoadResStr("IDS_DLGTIP_STARTGAME"));
 57	btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
 58	pStartButton = btn;
 59	AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_BTN_NETWORKGAME"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnNetJoinBtn));
 60	btn->SetToolTip(LoadResStr("IDS_DLGTIP_NETWORKGAME"));
 61	btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
 62	AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_DLG_PLAYERSELECTION"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnPlayerSelectionBtn));
 63	btn->SetToolTip(LoadResStr("IDS_DLGTIP_PLAYERSELECTION"));
 64	btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
 65	AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_DLG_OPTIONS"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnOptionsBtn));
 66	btn->SetToolTip(LoadResStr("IDS_DLGTIP_OPTIONS"));
 67	btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
 68	AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_DLG_ABOUT"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnAboutBtn));
 69	btn->SetToolTip(LoadResStr("IDS_DLGTIP_ABOUT"));
 70	btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
 71	AddElement(btn = new C4GUI::CallbackButton<C4StartupMainDlg>(LoadResStr("IDS_DLG_EXIT"), caButtons.GetFromTop(iButtonHeight), &C4StartupMainDlg::OnExitBtn));
 72	btn->SetToolTip(LoadResStr("IDS_DLGTIP_EXIT"));
 73	btn->SetCustomGraphics(&C4Startup::Get()->Graphics.barMainButtons, &C4Startup::Get()->Graphics.barMainButtonsDown);
 74	// list of selected players
 75	AddElement(pParticipantsLbl = new C4GUI::Label("test", GetClientRect().Wdt*39/40, GetClientRect().Hgt*9/10, ARight, 0xffffffff, &C4GUI::GetRes()->TitleFont, false));
 76	pParticipantsLbl->SetToolTip(LoadResStr("IDS_DLGTIP_SELECTEDPLAYERS"));
 77	// player selection shortcut - to be made optional
 78	UpdateParticipants();
 79	pParticipantsLbl->SetContextHandler(new C4GUI::CBContextHandler<C4StartupMainDlg>(this, &C4StartupMainDlg::OnPlayerSelContext));
 80	/*new C4GUI::ContextButton(pParticipantsLbl, true, 0,0);*/
 81	// key bindings
 82	C4CustomKey::CodeList keys;
 83	keys.push_back(C4KeyCodeEx(K_DOWN)); keys.push_back(C4KeyCodeEx(K_RIGHT));
 84	if (Config.Controls.GamepadGuiControl)
 85		{
 86		keys.push_back(C4KeyCodeEx(KEY_Gamepad(0, KEY_JOY_Down))); // right will be done by Dialog already
 87		}
 88	pKeyDown = new C4KeyBinding(keys, "StartupMainCtrlNext", KEYSCOPE_Gui,
 89		new C4GUI::DlgKeyCBEx<C4StartupMainDlg, bool>(*this, false, &C4StartupMainDlg::KeyAdvanceFocus), C4CustomKey::PRIO_CtrlOverride);
 90	keys.clear(); keys.push_back(C4KeyCodeEx(K_UP)); keys.push_back(C4KeyCodeEx(K_LEFT));
 91	if (Config.Controls.GamepadGuiControl)
 92		{
 93		keys.push_back(C4KeyCodeEx(KEY_Gamepad(0, KEY_JOY_Up))); // left will be done by Dialog already
 94		}
 95	pKeyUp = new C4KeyBinding(keys, "StartupMainCtrlPrev", KEYSCOPE_Gui,
 96		new C4GUI::DlgKeyCBEx<C4StartupMainDlg, bool>(*this, true, &C4StartupMainDlg::KeyAdvanceFocus), C4CustomKey::PRIO_CtrlOverride);
 97	keys.clear(); keys.push_back(C4KeyCodeEx(K_RETURN));
 98	pKeyEnter = new C4KeyBinding(keys, "StartupMainOK", KEYSCOPE_Gui,
 99		new C4GUI::DlgKeyCB<C4StartupMainDlg>(*this, &C4StartupMainDlg::KeyEnterDown, &C4StartupMainDlg::KeyEnterUp), C4CustomKey::PRIO_CtrlOverride);
100	keys.clear(); keys.push_back(C4KeyCodeEx(K_F6));
101	pKeyEditor = new C4KeyBinding(keys, "StartupMainEditor", KEYSCOPE_Gui,
102		new C4GUI::DlgKeyCB<C4StartupMainDlg>(*this, &C4StartupMainDlg::SwitchToEditor, false), C4CustomKey::PRIO_CtrlOverride);
103	}
104
105C4StartupMainDlg::~C4StartupMainDlg()
106	{
107	// dtor
108	delete pKeyEnter;
109	delete pKeyUp;
110	delete pKeyDown;
111	delete pKeyEditor;
112	}
113
114void C4StartupMainDlg::DrawElement(C4TargetFacet &cgo)
115	{
116	// inherited
117	typedef C4GUI::FullscreenDialog Base;
118	Base::DrawElement(cgo);
119	// draw logo
120	C4Facet &fctLogo = ::GraphicsResource.fctLogo;
121	float fLogoZoom = 1.0f;
122	fctLogo.DrawX(cgo.Surface, rcBounds.Wdt *1/21, rcBounds.Hgt/14 - 5, int32_t(fLogoZoom*fctLogo.Wdt), int32_t(fLogoZoom*fctLogo.Hgt));
123	// draw version info
124	StdStrBuf sVer;
125	sVer.Format(LoadResStr("IDS_DLG_VERSION"), C4VERSION);
126	if (!Config.Registered())
127		{ sVer += " <c ff0000>["; sVer += LoadResStr("IDS_CTL_UNREGISTERED"); sVer += "]</c>"; }
128	lpDDraw->TextOut(sVer.getData(), C4GUI::GetRes()->TextFont, 1.0f, cgo.Surface, rcBounds.Wdt*1/40, rcBounds.Hgt/12 + int32_t(fLogoZoom*fctLogo.Hgt) - 10, 0xffffffff, ALeft, true);
129	}
130
131C4GUI::ContextMenu *C4StartupMainDlg::OnPlayerSelContext(C4GUI::Element *pBtn, int32_t iX, int32_t iY)
132	{
133	// preliminary player selection via simple context menu
134	C4GUI::ContextMenu *pCtx = new C4GUI::ContextMenu();
135	pCtx->AddItem("Add", "Add participant", C4GUI::Ico_None, NULL, new C4GUI::CBContextHandler<C4StartupMainDlg>(this, &C4StartupMainDlg::OnPlayerSelContextAdd));
136	pCtx->AddItem("Remove", "Remove participant", C4GUI::Ico_None, NULL, new C4GUI::CBContextHandler<C4StartupMainDlg>(this, &C4StartupMainDlg::OnPlayerSelContextRemove));
137	return pCtx;
138	}
139
140C4GUI::ContextMenu *C4StartupMainDlg::OnPlayerSelContextAdd(C4GUI::Element *pBtn, int32_t iX, int32_t iY)
141	{
142	C4GUI::ContextMenu *pCtx = new C4GUI::ContextMenu();
143	const char *szFn;
144	StdStrBuf sSearchPath(Config.General.UserDataPath);
145//	sSearchPath.Format("%s%s", (const char *) Config.General.ExePath, (const char *) Config.General.PlayerPath);
146	for (DirectoryIterator i(sSearchPath.getData()); szFn=*i; i++)
147		{
148		szFn = Config.AtRelativePath(szFn);
149		if (*GetFilename(szFn) == '.') continue;
150		if (!WildcardMatch(C4CFN_PlayerFiles, GetFilename(szFn))) continue;
151		if (!SIsModule(Config.General.Participants, szFn, NULL, false))
152			pCtx->AddItem(C4Language::IconvClonk(GetFilenameOnly(szFn)).getData(), "Let this player join in next game", C4GUI::Ico_Player,
153				new C4GUI::CBMenuHandlerEx<C4StartupMainDlg, StdCopyStrBuf>(this, &C4StartupMainDlg::OnPlayerSelContextAddPlr, StdCopyStrBuf(szFn)), NULL);
154		}
155	return pCtx;
156	}
157
158C4GUI::ContextMenu *C4StartupMainDlg::OnPlayerSelContextRemove(C4GUI::Element *pBtn, int32_t iX, int32_t iY)
159	{
160	C4GUI::ContextMenu *pCtx = new C4GUI::ContextMenu();
161	char szPlayer[1024+1];
162	for (int i = 0; SCopySegment(Config.General.Participants, i, szPlayer, ';', 1024, true); i++)
163		if (*szPlayer)
164			pCtx->AddItem(GetFilenameOnly(szPlayer), "Remove this player from participation list", C4GUI::Ico_Player, new C4GUI::CBMenuHandlerEx<C4StartupMainDlg, int>(this, &C4StartupMainDlg::OnPlayerSelContextRemovePlr, i), NULL);
165	return pCtx;
166	}
167
168void C4StartupMainDlg::OnPlayerSelContextAddPlr(C4GUI::Element *pTarget, const StdCopyStrBuf &rsFilename)
169	{
170	SAddModule(Config.General.Participants, rsFilename.getData());
171	UpdateParticipants();
172	}
173
174void C4StartupMainDlg::OnPlayerSelContextRemovePlr(C4GUI::Element *pTarget, const int &iIndex)
175	{
176	char szPlayer[1024+1];
177	if (SCopySegment(Config.General.Participants, iIndex, szPlayer, ';', 1024, true))
178		SRemoveModule(Config.General.Participants, szPlayer, false);
179	UpdateParticipants();
180	}
181
182void C4StartupMainDlg::UpdateParticipants()
183	{
184	// First validate all participants (files must exist)
185	std::string strPlayers(Config.General.Participants);
186	std::string strPlayer;
187	strPlayer.reserve(1025);
188	*Config.General.Participants=0;
189	for (int i = 0; SCopySegment(strPlayers.c_str(), i, &strPlayer[0], ';', 1024, true); i++)
190		{
191		const char *szPlayer = strPlayer.c_str();
192		std::string strPlayerFile(Config.General.UserDataPath);
193		strPlayerFile.append(szPlayer);
194		if (!szPlayer || !*szPlayer) continue;
195		if (!FileExists(strPlayerFile.c_str())) continue;
196		if (!SEqualNoCase(GetExtension(szPlayer), "c4p")) continue; // additional sanity check to clear strange exe-path-only entries in player list?
197		SAddModule(Config.General.Participants, szPlayer);
198		}
199	// Draw selected players - we are currently displaying the players stored in Config.General.Participants.
200	// Existence of the player files is not validated and player filenames are displayed directly
201	// (names are not loaded from the player core).
202	strPlayers = LoadResStr("IDS_DESC_PLRS");
203	if (!Config.General.Participants[0])
204		strPlayers.append(LoadResStr("IDS_DLG_NOPLAYERSSELECTED"));
205	else
206		for (int i = 0; SCopySegment(Config.General.Participants, i, &strPlayer[0], ';', 1024, true); i++)
207			{
208			if (i > 0) strPlayers.append(", ");
209			strPlayers.append(C4Language::IconvClonk(GetFilenameOnly(strPlayer.c_str())).getData());
210			}
211	pParticipantsLbl->SetText(strPlayers.c_str());
212	}
213
214void C4StartupMainDlg::OnClosed(bool fOK)
215	{
216	// if dlg got aborted (by user), quit startup
217	// if it got closed with OK, the user pressed one of the buttons and dialog switching has been done already
218	if (!fOK) C4Startup::Get()->Exit();
219	}
220
221void C4StartupMainDlg::OnStartBtn(C4GUI::Control *btn)
222	{
223	// no regular game start if no players were selected
224	/*if (!*Config.General.Participants)
225		{
226		StdStrBuf buf(LoadResStrNoAmp("IDS_DLG_STARTGAME"), true);
227		GetScreen()->ShowMessageModal(LoadResStr("IDS_MSG_NOPLAYERSELECTED"), buf.getData(), C4GUI::MessageDialog::btnOK, C4GUI::Ico_Notify);
228		// let's go to the player selection dlg then instead
229		OnPlayerSelectionBtn(NULL);
230		return;
231		}*/
232	// advance to scenario selection screen
233	C4Startup::Get()->SwitchDialog(C4Startup::SDID_ScenSel);
234	}
235
236void C4StartupMainDlg::OnPlayerSelectionBtn(C4GUI::Control *btn)
237	{
238	// advance to player selection screen
239	C4Startup::Get()->SwitchDialog(C4Startup::SDID_PlrSel);
240	}
241
242void C4StartupMainDlg::OnNetJoinBtn(C4GUI::Control *btn)
243	{
244	// simple net join dlg
245	//GetScreen()->ShowDialog(new C4GUI::InputDialog("Enter host IP", "Direct join", C4GUI::Ico_Host, new C4GUI::InputCallback<C4StartupMainDlg>(this, &C4StartupMainDlg::OnNetJoin)), false);
246	// advanced net join and host dlg!
247	C4Startup::Get()->SwitchDialog(C4Startup::SDID_NetJoin);
248	}
249
250void C4StartupMainDlg::OnNetJoin(const StdStrBuf &rsHostAddress)
251	{
252	// no IP given: No join
253	if (!rsHostAddress || !*rsHostAddress.getData()) return;
254	// set default startup parameters
255	*Game.ScenarioFilename=0;
256	SCopy("Objects.c4d", Game.DefinitionFilenames);
257	Game.NetworkActive = true;
258	Game.fLobby = true;
259	Game.fObserve = false;
260	SCopy(rsHostAddress.getData(), Game.DirectJoinAddress, sizeof(Game.DirectJoinAddress)-1);
261	// start with this set!
262	C4Startup::Get()->Start();
263	}
264
265void C4StartupMainDlg::OnOptionsBtn(C4GUI::Control *btn)
266	{
267	// advance to options screen
268	C4Startup::Get()->SwitchDialog(C4Startup::SDID_Options);
269	}
270
271void C4StartupMainDlg::OnAboutBtn(C4GUI::Control *btn)
272	{
273	// advance to about screen
274	C4Startup::Get()->SwitchDialog(C4Startup::SDID_About);
275	}
276
277void C4StartupMainDlg::OnExitBtn(C4GUI::Control *btn)
278	{
279	// callback: exit button pressed
280	C4Startup::Get()->Exit();
281	}
282
283void C4StartupMainDlg::OnTODO(C4GUI::Control *btn)
284	{
285	GetScreen()->ShowMessage("not yet implemented", "2do", C4GUI::Ico_Error);
286	}
287
288bool C4StartupMainDlg::KeyEnterDown()
289	{
290	// just execute selected button: Re-Send as space
291	return Game.DoKeyboardInput(K_SPACE, KEYEV_Down, false, false, false, false, this);
292	}
293
294bool C4StartupMainDlg::KeyEnterUp()
295	{
296	// just execute selected button: Re-Send as space
297	return Game.DoKeyboardInput(K_SPACE, KEYEV_Up, false, false, false, false, this);
298	}
299
300void C4StartupMainDlg::OnShown()
301	{
302
303	// New valid registration key found (in working directory or key path)
304	if (Config.Registered() && !Config.Security.WasRegistered)
305		HandleIncomingKeyfile(Config.GetKeyFilename());
306	// Incoming key file from command line
307	else if (Application.IncomingKeyfile)
308		HandleIncomingKeyfile(Application.IncomingKeyfile.getData());
309	// An invalid key file was found: handle it to show warning message
310	else if (!Config.Registered() && *Config.GetInvalidKeyFilename())
311		HandleIncomingKeyfile(Config.GetInvalidKeyFilename());
312	// Clear incoming key info
313	Application.IncomingKeyfile.Clear();
314	// Update registration status
315	Config.Security.WasRegistered = Config.Registered();
316
317	// Incoming update
318	if (Application.IncomingUpdate)
319		{
320		C4UpdateDlg::ApplyUpdate(Application.IncomingUpdate.getData(), false, GetScreen());
321		Application.IncomingUpdate.Clear();
322		}
323	// Manual update by command line or url
324	if (Application.CheckForUpdates)
325		{
326		C4UpdateDlg::CheckForUpdates(GetScreen(), false);
327		Application.CheckForUpdates = false;
328		}
329	// Automatic update
330	else
331		{
332		if (Config.Network.AutomaticUpdate)
333			C4UpdateDlg::CheckForUpdates(GetScreen(), true);
334		}
335
336	// first start evaluation
337	if (Config.General.FirstStart)
338		{
339		Config.General.FirstStart = false;
340		}
341	// first thing that's needed is a new player, if there's none - independent of first start
342	bool fHasPlayer = false;
343	StdStrBuf sSearchPath(Config.General.UserDataPath);
344	const char *szFn;
345//	sSearchPath.Format("%s%s", (const char *) Config.General.ExePath, (const char *) Config.General.PlayerPath);
346	for (DirectoryIterator i(sSearchPath.getData()); szFn=*i; i++)
347		{
348		szFn = Config.AtRelativePath(szFn);
349		if (*GetFilename(szFn) == '.') continue; // ignore ".", ".." and private files (".*")
350		if (!WildcardMatch(C4CFN_PlayerFiles, GetFilename(szFn))) continue;
351		fHasPlayer = true;
352		break;
353		}
354	if (!fHasPlayer)
355		{
356		// no player created yet: Create one
357		C4GUI::Dialog *pDlg;
358		GetScreen()->ShowModalDlg(pDlg=new C4StartupPlrPropertiesDlg(NULL, NULL), true);
359		}
360	// make sure participants are updated after switching back from player selection
361	UpdateParticipants();
362
363	// First show
364	if (fFirstShown)
365		{
366		// Activate the application (trying to prevent flickering half-focus in win32...)
367		Application.Activate();
368		// Set the focus to the start button (we might still not have the focus after the update-check sometimes... :/)
369		SetFocus(pStartButton, false);
370		}
371	fFirstShown = false;
372	}
373
374bool C4StartupMainDlg::SwitchToEditor()
375{
376
377#ifdef _WIN32
378	// No editor executable available
379	if (!FileExists(Config.AtExePath(C4CFN_Editor))) return false;
380	// Flag editor launch
381	Application.launchEditor = true;
382	// Quit
383	C4Startup::Get()->Exit();
384#endif
385
386	return true;
387}
388
389void C4StartupMainDlg::HandleIncomingKeyfile(const char *strIncomingKey)
390{
391	static bool fWarnedInvalidKeyfile = false;
392
393	// Copy filename parameter to keep it valid
394	StdCopyStrBuf strKeyFilename; strKeyFilename = strIncomingKey;
395
396	// Key file doesn't even exist? Do nothing.
397	if (!FileExists(strKeyFilename.getData())) return;
398
399	// Try loading registration from the incoming keyfile to verify it
400	Config.ClearRegistrationError();
401	if (!Config.LoadRegistration(strKeyFilename.getData()))
402	{
403		// Invalid keyfile: show message (but only once)
404		if (!fWarnedInvalidKeyfile)
405		{
406			StdStrBuf strMessage; strMessage.Format(LoadResStr("IDS_MSG_INVALIDKEY"), Config.GetRegistrationError());
407			GetScreen()->ShowMessageModal(strMessage.getData(), LoadResStr("IDS_DLG_REGISTRATION"),	C4GUI::MessageDialog::btnOK, C4GUI::Ico_Error);
408		}
409		fWarnedInvalidKeyfile = true;
410		// Try to reload any existing registration
411		Config.LoadRegistration();
412		// Bail out
413		return;
414	}
415
416	// See where the key is coming from
417	char strIncomingPath[_MAX_PATH + 1];
418	GetParentPath(strKeyFilename.getData(), strIncomingPath);
419	AppendBackslash(strIncomingPath);
420
421	// The key is already in the key path: that's how we like it
422	if (SEqualNoCase(strIncomingPath, Config.GetKeyPath()))
423		{
424		// Just say thank you
425		GetScreen()->ShowMessageModal(LoadResStr("IDS_CTL_REGISTERED"), LoadResStr("IDS_DLG_REGISTRATION"),	C4GUI::MessageDialog::btnOK, C4GUI::Ico_Notify);
426		return;
427		}
428
429	// The key is currently in the work dir (ExePath)
430	if (SEqualNoCase(strIncomingPath, Config.General.ExePath))
431		{
432		// Ask whether to move it to the key path (preferred)
433		StdStrBuf strMessage; strMessage.Format("%s||%s", LoadResStr("IDS_CTL_REGISTERED"), LoadResStr("IDS_MSG_MOVEKEY"));
434		if (GetScreen()->ShowMessageModal(strMessage.getData(), LoadResStr("IDS_DLG_REGISTRATION"),	C4GUI::MessageDialog::btnYesNo, C4GUI::Ico_Confirm))
435			{
436			// Create key path if it doesn't already exist
437			CreatePath(Config.GetKeyPath());
438			// Move key into key path
439			StdStrBuf strTarget; strTarget.Format("%s%s", Config.GetKeyPath(), GetFilename(strKeyFilename.getData()));
440			if (!MoveItem(strKeyFilename.getData(), strTarget.getData()))
441				GetScreen()->ShowMessageModal(LoadResStr("IDS_FAIL_MOVE"), LoadResStr("IDS_DLG_REGISTRATION"),	C4GUI::MessageDialog::btnOK, C4GUI::Ico_Error);
442			// Update registration
443			Config.LoadRegistration();
444			}
445		return;
446		}
447
448	// The key is coming from the outside
449	else
450		{
451		// Say thank you
452		GetScreen()->ShowMessageModal(LoadResStr("IDS_CTL_REGISTERED"), LoadResStr("IDS_DLG_REGISTRATION"),	C4GUI::MessageDialog::btnOK, C4GUI::Ico_Notify);
453		// Create key path if it doesn't already exist
454		CreatePath(Config.GetKeyPath());
455		// Now try to copy it into the key path (preferred)
456		StdStrBuf strTarget; strTarget.Format("%s%s", Config.GetKeyPath(), GetFilename(strKeyFilename.getData()));
457		if (!CopyItem(strKeyFilename.getData(), strTarget.getData()))
458			{
459			// Failed for some reason, try copy it into the work dir instead (emergency backup)
460			strTarget.Format("%s%s", Config.General.ExePath, GetFilename(strKeyFilename.getData()));
461			if (!CopyItem(strKeyFilename.getData(), strTarget.getData()))
462				GetScreen()->ShowMessageModal(LoadResStr("IDS_FAIL_COPY"), LoadResStr("IDS_DLG_REGISTRATION"),	C4GUI::MessageDialog::btnOK, C4GUI::Ico_Error);
463			}
464		// Update registration
465		Config.LoadRegistration();
466		return;
467		}
468
469}