1 /*
2    Copyright (C) 2004 by James Gregory
3    Part of the GalaxyHack project
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License.
7    This program is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY.
9 
10    See the COPYING file for more details.
11 */
12 
13 #include "ForceSelect.h"
14 
15 #include "Globals.h"
16 #include "RTSInlines.h"
17 #include "PreBattle.h"
18 
19 #include <boost/filesystem/operations.hpp>
20 #include <boost/filesystem/exception.hpp>
21 
22 namespace ForceSelect {
23 
LoadSideDW()24 LoadSideDW::LoadSideDW():
25 LargeBlankDW("Edit a fleet or create a new one. Right click to copy or delete.") {}
26 
~LoadSideDW()27 LoadSideDW::~LoadSideDW() {
28 	if (!sides.size())
29 		gsTo = GST_MainMenu;
30 }
31 
LoadSideSM(int iParentID)32 LoadSideSM::LoadSideSM(int iParentID):
33 FileListMenu(iParentID) {
34 	ExpensiveUpdate();
35 }
36 
ExpensiveUpdate()37 void LoadSideSM::ExpensiveUpdate() {
38 	ClearItems();
39 
40 	MenuItem tempItem;
41 	tempItem.desc = "New";
42 	tempItem.choice = FS_NewSide;
43 	AddItem(tempItem);
44 
45 	AddBlankItem();
46     AddFleets(FS_LoadSide);
47 
48 	InitBorder();
49 }
50 
SwitchOnChoice(Uint16 x,Uint16 y)51 bool LoadSideSM::SwitchOnChoice(Uint16 x, Uint16 y) {
52 	if (currentSelection.choiceType == MCT_LeftCursor) {
53 		switch (currentSelection.choice) {
54 		case FS_NewSide:
55 			myWindows.push_back(GenWindow(0, 0, FS_NewSideName, 0, 0, 0));
56 			break;
57 
58 		case FS_LoadSide:
59 			ForceSelect::LoadSide(currentSelection.desc, false);
60 			closed = true;
61 			break;
62 		}
63 	} else if (currentSelection.choiceType == MCT_RightCursor) {
64 		switch (currentSelection.choice) {
65 		case FS_NewSide:
66 			break;
67 
68 		case FS_LoadSide:
69 			myWindows.push_back(GenWindow(x, y, FS_LoadSidePU, currentSelection.desc, myID, 0));
70 			break;
71 		}
72 	}
73 
74 	return false;
75 }
76 
LoadSidePU(int ix,int iy,const string & iSideName,int iParentID)77 LoadSidePU::LoadSidePU(int ix, int iy, const string& iSideName, int iParentID):
78 PopupMenu(ix, iy, iParentID, 0), sideName(iSideName) {
79 	MenuItem tempItem;
80 
81 	tempItem.desc = "Copy fleet: " + sideName;
82 	tempItem.choice = FS_CopyFleet;
83 	AddItem(tempItem);
84 
85 	tempItem.desc = "Delete fleet: " + sideName;
86 	tempItem.choice = FS_DeleteFleet;
87 	AddItem(tempItem);
88 
89 	InitRects();
90 }
91 
SwitchOnChoice(Uint16 x,Uint16 y)92 bool LoadSidePU::SwitchOnChoice(Uint16 x, Uint16 y) {
93 	if (currentSelection.choiceType == MCT_LeftCursor) {
94 		switch(currentSelection.choice) {
95 		case FS_CopyFleet:
96 			myWindows.push_back(GenWindow(0, 0, FS_CopyFleet, sideName, parentID, 0));
97 			closed = true;
98 			break;
99 
100 		case FS_DeleteFleet:
101 			myWindows.push_back(GenWindow(0, 0, FS_DeleteFleet, sideName, parentID, 0));
102 			closed = true;
103 			break;
104 		}
105 	}
106 
107 	return false;
108 }
109 
NewSideName()110 NewSideName::NewSideName():
111 StringInputBox(maxNameLength, none_constant, 0) {
112 	title = "What do you wish to call your new side?";
113 
114 	rect.w = 400;
115 	rect.h = 100;
116 
117 	CentreWindow();
118 
119 	InitRects();
120 }
121 
Keyboard(SDL_keysym & keysym)122 bool NewSideName::Keyboard(SDL_keysym& keysym) {
123 	bool ret = StringInputBox::Keyboard(keysym);
124 
125 	if (userHitEnter) {
126 		if (CheckNameValid(theInput, true)) {
127 			MessageWindows(WC_YouClose, 0, 0, all_constant, myID);
128 			ForceSelect::LoadSide(theInput, true);
129 		}
130 	}
131 
132 	return ret;
133 }
134 
ChangeCommanderName()135 ChangeCommanderName::ChangeCommanderName():
136 StringInputBox(maxNameLength, none_constant, 0) {
137 	title = "What is your name, commander?";
138 
139 	rect.w = 400;
140 	rect.h = 100;
141 
142 	CentreWindow();
143 
144 	InitRects();
145 }
146 
Keyboard(SDL_keysym & keysym)147 bool ChangeCommanderName::Keyboard(SDL_keysym& keysym) {
148 	bool ret = StringInputBox::Keyboard(keysym);
149 
150 	if (userHitEnter) {
151 		if (CheckNameValid(theInput, true)) {
152 			sides[0].commander = theInput;
153 			globalSettings.commander = theInput;
154 		}
155 	}
156 
157 	return ret;
158 }
159 
BasePU(int ix,int iy)160 BasePU::BasePU(int ix, int iy):
161 PopupMenu(ix, iy, none_constant, 0) {
162 	MenuItem tempItem;
163 
164 	tempItem.desc = "Edit group";
165 	tempItem.choice = WC_SidePU;
166 	AddItem(tempItem);
167 
168 	tempItem.desc = "Add new group(s)";
169 	tempItem.choice = FS_AddGroups;
170 	AddItem(tempItem);
171 
172 	tempItem.desc = "Delete group";
173 	tempItem.choice = FS_DeleteGroup;
174 	AddItem(tempItem);
175 
176 	tempItem.desc = "Starting positions";
177 	tempItem.choice = FS_StartingPositions;
178 	AddItem(tempItem);
179 
180 	AddBlankItem();
181 
182 	tempItem.desc = "Options";
183 	tempItem.choice = Opt_StandardOptions;
184 	AddItem(tempItem);
185 
186 	tempItem.desc = "Save and exit";
187 	tempItem.choice = WC_Quit;
188 	AddItem(tempItem);
189 
190 	tempItem.desc = "Exit without saving";
191 	tempItem.choice = FS_ExitNoSave;
192 	AddItem(tempItem);
193 
194 	InitRects();
195 }
196 
SwitchOnChoice(Uint16 x,Uint16 y)197 bool BasePU::SwitchOnChoice(Uint16 x, Uint16 y) {
198 	if (currentSelection.choiceType == MCT_LeftCursor) {
199 		switch(currentSelection.choice) {
200 		case WC_SidePU:
201 			myWindows.push_back(GenWindow(WC_SidePU, 0, 0, FS_EditGroup));
202 			closed = true;
203 			break;
204 
205 		case FS_AddGroups:
206 			if (sides[0].groups.size() < maxGroups) {
207 				myWindows.push_back(GenWindow(0, 0, WC_LargeBlankDW, "What sort of unit will this group consist of?\nRight click to copy or delete.", 0, 0));
208 				myWindows.push_back(GenWindow(100, 100 + (lineGap << 1), FS_AddGroupMenu, windowIDs, 0, 0));
209 			} else
210 				CreateInfoString("\n\n  You cannot have more than 60 groups on a side");
211 			closed = true;
212 			break;
213 
214 		case FS_DeleteGroup:
215 			myWindows.push_back(GenWindow(WC_SidePU, 0, 0, FS_DeleteGroup));
216 			closed = true;
217 			break;
218 
219 		case FS_StartingPositions:
220 			PreBattle::pbState = PBS_Position;
221 			gsTo = GST_PreBattle;
222 			break;
223 
224 		case Opt_StandardOptions:
225 			myWindows.push_back(GenWindow(rect.x, rect.y, Opt_StandardOptions, 0, 0, 0));
226 			closed = true;
227 			break;
228 
229 		case WC_Quit:
230 			TrySaveAndExit();
231 			break;
232 
233 		case FS_ExitNoSave:
234 			myWindows.push_back(GenWindow(0, 0, FS_ExitNoSaveQ, 0, 0, 0));
235 			closed = true;
236 			break;
237 		}
238 	}
239 
240 	return false;
241 }
242 
SideOptions(int ix,int iy,int flags)243 SideOptions::SideOptions(int ix, int iy, int flags):
244 DragWindow(0, 0, none_constant, flags) {
245 	rect.w = 200;
246 	rect.h = 150;
247 
248 	rect.x = globalSettings.screenWidth - rect.w - 10;
249 	rect.y = 10;
250 
251 	InitBorder();
252 }
253 
MouseD(Uint8 button,Uint16 x,Uint16 y)254 bool SideOptions::MouseD(Uint8 button, Uint16 x, Uint16 y) {
255 	bool ret = GenWindow_Base::MouseD(button, x, y);
256 
257 	if (ret == true && button == SDL_BUTTON_RIGHT)
258 		myWindows.push_back(GenWindow(x, y, FS_SideOptionsPU, 0, 0, 0));
259 
260 	return ret;
261 }
262 
DrawSelf()263 void SideOptions::DrawSelf() {
264 	DragWindow::DrawSelf();
265 
266 	int x = rect.x + smallBorderSize;
267 	int y = rect.y + smallBorderSize;
268 
269 	char output[60];
270 
271 	boldFonts.BlitString(x, y, 0, sides[0].name);
272 	y += lineGap << 1;
273 
274 	string outputStr = "Commander: " + sides[0].commander;
275 	normalFonts.BlitString(x, y, 0, outputStr);
276 	y += lineGap << 1;
277 
278 	sprintf(output, "Points value: %d", sides[0].GetPointsValue());
279 	normalFonts.BlitString(x, y, 0, output);
280 }
281 
SideOptionsPU(int ix,int iy)282 SideOptionsPU::SideOptionsPU(int ix, int iy):
283 PopupMenu(ix, iy, none_constant, 0) {
284 	MenuItem tempItem;
285 
286 	tempItem.desc = "Commander name";
287 	tempItem.choice = FS_Commander;
288 	AddItem(tempItem);
289 
290 	tempItem.desc = "Change saved groups";
291 	tempItem.choice = FS_ChooseGSaveGroup;
292 	AddItem(tempItem);
293 
294 	InitRects();
295 }
296 
SwitchOnChoice(Uint16 x,Uint16 y)297 bool SideOptionsPU::SwitchOnChoice(Uint16 x, Uint16 y) {
298 	if (currentSelection.choiceType == MCT_LeftCursor) {
299 		switch(currentSelection.choice) {
300 		case FS_Commander:
301 			myWindows.push_back(GenWindow(0, 0, FS_Commander, 0, 0, 0));
302 			closed = true;
303 			break;
304 
305 		case FS_ChooseGSaveGroup:
306 			myWindows.push_back(GenWindow(0, 0, FS_WhichSaveGroup, 0, 1, 0));
307 			closed = true;
308 			break;
309 		}
310 	}
311 
312 	return false;
313 }
314 
EditGroup(int ix,int iy,int iMyGroup,int flags)315 EditGroup::EditGroup(int ix, int iy, int iMyGroup, int flags):
316 DragWindow(ix, iy, none_constant, flags), myGroup(iMyGroup) {
317 	rect.w = 350;
318 	rect.h = 170;
319 
320 	InitRects();
321 }
322 
MouseD(Uint8 button,Uint16 x,Uint16 y)323 bool EditGroup::MouseD(Uint8 button, Uint16 x, Uint16 y) {
324 	bool ret = DragWindow::MouseD(button, x, y);
325 
326 	if (ret == true && button == SDL_BUTTON_RIGHT)
327 		myWindows.push_back(GenWindow(x, y, FS_EditGroupPU, myGroup, 0, 0));
328 
329 	return ret;
330 }
331 
DrawSelf()332 void EditGroup::DrawSelf() {
333 	DragWindow::DrawSelf();
334 
335 	int x = rect.x + smallBorderSize;
336 	int y = rect.y + smallBorderSize;
337 
338 	char output[50];
339 	sprintf(output, "Group %d:", myGroup+1);
340 	boldFonts.BlitString(x, y, 0, output);
341 
342 	y += lineGap;
343 
344 	string outputStr = "Unit name: " + sides[0].groups[myGroup].GetUnitName();
345 	normalFonts.BlitString(x, y, 0, outputStr);
346 
347 	y += lineGap;
348 
349 	outputStr = "Unit type: " + GetFullTypeName(0, myGroup);
350 	normalFonts.BlitString(x, y, 0, outputStr);
351 
352 	y += lineGap;
353 
354 	sprintf(output, "Number: %d", sides[0].groups[myGroup].GetUnitsLeft());
355 	normalFonts.BlitString(x, y, 0, output);
356 
357 	y += lineGap;
358 
359 	sprintf(output, "Points value: %d", sides[0].groups[myGroup].GetPointsValue());
360 	normalFonts.BlitString(x, y, 0, output);
361 	y += lineGap << 1;
362 
363 	int groupNumber = sides[0].groups[myGroup].GetParentCaSh();
364 	if (groupNumber != -1)
365 		sprintf(output, "Parent capital ship: Group %d", groupNumber + 1);
366 	else
367 		sprintf(output, "Parent capital ship: None");
368 	normalFonts.BlitString(x, y, 0, output);
369 
370 	y += lineGap;
371 
372 	sprintf(output, "AI script: %s", sides[0].groups[myGroup].GetAIFilename().c_str());
373 	normalFonts.BlitString(x, y, 0, output);
374 
375 	y += lineGap;
376 
377    if (sides[0].groups[myGroup].GetType() == UT_CaShUnit) {
378 		sprintf(output, "Capacity: %d / %d", sides[0].groups[myGroup].GetHowFull(), sides[0].groups[myGroup].GetCapacity());
379 		normalFonts.BlitString(x, y, 0, output);
380 	}
381 }
382 
WinMessage(WindowChoice theMessage,int paremOne,int paremTwo,int targetID,int sourceID)383 void EditGroup::WinMessage(WindowChoice theMessage, int paremOne, int paremTwo, int targetID, int sourceID) {
384 	GenWindow_Base::WinMessage(theMessage, paremOne, paremTwo, targetID, sourceID);
385 
386 	if (targetID == all_constant || targetID == myID) {
387 		switch (theMessage) {
388 			//our group has been deleted
389 		case FS_GroupNumChange:
390 			GroupNumChange(paremOne, paremTwo, myGroup);
391 			break;
392 		}
393 	}
394 }
395 
AddGroupMenu(int iParentID)396 AddGroupMenu::AddGroupMenu(int iParentID):
397 FileListMenu(iParentID) {
398 	ExpensiveUpdate();
399 }
400 
ExpensiveUpdate()401 void AddGroupMenu::ExpensiveUpdate() {
402 	ClearItems();
403 
404 	MenuItem tempItem;
405 
406 	tempItem.desc = "New capital ship";
407 	tempItem.choice = FS_NewCaSh;
408 	AddItem(tempItem);
409 
410 	tempItem.desc = "New frigate";
411 	tempItem.choice = FS_NewFr;
412 	AddItem(tempItem);
413 
414 	tempItem.desc = "New small ship";
415 	tempItem.choice = FS_NewSmSh;
416 	AddItem(tempItem);
417 
418 	AddBlankItem();
419 
420 	AddFleetFiles(0, ".dat", FS_AddGroups);
421 
422 	InitBorder();
423 }
424 
425 
SwitchOnChoice(Uint16 x,Uint16 y)426 bool AddGroupMenu::SwitchOnChoice(Uint16 x, Uint16 y) {
427 	if (currentSelection.choiceType == MCT_LeftCursor) {
428 		switch(currentSelection.choice) {
429 		case FS_NewCaSh:
430 			myWindows.push_back(GenWindow(FS_NewUnitName, UT_CaShUnit, myID));
431 			break;
432 
433 		case FS_NewFr:
434 			myWindows.push_back(GenWindow(FS_NewUnitName, UT_FrUnit, myID));
435 			break;
436 
437 		case FS_NewSmSh:
438 			myWindows.push_back(GenWindow(FS_NewUnitName, UT_SmShUnit, myID));
439 			break;
440 
441 		case FS_AddGroups:
442 			UnitType iType = RTSUnit::WhatUTIsThis(0, currentSelection.desc);
443 			CreateNewGroupWins(currentSelection.desc, iType, 0);
444 			closed = true;
445 			break;
446 		}
447 	}
448 	else if (currentSelection.choiceType == MCT_RightCursor) {
449 		switch(currentSelection.choice) {
450 		case FS_AddGroups:
451 			myWindows.push_back(GenWindow(x, y, FS_AddGroupPU, currentSelection.desc, myID, 0));
452 			break;
453 		}
454 	}
455 
456 	return false;
457 }
458 
NewGroupParentPU(const string & iName,UnitType iType,int iNumber)459 NewGroupParentPU::NewGroupParentPU(const string& iName, UnitType iType, int iNumber):
460 SidePU(0, 0, FS_ChangeParentCap), name(iName), myType(iType), number(iNumber) {}
461 
SwitchOnChoice(Uint16 x,Uint16 y)462 bool NewGroupParentPU::SwitchOnChoice(Uint16 x, Uint16 y) {
463 	if (currentSelection.choiceType == MCT_LeftCursor) {
464 		switch (currentSelection.choice) {
465 		case FS_ChangeParentCap:
466 			if (sides[mySide].groups[currentSelection.parem].GetType() == UT_CaShUnit) {
467 				if (sides[mySide].groups[currentSelection.parem].GetHowFull() + number <= sides[0].groups[currentSelection.parem].GetCapacity())
468 					AddGroups(name, myType, number, CST_None, currentSelection.parem);
469 
470 				else {
471 					char output[80];
472 					sprintf(output, "Cannot fit another %d groups in capital ship %d", number, currentSelection.parem + 1);
473 					CreateInfoString(output);
474 				}
475 			}
476 			break;
477 		}
478 	}
479 
480 	return false;
481 }
482 
AddGroupPU(int ix,int iy,const string & iUnitName,int iParentID)483 AddGroupPU::AddGroupPU(int ix, int iy, const string& iUnitName, int iParentID):
484 PopupMenu(ix, iy, iParentID, 0), unitName(iUnitName) {
485 	MenuItem tempItem;
486 
487 	tempItem.desc = "Copy unit: " + unitName;
488 	tempItem.choice = FS_CopyUnit;
489 	AddItem(tempItem);
490 
491 	tempItem.desc = "Delete unit: " + unitName;
492 	tempItem.choice = FS_DeleteUnit;
493 	AddItem(tempItem);
494 
495 	InitRects();
496 }
497 
SwitchOnChoice(Uint16 x,Uint16 y)498 bool AddGroupPU::SwitchOnChoice(Uint16 x, Uint16 y) {
499 	if (currentSelection.choiceType == MCT_LeftCursor) {
500 		switch(currentSelection.choice) {
501 		case FS_CopyUnit:
502 			myWindows.push_back(GenWindow(WC_CopyBox, unitName, GetFleetDir(0), parentID));
503 			closed = true;
504 			break;
505 
506 		case FS_DeleteUnit:
507 			myWindows.push_back(GenWindow(WC_DeleteBox, unitName, GetFleetDir(0), parentID));
508 			closed = true;
509 			break;
510 		}
511 	}
512 
513 	return false;
514 }
515 
NewUnitName(UnitType iUnitType,int iParentID)516 NewUnitName::NewUnitName(UnitType iUnitType, int iParentID):
517 StringInputBox(maxNameLength, iParentID, 0), unitType(iUnitType) {
518 	title = "What do you wish to call the new unit type?";
519 
520 	rect.w = 400;
521 	rect.h = 100;
522 
523 	CentreWindow();
524 
525 	InitRects();
526 }
527 
Keyboard(SDL_keysym & keysym)528 bool NewUnitName::Keyboard(SDL_keysym& keysym) {
529 	bool ret = StringInputBox::Keyboard(keysym);
530 
531 	if (userHitEnter) {
532 		if (CheckNameValid(theInput, true)) {
533 			if (theInput == sides[0].name)
534 				CreateInfoString("A unit cannot have the same name as your side");
535 			else {
536 				CreateNewGroupWins(theInput, unitType, 1);
537 				MessageWindows(WC_YouClose, 0, 0, parentID, myID);
538 			}
539 		}
540 	}
541 
542 	return ret;
543 }
544 
EditGroupPU(int ix,int iy,int iMyGroup)545 EditGroupPU::EditGroupPU(int ix, int iy, int iMyGroup):
546 PopupMenu(ix, iy, none_constant, 0), myGroup(iMyGroup) {
547 	MenuItem tempItem;
548 
549 	tempItem.desc = "Edit unit";
550 	tempItem.choice = FS_EditUnit;
551 	AddItem(tempItem);
552 
553 	tempItem.desc = "AI script";
554 	tempItem.choice = FS_ChangeAIScript;
555 	AddItem(tempItem);
556 
557 	tempItem.desc = "Change saved groups";
558 	tempItem.choice = FS_ChooseSaveGroup;
559 	AddItem(tempItem);
560 
561 	InitRects();
562 }
563 
SwitchOnChoice(Uint16 x,Uint16 y)564 bool EditGroupPU::SwitchOnChoice(Uint16 x, Uint16 y) {
565 	if (currentSelection.choiceType == MCT_LeftCursor) {
566 		switch (currentSelection.choice) {
567 		case FS_EditUnit: {
568 				string unitName = sides[0].groups[myGroup].GetUnitName();
569 				myWindows.push_back(GenWindow(rect.x, rect.y, FS_EditUnit, myGroup, 0, 0));
570 				closed = true;
571 			}
572 			break;
573 
574 		case FS_ChangeAIScript:
575 			myWindows.push_back(GenWindow(0, 0, WC_LargeBlankDW, "Choose an AI script", 0, 0));
576 			myWindows.push_back(GenWindow(100, 100 + (lineGap << 1), FS_AIScriptMenu, myGroup, windowIDs, 0));
577 			closed = true;
578 			break;
579 
580 		case FS_ChooseSaveGroup:
581 			myWindows.push_back(GenWindow(0, 0, FS_WhichSaveGroup, myGroup, 0, 0));
582 			closed = true;
583 			break;
584 		}
585 	}
586 
587 	return false;
588 }
589 
SetAIScriptMenu(int iMyGroup,int iParentID)590 SetAIScriptMenu::SetAIScriptMenu(int iMyGroup, int iParentID):
591 FileListMenu(iParentID), myGroup(iMyGroup) {
592 	MenuItem tempItem;
593 
594 	tempItem.desc = "None";
595 	tempItem.choice = FS_ChangeAIScript;
596 	AddItem(tempItem);
597 
598 	AddBlankItem();
599 
600 	AddFleetFiles(0, ".ai", FS_ChangeAIScript);
601 
602 	InitBorder();
603 }
604 
SwitchOnChoice(Uint16 x,Uint16 y)605 bool SetAIScriptMenu::SwitchOnChoice(Uint16 x, Uint16 y) {
606 	if (currentSelection.choiceType == MCT_LeftCursor) {
607 		switch(currentSelection.choice) {
608 		case FS_ChangeAIScript:
609 			if (currentSelection.desc == "None")
610 				currentSelection.desc = "";
611 			if (sides[0].aiScripts.find(currentSelection.desc) == sides[0].aiScripts.end()) {
612 				try {
613 					sides[0].CreateAIScriptVec(currentSelection.desc);
614 					sides[0].MakeFunctionLookupTable(currentSelection.desc);
615 				} catch (runtime_error e) {
616 					//FIXME we should probably delete the half-loaded script
617 					ReportOnMinorError(e.what());
618 					closed = true;
619 					break;
620 				}
621 			}
622 
623 			if (WhichGSharesName(myGroup) != -1)
624 			   myWindows.push_back(GenWindow(0, 0, FS_ChangeAIScriptPU, currentSelection.desc, myGroup, 0));
625 			else
626 			   sides[0].groups[myGroup].ChangeAIScript(currentSelection.desc);
627 			closed = true;
628 			break;
629 		}
630 	}
631 
632 	return false;
633 }
634 
WinMessage(WindowChoice theMessage,int paremOne,int paremTwo,int targetID,int sourceID)635 void SetAIScriptMenu::WinMessage(WindowChoice theMessage, int paremOne, int paremTwo, int targetID, int sourceID) {
636 	GenWindow_Base::WinMessage(theMessage, paremOne, paremTwo, targetID, sourceID);
637 
638 	if (targetID == all_constant || targetID == myID) {
639 		switch (theMessage) {
640 			//our group has been deleted
641 		case FS_GroupNumChange:
642 			GroupNumChange(paremOne, paremTwo, myGroup);
643 			break;
644 		}
645 	}
646 }
647 
SetAIScriptPU(const string & iNewScript,int iMyGroup,int iParentID)648 SetAIScriptPU::SetAIScriptPU(const string& iNewScript, int iMyGroup, int iParentID):
649 Menu_Base(0, 0, iParentID, 0), newScript(iNewScript), myGroup(iMyGroup) {
650 	MenuItem tempItem;
651 
652 	tempItem.desc = "Change AI script for just this group or all groups with this unit type?";
653 	tempItem.choice = WC_Nothing;
654 	AddItem(tempItem);
655 
656 	tempItem.desc = "Just this one";
657 	tempItem.choice = WC_Yes;
658 	AddItem(tempItem);
659 
660 	tempItem.desc = "All";
661 	tempItem.choice = WC_No;
662 	AddItem(tempItem);
663 
664 	InitRects();
665 
666 	CentreWindow();
667 }
668 
SwitchOnChoice(Uint16 x,Uint16 y)669 bool SetAIScriptPU::SwitchOnChoice(Uint16 x, Uint16 y) {
670 	if (currentSelection.choiceType == MCT_LeftCursor) {
671 		switch(currentSelection.choice) {
672 		case WC_Yes:
673 			sides[0].groups[myGroup].ChangeAIScript(newScript);
674 			closed = true;
675 			break;
676 
677 		case WC_No:
678 			ChangeUnitAI(sides[0].groups[myGroup].GetUnitName(), newScript);
679 			closed = true;
680 			break;
681 		}
682 	}
683 
684 	return false;
685 }
686 
WinMessage(WindowChoice theMessage,int paremOne,int paremTwo,int targetID,int sourceID)687 void SetAIScriptPU::WinMessage(WindowChoice theMessage, int paremOne, int paremTwo, int targetID, int sourceID) {
688 	GenWindow_Base::WinMessage(theMessage, paremOne, paremTwo, targetID, sourceID);
689 
690 	if (targetID == all_constant || targetID == myID) {
691 		switch (theMessage) {
692 			//our group has been deleted
693 		case FS_GroupNumChange:
694 			GroupNumChange(paremOne, paremTwo, myGroup);
695 			break;
696 		}
697 	}
698 }
699 
EditUnit(int ix,int iy,int iMyGroup)700 EditUnit::EditUnit(int ix, int iy, int iMyGroup):
701 DragWindow(ix, iy, none_constant, 0), myGroup(iMyGroup), myType(sides[0].groups[iMyGroup].GetType()) {
702 	switch (myType) {
703 	case UT_SmShUnit:
704 	case UT_FrUnit:
705 		rect.w = 400;
706 		rect.h = FrHeight + 400;
707 		break;
708 
709 	case UT_CaShUnit:
710 		rect.w = HCSWidth + (bigBorderSize << 1);
711 		rect.h = HCSHeight + 400;
712 		break;
713 	}
714 
715 	CentreWindow();
716 
717 	InitRects();
718 }
719 
MouseD(Uint8 button,Uint16 x,Uint16 y)720 bool EditUnit::MouseD(Uint8 button, Uint16 x, Uint16 y) {
721 	bool ret = DragWindow::MouseD(button, x, y);
722 
723 	if (ret == true && button == SDL_BUTTON_RIGHT)
724 		myWindows.push_back(GenWindow(x, y, FS_EditUnitPU, myGroup, 0, 0));
725 
726 	return ret;
727 }
728 
DrawSelf()729 void EditUnit::DrawSelf() {
730 	DragWindow::DrawSelf();
731 
732 	int x = rect.x + bigBorderSize;
733 	int y = rect.y + smallBorderSize;
734 
735 	char output[50];
736 
737 	boldFonts.BlitString(x, y, 0, sides[0].groups[myGroup].GetUnitName());
738 
739 	y += lineGap;
740 
741 	int picAllowance;
742 
743 	switch(myType) {
744 	case UT_CaShUnit:
745 		picAllowance = HCSHeight;
746 		break;
747 
748 	case UT_FrUnit:
749 	case UT_SmShUnit:
750 		picAllowance = FrHeight;
751 		break;
752 	}
753 
754 	sides[0].groups[myGroup].DrawUnitPic(x + bigBorderSize, y);
755 
756 	y += picAllowance + lineGap;
757 
758 	string outputStr = "Unit type: " + GetFullTypeName(0, myGroup);
759 
760 	normalFonts.BlitString(x, y, 0, outputStr);
761 
762 	y += lineGap << 1;
763 
764 	outputStr = sides[0].groups[myGroup].GetShieldName();
765 	outputStr = "Shield: " + outputStr;
766 	normalFonts.BlitString(x, y, 0, outputStr);
767 
768 	y += lineGap << 1;
769 
770 	outputStr = sides[0].groups[myGroup].GetArmourName();
771 	outputStr = "Armour: " + outputStr;
772 	normalFonts.BlitString(x, y, 0, outputStr);
773 
774 	y += lineGap << 1;
775 
776 	outputStr = sides[0].groups[myGroup].GetEngineName();
777 	outputStr = "Engine: " + outputStr;
778 	normalFonts.BlitString(x, y, 0, outputStr);
779 
780 	y += lineGap << 1;
781 
782 	outputStr = weaponLookup[sides[0].groups[myGroup].GetSmallType()].name;
783 	outputStr = "Small weapons: " + outputStr;
784 
785 	if (myType != UT_SmShUnit) {
786 		sprintf(output, " * %d", sides[0].groups[myGroup].GetSmallNumber());
787 		outputStr+= output;
788 	}
789 
790 	normalFonts.BlitString(x, y, 0, outputStr);
791 
792 	y += lineGap << 1;
793 
794 	outputStr = weaponLookup[sides[0].groups[myGroup].GetBigType()].name;
795 	outputStr = "Big weapons: " + outputStr;
796 	if (weaponLookup[sides[0].groups[myGroup].GetBigType()].category == WCAT_Torpedo)
797 		outputStr += " (25% speed penalty)";
798 	normalFonts.BlitString(x, y, 0, outputStr);
799 	y += lineGap << 1;
800 
801 	if (myType == UT_CaShUnit) {
802 		sprintf(output, "Capacity: %d", sides[0].groups[myGroup].GetCapacity());
803 		normalFonts.BlitString(x, y, 0, output);
804 		y += lineGap << 1;
805 	}
806 
807 	if (sides[0].groups[myGroup].GetUnitMaxPoints() != infinite_constant)
808 		sprintf(output, "Points value: %d / %d", sides[0].groups[myGroup].GetUnitPointsValue(), sides[0].groups[myGroup].GetUnitMaxPoints());
809 	else
810 		sprintf(output, "Points value: %d / infinite", sides[0].groups[myGroup].GetUnitPointsValue());
811 	normalFonts.BlitString(x, y, 0, output);
812 }
813 
WinMessage(WindowChoice theMessage,int paremOne,int paremTwo,int targetID,int sourceID)814 void EditUnit::WinMessage(WindowChoice theMessage, int paremOne, int paremTwo, int targetID, int sourceID) {
815 	GenWindow_Base::WinMessage(theMessage, paremOne, paremTwo, targetID, sourceID);
816 
817 	if (targetID == all_constant || targetID == myID) {
818 		switch (theMessage) {
819 			//our group has been deleted
820 		case FS_GroupNumChange:
821 			if(!UnitNameSharedQ(myGroup, paremOne, paremTwo))
822 				closed = true;
823 			break;
824 		}
825 	}
826 }
827 
EditUnitPU(int ix,int iy,int iMyGroup)828 EditUnitPU::EditUnitPU(int ix, int iy, int iMyGroup):
829 PopupMenu(ix, iy, none_constant, 0), myGroup(iMyGroup) {
830 	MenuItem tempItem;
831 
832 	tempItem.desc = "Change picture";
833 	tempItem.choice = FS_Picture;
834 	AddItem(tempItem);
835 
836 	tempItem.desc = "Small weapons";
837 	tempItem.choice = FS_SmallWeapons;
838 	AddItem(tempItem);
839 
840 	if (sides[0].groups[myGroup].GetType() != UT_CaShUnit) {
841 		tempItem.desc = "Big weapons";
842 		tempItem.choice = FS_BigWeapons;
843 		AddItem(tempItem);
844 
845 		tempItem.desc = "Engine";
846 
847 		tempItem.choice = FS_Engine;
848 		AddItem(tempItem);
849 
850 		tempItem.desc = "Armour";
851 		tempItem.choice = FS_Armour;
852 		AddItem(tempItem);
853 
854 		tempItem.desc = "Shield";
855 		tempItem.choice = FS_Shield;
856 		AddItem(tempItem);
857 	}
858 	else {
859 		tempItem.desc = "Size";
860 		tempItem.choice = FS_CSType;
861 		AddItem(tempItem);
862 	}
863 
864 	InitRects();
865 }
866 
867 
SwitchOnChoice(Uint16 x,Uint16 y)868 bool EditUnitPU::SwitchOnChoice(Uint16 x, Uint16 y) {
869 	if (currentSelection.choiceType == MCT_LeftCursor) {
870 		switch(currentSelection.choice) {
871 		case FS_Picture:
872 			myWindows.push_back(GenWindow(0, 0, WC_LargeBlankDW, "Choose a picture", 0, 0));
873 			myWindows.push_back(GenWindow(100, 100 + (lineGap << 1), FS_PictureMenu, myGroup, windowIDs, 0));
874 			closed = true;
875 			break;
876 
877 		case FS_SmallWeapons:
878 			myWindows.push_back(GenWindow(200, 200, FS_WeaponsDW, myGroup, 0, 0));
879 			myWindows.push_back(GenWindow(200, 200, FS_SmallWeaponsMenu, myGroup, windowIDs, 0));
880 			closed = true;
881 			break;
882 
883 		case FS_BigWeapons:
884 			myWindows.push_back(GenWindow(200, 200, FS_WeaponsDW, myGroup, 1, 0));
885 			myWindows.push_back(GenWindow(200, 200, FS_BigWeaponsMenu, myGroup, windowIDs, 0));
886 			closed = true;
887 			break;
888 
889 		case FS_Engine:
890 			myWindows.push_back(GenWindow(200, 200, FS_EquipmentDW, myGroup, FS_Engine, 0));
891 			myWindows.push_back(GenWindow(200, 200, FS_EngineMenu, myGroup, windowIDs, 0));
892 			closed = true;
893 			break;
894 
895 		case FS_Armour:
896 			myWindows.push_back(GenWindow(200, 200, FS_EquipmentDW, myGroup, FS_Armour, 0));
897 			myWindows.push_back(GenWindow(200, 200, FS_ArmourMenu, myGroup, windowIDs, 0));
898 			closed = true;
899 			break;
900 
901 		case FS_Shield:
902 			myWindows.push_back(GenWindow(200, 200, FS_EquipmentDW, myGroup, FS_Shield, 0));
903 			myWindows.push_back(GenWindow(200, 200, FS_ShieldMenu, myGroup, windowIDs, 0));
904 			closed = true;
905 			break;
906 
907 		case FS_CSType:
908 			myWindows.push_back(GenWindow(200, 200, FS_CSType, myGroup, 0, 0));
909 			closed = true;
910 			break;
911 		}
912 	}
913 
914 	return false;
915 }
916 
917 ///
918 
SetUnitPicMenu(int iMyGroup,int iParentID)919 SetUnitPicMenu::SetUnitPicMenu(int iMyGroup, int iParentID):
920 FileListMenu(iParentID), myGroup(iMyGroup) {
921 	MenuItem tempItem;
922 
923 	try {
924 		UnitType uType = sides[0].groups[myGroup].GetType();
925 		string dir = MakePicDirString(0, RTSUnit_Base::UTypeToPicDir(uType), false);
926 		if (DoesFileExist(dir))
927 			AddDirectory(dir, ".png", FS_Picture);
928 		dir = MakePicDirString(0, RTSUnit_Base::UTypeToPicDir(uType), true);
929 		AddDirectory(dir, ".png", FS_Picture);
930 	} catch (boost::filesystem::filesystem_error e) {
931 		string errorStr = "\n";
932 		errorStr += e.what();
933 		CreateInfoString(errorStr);
934 	}
935 
936 	InitBorder();
937 }
938 
SwitchOnChoice(Uint16 x,Uint16 y)939 bool SetUnitPicMenu::SwitchOnChoice(Uint16 x, Uint16 y) {
940 	if (currentSelection.choiceType == MCT_LeftCursor)
941 		closed = true;
942 
943 	return false;
944 }
945 
MouseM(Uint8 state,Uint16 x,Uint16 y)946 bool SetUnitPicMenu::MouseM(Uint8 state, Uint16 x, Uint16 y) {
947 	bool ret = Menu_Base::MouseM(state, x, y);
948 
949 	if (currentSelection.choiceType == MCT_Highlight) {
950 		switch (currentSelection.choice) {
951 		case FS_Picture:
952 			string newPic = RTSUnit_Base::UTypeToPicDir(sides[0].groups[myGroup].GetType()) + currentSelection.desc + ".png";
953 			string oldPic = sides[0].groups[myGroup].GetRealPictureName();
954 
955 			if (oldPic != newPic)
956 				ChangeUnitPic(sides[0].groups[myGroup].GetUnitName(), newPic);
957 			break;
958 		}
959 	}
960 
961 	return ret;
962 }
963 
WinMessage(WindowChoice theMessage,int paremOne,int paremTwo,int targetID,int sourceID)964 void SetUnitPicMenu::WinMessage(WindowChoice theMessage, int paremOne, int paremTwo, int targetID, int sourceID) {
965 	GenWindow_Base::WinMessage(theMessage, paremOne, paremTwo, targetID, sourceID);
966 
967 	if (targetID == all_constant || targetID == myID) {
968 		switch (theMessage) {
969 			//our group has been deleted
970 		case FS_GroupNumChange:
971 			if(!UnitNameSharedQ(myGroup, paremOne, paremTwo))
972 				closed = true;
973 			break;
974 		}
975 	}
976 }
977 
978 ////
979 
WeapEquipMenu_Base(int ix,int iy,int iMyGroup,int iParentID)980 WeapEquipMenu_Base::WeapEquipMenu_Base(int ix, int iy, int iMyGroup, int iParentID):
981 Menu_Base(ix, iy, iParentID, 0), myGroup(iMyGroup) {}
982 
~WeapEquipMenu_Base()983 WeapEquipMenu_Base::~WeapEquipMenu_Base() {
984 	MessageWindows(WC_YouClose, 0, 0, parentID, myID);
985 }
986 
WinMessage(WindowChoice theMessage,int paremOne,int paremTwo,int targetID,int sourceID)987 void WeapEquipMenu_Base::WinMessage(WindowChoice theMessage, int paremOne, int paremTwo, int targetID, int sourceID) {
988 	GenWindow_Base::WinMessage(theMessage, paremOne, paremTwo, targetID, sourceID);
989 
990 	if (targetID == all_constant || targetID == myID) {
991 		switch (theMessage) {
992 			//our group has been deleted
993 		case FS_GroupNumChange:
994 			if(!UnitNameSharedQ(myGroup, paremOne, paremTwo))
995 				closed = true;
996 			break;
997 		}
998 	}
999 }
1000 
InitEquipMenu(WindowChoice first,WindowChoice last)1001 void WeapEquipMenu_Base::InitEquipMenu(WindowChoice first, WindowChoice last) {
1002 	MenuItem tempItem;
1003 
1004 	for (WindowChoice i = first; i != last + 1; i = static_cast<WindowChoice>(i + 1)) {
1005 		tempItem.desc = WCToETLookup[i];
1006 		tempItem.choice = equipLookup[tempItem.desc].FSEC;
1007 		AddItem(tempItem);
1008 	}
1009 
1010 	InitRects();
1011 }
1012 
SharedSwitchOnChoice(void (* ChangeUnitFunction)(const string &,const string &))1013 bool WeapEquipMenu_Base::SharedSwitchOnChoice(void (*ChangeUnitFunction)(const string&, const string&)) {
1014 	if (currentSelection.choiceType == MCT_LeftCursor) {
1015 		try {
1016 			ChangeUnitFunction(sides[0].groups[myGroup].GetUnitName(), currentSelection.desc);
1017 		} catch (MinorError e) {
1018 			CreateInfoString(e.what());
1019 		}
1020 		closed = true;
1021 	}
1022 
1023 	return false;
1024 }
1025 
MouseM(Uint8 state,Uint16 x,Uint16 y)1026 bool WeapEquipMenu_Base::MouseM(Uint8 state, Uint16 x, Uint16 y) {
1027 	bool ret = Menu_Base::MouseM(state, x, y);
1028 
1029 	if (currentSelection.choiceType == MCT_Highlight)
1030 		MessageWindows(currentSelection.choice, 0, 0, parentID, myID);
1031 
1032 	return ret;
1033 }
1034 
WeaponsDW(int ix,int iy,int iMyGroup,int bBig)1035 WeaponsDW::WeaponsDW(int ix, int iy, int iMyGroup, int bBig):
1036 DragWindow(ix, iy, none_constant, 0) {
1037 	rect.w = 450;
1038 	rect.h = 200;
1039 
1040 	if (bBig)
1041 		weaponChoice = sides[0].groups[iMyGroup].GetBigType();
1042 	else
1043 		weaponChoice = sides[0].groups[iMyGroup].GetSmallType();
1044 
1045 	InitRects();
1046 }
1047 
DrawSelf()1048 void WeaponsDW::DrawSelf() {
1049 	DragWindow::DrawSelf();
1050 
1051 	int x = rect.x + 190;
1052 	int y = rect.y;
1053 
1054 	char output[50];
1055 
1056 	sprintf(output, "Name: %s", (weaponLookup[weaponChoice].name).c_str());
1057 	boldFonts.BlitString(x, y, 0, output);
1058 
1059 	y += lineGap;
1060 
1061 	sprintf(output, "Power: %d", weaponLookup[weaponChoice].power);
1062 	normalFonts.BlitString(x, y, 0, output);
1063 
1064 	y += lineGap;
1065 
1066 	sprintf(output, "Range: %d", weaponLookup[weaponChoice].range);
1067 	normalFonts.BlitString(x, y, 0, output);
1068 
1069 	y += lineGap;
1070 
1071 	sprintf(output, "Base accuracy: %d %%", weaponLookup[weaponChoice].accuracy);
1072 	normalFonts.BlitString(x, y, 0, output);
1073 
1074 	y += lineGap;
1075 
1076 	sprintf(output, "Reload: %d ms", weaponLookup[weaponChoice].reload);
1077 	normalFonts.BlitString(x, y, 0, output);
1078 
1079 	y += lineGap;
1080 
1081 	int startAmmo = weaponLookup[weaponChoice].startAmmo;
1082 
1083 	if (startAmmo != 100)
1084 		sprintf(output, "Ammo: %d", weaponLookup[weaponChoice].startAmmo);
1085 	else
1086 		sprintf(output, "Ammo: Infinite");
1087 
1088 	normalFonts.BlitString(x, y, 0, output);
1089 
1090 	y += lineGap << 1;
1091 
1092 	sprintf(output, "Points: %d", weaponLookup[weaponChoice].points);
1093 	normalFonts.BlitString(x, y, 0, output);
1094 }
1095 
WinMessage(WindowChoice theMessage,int paremOne,int paremTwo,int targetID,int sourceID)1096 void WeaponsDW::WinMessage(WindowChoice theMessage, int paremOne, int paremTwo, int targetID, int sourceID) {
1097 	//group deletion should be handled by child menu
1098 
1099 	GenWindow_Base::WinMessage(theMessage, paremOne, paremTwo, targetID, sourceID);
1100 
1101 	if (targetID == all_constant || targetID == myID) {
1102 		if (theMessage >= FS_WT_None - 1 && theMessage <= FS_WT_Torpedo3)
1103 			weaponChoice = WCToWTLookup[theMessage];
1104 	}
1105 }
1106 
1107 
SmallWeaponsMenu(int ix,int iy,int iMyGroup,int iParentID)1108 SmallWeaponsMenu::SmallWeaponsMenu(int ix, int iy, int iMyGroup, int iParentID):
1109 WeapEquipMenu_Base(ix, iy, iMyGroup, iParentID) {
1110 	MenuItem tempItem;
1111 
1112 	tempItem.desc = weaponLookup[WT_None].name;
1113 	tempItem.choice = FS_WT_None;
1114 	AddItem(tempItem);
1115 
1116 	for (WeaponType i = WT_Twin1; i != WT_Twin3 + 1; i = static_cast<WeaponType>(i + 1)) {
1117 		tempItem.desc = weaponLookup[i].name;
1118 		tempItem.choice = weaponLookup[i].FSWC;
1119 		AddItem(tempItem);
1120 	}
1121 
1122 	if (sides[0].groups[myGroup].GetType() != UT_SmShUnit) {
1123 		AddBlankItem();
1124 
1125 		for (WeaponType i = WT_BSSmall1; i != WT_BSSmall3 + 1; i = static_cast<WeaponType>(i + 1)) {
1126 			tempItem.desc = weaponLookup[i].name;
1127 			tempItem.choice = weaponLookup[i].FSWC;
1128 			AddItem(tempItem);
1129 		}
1130 	}
1131 
1132 	InitRects();
1133 }
1134 
SwitchOnChoice(Uint16 x,Uint16 y)1135 bool SmallWeaponsMenu::SwitchOnChoice(Uint16 x, Uint16 y) {
1136 	return SharedSwitchOnChoice(ChangeUnitSmallWeapons);
1137 }
1138 
BigWeaponsMenu(int ix,int iy,int iMyGroup,int iParentID)1139 BigWeaponsMenu::BigWeaponsMenu(int ix, int iy, int iMyGroup, int iParentID):
1140 WeapEquipMenu_Base(ix, iy, iMyGroup, iParentID) {
1141 	MenuItem tempItem;
1142 
1143 	tempItem.desc = weaponLookup[WT_None].name;
1144 	tempItem.choice = weaponLookup[WT_None].FSWC;
1145 	AddItem(tempItem);
1146 
1147 	WeaponType first;
1148 	WeaponType last;
1149 
1150 	if (sides[0].groups[myGroup].GetType() == UT_SmShUnit) {
1151 		first = WT_Missile1;
1152 		last = WT_Torpedo3;
1153 	} else {
1154 		first = WT_BSLarge1;
1155 		last = WT_BSLarge3;
1156 	}
1157 
1158 	for (WeaponType i = first; i != last + 1; i = static_cast<WeaponType>(i + 1)) {
1159 		tempItem.desc = weaponLookup[i].name;
1160 		tempItem.choice = weaponLookup[i].FSWC;
1161 		AddItem(tempItem);
1162 	}
1163 
1164 	InitRects();
1165 }
1166 
SwitchOnChoice(Uint16 x,Uint16 y)1167 bool BigWeaponsMenu::SwitchOnChoice(Uint16 x, Uint16 y) {
1168 	return SharedSwitchOnChoice(ChangeUnitBigWeapons);
1169 }
1170 
1171 ///
1172 
EquipmentDW(int ix,int iy,int iMyGroup,int equipType)1173 EquipmentDW::EquipmentDW(int ix, int iy, int iMyGroup, int equipType):
1174 DragWindow(ix, iy, none_constant, 0) {
1175 	rect.w = 450;
1176 	rect.h = 200;
1177 
1178 	switch (static_cast<WindowChoice>(equipType)) {
1179 	case FS_Engine:
1180 		equipChoice = sides[0].groups[iMyGroup].GetEngineName();
1181 		break;
1182 	case FS_Armour:
1183 		equipChoice = sides[0].groups[iMyGroup].GetArmourName();
1184 		break;
1185 	case FS_Shield:
1186 		equipChoice = sides[0].groups[iMyGroup].GetShieldName();
1187 		break;
1188 	}
1189 
1190 	InitRects();
1191 }
1192 
DrawSelf()1193 void EquipmentDW::DrawSelf() {
1194 	DragWindow::DrawSelf();
1195 
1196 	int x = rect.x + 190;
1197 	int y = rect.y;
1198 
1199 	char output[50];
1200 
1201 	string outputStr = "Name: " + equipChoice;
1202 	boldFonts.BlitString(x, y, 0, outputStr);
1203 
1204 	y += lineGap;
1205 
1206 	sprintf(output, "Max: %d", equipLookup[equipChoice].max);
1207 	normalFonts.BlitString(x, y, 0, output);
1208 
1209 	y += lineGap;
1210 
1211 	if (equipLookup[equipChoice].category == EQCAT_SSShield || equipLookup[equipChoice].category == EQCAT_FrShield) {
1212 		sprintf(output, "Recharge interval: %d ms", equipLookup[equipChoice].recharge);
1213 		normalFonts.BlitString(x, y, 0, output);
1214 
1215 		y += lineGap;
1216 	}
1217 
1218 	y += lineGap;
1219 
1220 	sprintf(output, "Points: %d", equipLookup[equipChoice].points);
1221 	normalFonts.BlitString(x, y, 0, output);
1222 }
1223 
WinMessage(WindowChoice theMessage,int paremOne,int paremTwo,int targetID,int sourceID)1224 void EquipmentDW::WinMessage(WindowChoice theMessage, int paremOne, int paremTwo, int targetID, int sourceID) {
1225 	//group deletion should be handled by child menu
1226 
1227 	GenWindow_Base::WinMessage(theMessage, paremOne, paremTwo, targetID, sourceID);
1228 
1229 	if (targetID == all_constant || targetID == myID) {
1230 		if (theMessage >= FS_ET_None - 1 && theMessage <= FS_ET_FrShield3)
1231 			equipChoice = WCToETLookup[theMessage];
1232 	}
1233 }
1234 
EngineMenu(int ix,int iy,int iMyGroup,int iParentID)1235 EngineMenu::EngineMenu(int ix, int iy, int iMyGroup, int iParentID):
1236 WeapEquipMenu_Base(ix, iy, iMyGroup, iParentID) {
1237 	if (sides[0].groups[myGroup].GetType() == UT_SmShUnit)
1238 		InitEquipMenu(FS_ET_SSEngine1, FS_ET_SSEngine3);
1239 	else
1240 		InitEquipMenu(FS_ET_FrEngine1, FS_ET_FrEngine3);
1241 }
1242 
SwitchOnChoice(Uint16 x,Uint16 y)1243 bool EngineMenu::SwitchOnChoice(Uint16 x, Uint16 y) {
1244 	return SharedSwitchOnChoice(ChangeUnitEngine);
1245 }
1246 
ArmourMenu(int ix,int iy,int iMyGroup,int iParentID)1247 ArmourMenu::ArmourMenu(int ix, int iy, int iMyGroup, int iParentID):
1248 WeapEquipMenu_Base(ix, iy, iMyGroup, iParentID) {
1249 	if (sides[0].groups[myGroup].GetType() == UT_SmShUnit)
1250 		InitEquipMenu(FS_ET_SSArmour1, FS_ET_SSArmour3);
1251 	else
1252 		InitEquipMenu(FS_ET_FrArmour1, FS_ET_FrArmour3);
1253 }
1254 
SwitchOnChoice(Uint16 x,Uint16 y)1255 bool ArmourMenu::SwitchOnChoice(Uint16 x, Uint16 y) {
1256 	return SharedSwitchOnChoice(ChangeUnitArmour);
1257 }
1258 
ShieldMenu(int ix,int iy,int iMyGroup,int iParentID)1259 ShieldMenu::ShieldMenu(int ix, int iy, int iMyGroup, int iParentID):
1260 WeapEquipMenu_Base(ix, iy, iMyGroup, iParentID) {
1261 	MenuItem tempItem;
1262 
1263 	tempItem.desc = weaponLookup[WT_None].name;
1264 	tempItem.choice = weaponLookup[WT_None].FSWC;
1265 	AddItem(tempItem);
1266 
1267 	if (sides[0].groups[myGroup].GetType() == UT_SmShUnit)
1268 		InitEquipMenu(FS_ET_SSShield1, FS_ET_SSShield3);
1269 	else
1270 		InitEquipMenu(FS_ET_FrShield1, FS_ET_FrShield3);
1271 }
1272 
SwitchOnChoice(Uint16 x,Uint16 y)1273 bool ShieldMenu::SwitchOnChoice(Uint16 x, Uint16 y) {
1274 	return SharedSwitchOnChoice(ChangeUnitShield);
1275 }
1276 
1277 
1278 ////
1279 
CSTypeMenu(int ix,int iy,int iMyGroup)1280 CSTypeMenu::CSTypeMenu(int ix, int iy, int iMyGroup):
1281 Menu_Base(ix, iy, none_constant, 0), myGroup(iMyGroup) {
1282 	MenuItem tempItem;
1283 	tempItem.rect.h = lineGap << 1;
1284 
1285 	tempItem.desc = "New capital ship type?";
1286 	tempItem.choice = WC_Nothing;
1287 	AddItem(tempItem);
1288 
1289 	tempItem.rect.h = lineGap;
1290 
1291 	tempItem.desc = "Heavy";
1292 	tempItem.choice = FS_HCS;
1293 	AddItem(tempItem);
1294 
1295 	tempItem.desc = "Medium";
1296 	tempItem.choice = FS_MCS;
1297 	AddItem(tempItem);
1298 
1299 	tempItem.desc = "Light";
1300 	tempItem.choice = FS_LCS;
1301 	AddItem(tempItem);
1302 
1303 	InitRects();
1304 }
1305 
SwitchOnChoice(Uint16 x,Uint16 y)1306 bool CSTypeMenu::SwitchOnChoice(Uint16 x, Uint16 y) {
1307 	if (currentSelection.choiceType == MCT_LeftCursor) {
1308 		switch (currentSelection.choice) {
1309 		case FS_HCS:
1310 			ChangeUnitCSType(sides[0].groups[myGroup].GetUnitName(), CST_Heavy);
1311 			closed = true;
1312 			break;
1313 		case FS_MCS:
1314 			ChangeUnitCSType(sides[0].groups[myGroup].GetUnitName(), CST_Medium);
1315 			closed = true;
1316 			break;
1317 		case FS_LCS:
1318 			ChangeUnitCSType(sides[0].groups[myGroup].GetUnitName(), CST_Light);
1319 			closed = true;
1320 			break;
1321 		}
1322 
1323 		//check that no capital ships are now overly full
1324 		for (int i = 0; i != sides[0].groups.size(); ++i) {
1325 			if (sides[0].groups[i].GetType() == UT_CaShUnit && sides[0].groups[i].GetHowFull() > sides[0].groups[i].GetCapacity()) {
1326 				char output[80];
1327 				sprintf(output, "Capital ship %d now contains too many small ship groups", i + 1);
1328 				CreateInfoString(output);
1329 			}
1330 		}
1331 	}
1332 
1333 	//don't let other windows get input until we have got a response
1334 	return true;
1335 }
1336 
ForceExitQ(const string & error)1337 ForceExitQ::ForceExitQ(const string& error):
1338 Menu_Base(0, 0, none_constant, 0) {
1339 	MenuItem tempItem;
1340 	tempItem.rect.h = lineGap * 5;
1341 
1342 	tempItem.desc = "Error saving side:\n" + error + "\n\n" +
1343 	                "Force exit without save?" + '\n';
1344 	tempItem.choice = WC_Nothing;
1345 	AddItem(tempItem);
1346 
1347 	tempItem.rect.h = lineGap;
1348 
1349 	tempItem.desc = "Yes";
1350 	tempItem.choice = WC_Yes;
1351 	AddItem(tempItem);
1352 
1353 	tempItem.desc = "No";
1354 	tempItem.choice = WC_No;
1355 	AddItem(tempItem);
1356 
1357 	InitRects();
1358 	CentreWindow();
1359 }
1360 
1361 
SwitchOnChoice(Uint16 x,Uint16 y)1362 bool ForceExitQ::SwitchOnChoice(Uint16 x, Uint16 y) {
1363 	if (currentSelection.choiceType == MCT_LeftCursor) {
1364 		switch(currentSelection.choice) {
1365 		case WC_Yes:
1366 			gsTo = GST_MainMenu;
1367 			break;
1368 
1369 		case WC_No:
1370 			closed = true;
1371 			break;
1372 		}
1373 	}
1374 
1375 	return false;
1376 }
1377 
ExitNoSaveQ()1378 ExitNoSaveQ::ExitNoSaveQ():
1379 Menu_Base(0, 0, none_constant, 0) {
1380 	MenuItem tempItem;
1381 	tempItem.rect.h = lineGap * 2;
1382 
1383 	tempItem.desc = "Exit without saving changes?\n";
1384 	tempItem.choice = WC_Nothing;
1385 	AddItem(tempItem);
1386 
1387 	tempItem.rect.h = lineGap;
1388 
1389 	tempItem.desc = "Yes";
1390 	tempItem.choice = WC_Yes;
1391 	AddItem(tempItem);
1392 
1393 	tempItem.desc = "No";
1394 	tempItem.choice = WC_No;
1395 	AddItem(tempItem);
1396 
1397 	InitRects();
1398 	CentreWindow();
1399 }
1400 
1401 
SwitchOnChoice(Uint16 x,Uint16 y)1402 bool ExitNoSaveQ::SwitchOnChoice(Uint16 x, Uint16 y) {
1403 	if (currentSelection.choiceType == MCT_LeftCursor) {
1404 		switch(currentSelection.choice) {
1405 		case WC_Yes:
1406 			gsTo = GST_MainMenu;
1407 			break;
1408 
1409 		case WC_No:
1410 			closed = true;
1411 			break;
1412 		}
1413 	}
1414 
1415 	return false;
1416 }
1417 
NewGroupChoicesOK(int ix,int iy,const string & iName,UnitType iMyType,int iIDOne,int iIDTwo,int iParentID)1418 NewGroupChoicesOK::NewGroupChoicesOK(int ix, int iy, const string& iName, UnitType iMyType, int iIDOne, int iIDTwo, int iParentID):
1419 Menu_Base(ix, iy, iParentID, 0), name(iName), myType(iMyType), sliderOneID(iIDOne), sliderTwoID(iIDTwo) {
1420 	MenuItem tempItem;
1421 	tempItem.desc = "OK";
1422 	tempItem.choice = WC_Yes;
1423 	AddItem(tempItem);
1424 
1425 	InitRects();
1426 }
1427 
SwitchOnChoice(Uint16 x,Uint16 y)1428 bool NewGroupChoicesOK::SwitchOnChoice(Uint16 x, Uint16 y) {
1429 	if (currentSelection.choiceType == MCT_LeftCursor) {
1430 		switch (currentSelection.choice) {
1431 		case WC_Yes: {
1432 				int number;
1433 
1434 				if (sliderOneID != none_constant) {
1435 					Slider* sliderOne = dynamic_cast<Slider*>(LocateWindow(sliderOneID));
1436 					number = sliderOne->GetSliderVar();
1437 				} else
1438 					number = 1;
1439 
1440 				switch (myType) {
1441 				case UT_CaShUnit: {
1442 						int sliderTwoVar = 0;
1443 
1444 						if (sliderTwoID != none_constant) {
1445 							Slider* sliderTwo = dynamic_cast<Slider*>(LocateWindow(sliderTwoID));
1446 							sliderTwoVar = sliderTwo->GetSliderVar();
1447 						}
1448 
1449 						CapShipType csType = static_cast<CapShipType>(sliderTwoVar);
1450 						AddGroups(name, myType, number, csType, -1);
1451 					}
1452 					break;
1453 				case UT_FrUnit:
1454 					AddGroups(name, myType, number, CST_None, -1);
1455 					break;
1456 				case UT_SmShUnit:
1457 					myWindows.push_back(GenWindow(0, 0, FS_NewGroupParentPU, name, myType, number, 0, 0));
1458 					break;
1459 				}
1460 
1461 				MessageWindows(WC_YouClose, 0, 0, parentID, myID);
1462 				closed = true;
1463 			}
1464 			break;
1465 		}
1466 	}
1467 
1468 	return false;
1469 }
1470 
CapShipTypeSlider(int ix,int iy,int iParentID,int flags)1471 CapShipTypeSlider::CapShipTypeSlider(int ix, int iy, int iParentID, int flags):
1472 Slider(ix, iy, static_cast<int>(CST_Medium), static_cast<int>(CST_Light), static_cast<int>(CST_Heavy), iParentID, flags) {}
1473 
DrawSelf()1474 void CapShipTypeSlider::DrawSelf() {
1475 	Slider::DrawSelf();
1476 
1477 	CapShipType currentType = static_cast<CapShipType>(sliderVar);
1478 	string typeStr = csTypeToString[currentType];
1479 	typeStr = typeStr.substr(0, typeStr.find(' '));
1480 
1481 	//in text
1482 	int x = rect.x + smallBorderSize;
1483 	int y = rect.y + smallBorderSize;
1484 	string output = "Capital ship type: " + typeStr;
1485 	normalFonts.BlitString(x, y, 0, output);
1486 }
1487 
WhichSaveGroup(int iMyGroup,bool globalVar)1488 WhichSaveGroup::WhichSaveGroup(int iMyGroup, bool globalVar):
1489 PopupMenu(0, 0, none_constant, 0), myGroup(iMyGroup) {
1490 	MenuItem tempItem;
1491 
1492 	for (int i = 0; i != nAIVars; ++i) {
1493 		char whichStr[60];
1494 
1495 		if (globalVar) {
1496 			sprintf(whichStr, "$globalg%d:     myside-%d", i, sides[0].saveGroups[i].y + 1);
1497 			tempItem.choice = FS_ChooseGSaveGroup;
1498 		} else {
1499 			sprintf(whichStr, "$g%d:     myside-%d", i, sides[0].groups[myGroup].GetSaveGroup(i).y + 1);
1500 			tempItem.choice = FS_ChooseSaveGroup;
1501 		}
1502 
1503 		tempItem.desc = whichStr;
1504 		tempItem.parem = i;
1505 		AddItem(tempItem);
1506 	}
1507 
1508 	InitRects();
1509 	CentreWindow();
1510 }
1511 
SwitchOnChoice(Uint16 x,Uint16 y)1512 bool WhichSaveGroup::SwitchOnChoice(Uint16 x, Uint16 y) {
1513 	if (currentSelection.choiceType == MCT_LeftCursor) {
1514 		myWindows.push_back(GenWindow(WC_SidePU, 0, myGroup, currentSelection.choice, currentSelection.parem));
1515 		closed = true;
1516 	}
1517 
1518 	return false;
1519 }
1520 
DeleteFleet(const string & iSideName,int iParentID)1521 DeleteFleet::DeleteFleet(const string& iSideName, int iParentID):
1522 Menu_Base(0, 0, iParentID, 0), sideName(iSideName) {
1523 	MenuItem tempItem;
1524 
1525 	tempItem.desc = "Are you sure you wish to delete this fleet?";
1526 	tempItem.choice = WC_Nothing;
1527 	AddItem(tempItem);
1528 
1529 	tempItem.desc = "Yes";
1530 	tempItem.choice = WC_Yes;
1531 	AddItem(tempItem);
1532 
1533 	tempItem.desc = "No";
1534 	tempItem.choice = WC_No;
1535 	AddItem(tempItem);
1536 
1537 	InitRects();
1538 	CentreWindow();
1539 }
1540 
SwitchOnChoice(Uint16 x,Uint16 y)1541 bool DeleteFleet::SwitchOnChoice(Uint16 x, Uint16 y) {
1542 	if (currentSelection.choiceType == MCT_LeftCursor) {
1543 		switch (currentSelection.choice) {
1544 		case WC_Yes:
1545 			RemoveDirectory(globalSettings.bdp + "fleets/" + sideName);
1546 			MessageWindows(WC_ExpensiveUpdate, 0, 0, parentID, myID);
1547 			closed = true;
1548 			break;
1549 
1550 		case WC_No:
1551 			closed = true;
1552 			break;
1553 		}
1554 	}
1555 
1556 	return false;
1557 }
1558 
CopyFleet(const string & iSideName,int iParentID)1559 CopyFleet::CopyFleet(const string& iSideName, int iParentID):
1560 StringInputBox(maxNameLength, iParentID, 0), sideName(iSideName) {
1561 	title = "What would you like to call the copy?";
1562 	rect.x = 200;
1563 	rect.y = 200;
1564 	rect.w = 400;
1565 	rect.h = 100;
1566 
1567 	InitRects();
1568 }
1569 
Keyboard(SDL_keysym & keysym)1570 bool CopyFleet::Keyboard(SDL_keysym& keysym) {
1571 	StringInputBox::Keyboard(keysym);
1572 
1573 	namespace fs = boost::filesystem;
1574 
1575 	if (userHitEnter) {
1576 		if (CheckNameValid(theInput, true)) {
1577 			try {
1578 				fs::path sourcePath(globalSettings.bdp + "fleets/" + sideName);
1579 				fs::path destPath(globalSettings.bdp + "fleets/" + theInput);
1580 				fs::create_directory(destPath);
1581 				DoCopy(sourcePath, destPath);
1582 				MessageWindows(WC_ExpensiveUpdate, 0, 0, parentID, myID);
1583 			} catch (fs::filesystem_error e) {
1584 				string errorStr = "\n";
1585 				errorStr += e.what();
1586 				CreateInfoString(errorStr);
1587 			}
1588 		}
1589 	}
1590 
1591 	return true;
1592 }
1593 
DoCopy(boost::filesystem::path sourcePath,boost::filesystem::path destPath)1594 void CopyFleet::DoCopy(boost::filesystem::path sourcePath, boost::filesystem::path destPath) {
1595 	namespace fs = boost::filesystem;
1596 	fs::directory_iterator directoryEnd; // default construction yields past-the-end
1597 	for (fs::directory_iterator iter(sourcePath); iter != directoryEnd; ++iter) {
1598 		if (is_directory(*iter)) {
1599 			fs::create_directory(destPath.string() + "/" + iter->path().filename().string());
1600 			DoCopy(sourcePath.string() + "/" + iter->path().filename().string(), destPath.string() + "/" + iter->path().filename().string());
1601 			continue;
1602 		}
1603 		string destFile;
1604 		if (iter->path().filename() == sideName + ".dat")
1605 			destFile = theInput + ".dat";
1606 		else
1607 			destFile = iter->path().filename().string();
1608 
1609 		fs::copy_file(*iter, destPath.string() + "/" + destFile);
1610 	}
1611 }
1612 
1613 } //end namespace
1614