1 //       _________ __                 __
2 //      /   _____//  |_____________ _/  |______     ____  __ __  ______
3 //      \_____  \\   __\_  __ \__  \\   __\__  \   / ___\|  |  \/  ___/
4 //      /        \|  |  |  | \// __ \|  |  / __ \_/ /_/  >  |  /\___ |
5 //     /_______  /|__|  |__|  (____  /__| (____  /\___  /|____//____  >
6 //             \/                  \/          \//_____/            \/
7 //  ______________________                           ______________________
8 //                        T H E   W A R   B E G I N S
9 //         Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name script_ui.cpp - The ui ccl functions. */
12 //
13 //      (c) Copyright 1999-2019 by Lutz Sammer, Jimmy Salmon, Martin Renold
14 //      and Andrettin
15 //
16 //      This program is free software; you can redistribute it and/or modify
17 //      it under the terms of the GNU General Public License as published by
18 //      the Free Software Foundation; only version 2 of the License.
19 //
20 //      This program is distributed in the hope that it will be useful,
21 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
22 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 //      GNU General Public License for more details.
24 //
25 //      You should have received a copy of the GNU General Public License
26 //      along with this program; if not, write to the Free Software
27 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 //      02111-1307, USA.
29 //
30 
31 //@{
32 
33 /*----------------------------------------------------------------------------
34 --  Includes
35 ----------------------------------------------------------------------------*/
36 
37 #include "stratagus.h"
38 
39 #include "ui/ui.h"
40 
41 #include "font.h"
42 //Wyrmgus start
43 #include "icons.h"
44 //Wyrmgus end
45 #include "map/map.h"
46 #include "menus.h"
47 #include "script.h"
48 #include "spells.h"
49 #include "title.h"
50 #include "util.h"
51 #include "ui/button_action.h"
52 #include "ui/button_level.h"
53 #include "ui/contenttype.h"
54 #include "ui/interface.h"
55 #include "ui/popup.h"
56 #include "unit/unit.h"
57 #include "unit/unit_manager.h"
58 #include "unit/unittype.h"
59 #include "video.h"
60 
61 /*----------------------------------------------------------------------------
62 --  Variables
63 ----------------------------------------------------------------------------*/
64 
65 std::string ClickMissile;		/// FIXME:docu
66 std::string DamageMissile;		/// FIXME:docu
67 std::map<std::string, ButtonStyle *> ButtonStyleHash;
68 
69 static int HandleCount = 1;		/// Lua handler count
70 
71 CPreference Preference;
72 
73 /*----------------------------------------------------------------------------
74 --  Functions
75 ----------------------------------------------------------------------------*/
76 
77 /**
78 **  Set speed of key scroll
79 **
80 **  @param l  Lua state.
81 */
CclSetKeyScrollSpeed(lua_State * l)82 static int CclSetKeyScrollSpeed(lua_State *l)
83 {
84 	LuaCheckArgs(l, 1);
85 	UI.KeyScrollSpeed = LuaToNumber(l, 1);
86 	return 0;
87 }
88 
89 /**
90 **  Get speed of key scroll
91 **
92 **  @param l  Lua state.
93 */
CclGetKeyScrollSpeed(lua_State * l)94 static int CclGetKeyScrollSpeed(lua_State *l)
95 {
96 	LuaCheckArgs(l, 0);
97 	lua_pushnumber(l, UI.KeyScrollSpeed);
98 	return 1;
99 }
100 
101 /**
102 **  Set speed of mouse scroll
103 **
104 **  @param l  Lua state.
105 */
CclSetMouseScrollSpeed(lua_State * l)106 static int CclSetMouseScrollSpeed(lua_State *l)
107 {
108 	LuaCheckArgs(l, 1);
109 	UI.MouseScrollSpeed = LuaToNumber(l, 1);
110 	return 0;
111 }
112 
113 /**
114 **  Get speed of mouse scroll
115 **
116 **  @param l  Lua state.
117 */
CclGetMouseScrollSpeed(lua_State * l)118 static int CclGetMouseScrollSpeed(lua_State *l)
119 {
120 	LuaCheckArgs(l, 0);
121 	lua_pushnumber(l, UI.MouseScrollSpeed);
122 	return 1;
123 }
124 
125 /**
126 **  Set speed of middle-mouse scroll
127 **
128 **  @param l  Lua state.
129 */
CclSetMouseScrollSpeedDefault(lua_State * l)130 static int CclSetMouseScrollSpeedDefault(lua_State *l)
131 {
132 	LuaCheckArgs(l, 1);
133 	UI.MouseScrollSpeedDefault = LuaToNumber(l, 1);
134 	return 0;
135 }
136 
137 /**
138 **  Get speed of middle-mouse scroll
139 **
140 **  @param l  Lua state.
141 */
CclGetMouseScrollSpeedDefault(lua_State * l)142 static int CclGetMouseScrollSpeedDefault(lua_State *l)
143 {
144 	LuaCheckArgs(l, 0);
145 	lua_pushnumber(l, UI.MouseScrollSpeedDefault);
146 	return 0;
147 }
148 
149 /**
150 **  Set speed of ctrl-middle-mouse scroll
151 **
152 **  @param l  Lua state.
153 */
CclSetMouseScrollSpeedControl(lua_State * l)154 static int CclSetMouseScrollSpeedControl(lua_State *l)
155 {
156 	LuaCheckArgs(l, 1);
157 	UI.MouseScrollSpeedControl = LuaToNumber(l, 1);
158 	return 0;
159 }
160 
161 /**
162 **  Get speed of ctrl-middle-mouse scroll
163 **
164 **  @param l  Lua state.
165 */
CclGetMouseScrollSpeedControl(lua_State * l)166 static int CclGetMouseScrollSpeedControl(lua_State *l)
167 {
168 	LuaCheckArgs(l, 0);
169 	lua_pushnumber(l, UI.MouseScrollSpeedControl);
170 	return 0;
171 }
172 
173 /**
174 **  Set which missile is used for right click
175 **
176 **  @param l  Lua state.
177 */
CclSetClickMissile(lua_State * l)178 static int CclSetClickMissile(lua_State *l)
179 {
180 	const int args = lua_gettop(l);
181 	if (args > 1 || (args == 1 && (!lua_isnil(l, 1) && !lua_isstring(l, 1)))) {
182 		LuaError(l, "incorrect argument");
183 	}
184 	ClickMissile.clear();
185 	if (args == 1 && !lua_isnil(l, 1)) {
186 		ClickMissile = lua_tostring(l, 1);
187 	}
188 	return 0;
189 }
190 
191 /**
192 **  Set which missile shows Damage
193 **
194 **  @param l  Lua state.
195 */
CclSetDamageMissile(lua_State * l)196 static int CclSetDamageMissile(lua_State *l)
197 {
198 	const int args = lua_gettop(l);
199 
200 	if (args > 1 || (args == 1 && (!lua_isnil(l, 1) && !lua_isstring(l, 1)))) {
201 		LuaError(l, "incorrect argument");
202 	}
203 	DamageMissile.clear();
204 	if (args == 1 && !lua_isnil(l, 1)) {
205 		DamageMissile = lua_tostring(l, 1);
206 	}
207 	return 0;
208 }
209 
CclSetMaxOpenGLTexture(lua_State * l)210 static int CclSetMaxOpenGLTexture(lua_State *l)
211 {
212 	LuaCheckArgs(l, 1);
213 #if defined(USE_OPENGL) || defined(USE_GLES)
214 	if (CclInConfigFile) {
215 		GLMaxTextureSizeOverride = LuaToNumber(l, 1);
216 	}
217 #endif
218 	return 0;
219 }
220 
CclSetUseTextureCompression(lua_State * l)221 static int CclSetUseTextureCompression(lua_State *l)
222 {
223 	LuaCheckArgs(l, 1);
224 #if defined(USE_OPENGL) || defined(USE_GLES)
225 	if (CclInConfigFile) {
226 		UseGLTextureCompression = LuaToBoolean(l, 1);
227 	}
228 #endif
229 	return 0;
230 }
231 
CclSetUseOpenGL(lua_State * l)232 static int CclSetUseOpenGL(lua_State *l)
233 {
234 	LuaCheckArgs(l, 1);
235 #if defined(USE_OPENGL) || defined(USE_GLES)
236 	if (CclInConfigFile) {
237 		// May have been set from the command line
238 		if (!ForceUseOpenGL) {
239 			UseOpenGL = LuaToBoolean(l, 1);
240 		}
241 	}
242 #endif
243 	return 0;
244 }
245 
CclSetZoomNoResize(lua_State * l)246 static int CclSetZoomNoResize(lua_State *l)
247 {
248 	LuaCheckArgs(l, 1);
249 #if defined(USE_OPENGL) || defined(USE_GLES)
250 	if (CclInConfigFile) {
251 		// May have been set from the command line
252 		if (!ForceUseOpenGL) {
253 			ZoomNoResize = LuaToBoolean(l, 1);
254 			if (ZoomNoResize) {
255 				UseOpenGL = true;
256 			}
257 		}
258 	}
259 #endif
260 	return 0;
261 }
262 
263 /**
264 **  Set the video resolution.
265 **
266 **  @param l  Lua state.
267 */
CclSetVideoResolution(lua_State * l)268 static int CclSetVideoResolution(lua_State *l)
269 {
270 	LuaCheckArgs(l, 2);
271 	if (CclInConfigFile) {
272 		// May have been set from the command line
273 		if (!Video.Width || !Video.Height) {
274 			Video.Width = LuaToNumber(l, 1);
275 			Video.Height = LuaToNumber(l, 2);
276 		}
277 	}
278 	return 0;
279 }
280 
281 /**
282 **  Get the video resolution.
283 **
284 **  @param l  Lua state.
285 */
CclGetVideoResolution(lua_State * l)286 static int CclGetVideoResolution(lua_State *l)
287 {
288 	LuaCheckArgs(l, 0);
289 	lua_pushnumber(l, Video.Width);
290 	lua_pushnumber(l, Video.Height);
291 	return 2;
292 }
293 
294 /**
295 **  Set the video fullscreen mode.
296 **
297 **  @param l  Lua state.
298 */
CclSetVideoFullScreen(lua_State * l)299 static int CclSetVideoFullScreen(lua_State *l)
300 {
301 	LuaCheckArgs(l, 1);
302 	if (CclInConfigFile) {
303 		// May have been set from the command line
304 		if (!VideoForceFullScreen) {
305 			Video.FullScreen = LuaToBoolean(l, 1);
306 		}
307 	}
308 	return 0;
309 }
310 
311 /**
312 **  Get the video fullscreen mode.
313 **
314 **  @param l  Lua state.
315 */
CclGetVideoFullScreen(lua_State * l)316 static int CclGetVideoFullScreen(lua_State *l)
317 {
318 	LuaCheckArgs(l, 0);
319 	lua_pushboolean(l, Video.FullScreen);
320 	return 1;
321 }
322 
323 /**
324 **  Default title screens.
325 **
326 **  @param l  Lua state.
327 */
CclSetTitleScreens(lua_State * l)328 static int CclSetTitleScreens(lua_State *l)
329 {
330 	if (TitleScreens) {
331 		for (int i = 0; TitleScreens[i]; ++i) {
332 			delete TitleScreens[i];
333 		}
334 		delete[] TitleScreens;
335 		TitleScreens = nullptr;
336 	}
337 
338 	const int args = lua_gettop(l);
339 	TitleScreens = new TitleScreen *[args + 1];
340 	memset(TitleScreens, 0, (args + 1) * sizeof(TitleScreen *));
341 
342 	for (int j = 0; j < args; ++j) {
343 		if (!lua_istable(l, j + 1)) {
344 			LuaError(l, "incorrect argument");
345 		}
346 		TitleScreens[j] = new TitleScreen;
347 		TitleScreens[j]->Iterations = 1;
348 		lua_pushnil(l);
349 		while (lua_next(l, j + 1)) {
350 			const char *value = LuaToString(l, -2);
351 			if (!strcmp(value, "Image")) {
352 				TitleScreens[j]->File = LuaToString(l, -1);
353 			} else if (!strcmp(value, "Music")) {
354 				TitleScreens[j]->Music = LuaToString(l, -1);
355 			} else if (!strcmp(value, "Timeout")) {
356 				TitleScreens[j]->Timeout = LuaToNumber(l, -1);
357 			} else if (!strcmp(value, "Iterations")) {
358 				TitleScreens[j]->Iterations = LuaToNumber(l, -1);
359 			} else if (!strcmp(value, "Editor")) {
360 				TitleScreens[j]->Editor = LuaToNumber(l, -1);
361 			} else if (!strcmp(value, "Labels")) {
362 				if (!lua_istable(l, -1)) {
363 					LuaError(l, "incorrect argument");
364 				}
365 				const int subargs = lua_rawlen(l, -1);
366 				TitleScreens[j]->Labels = new TitleScreenLabel *[subargs + 1];
367 				memset(TitleScreens[j]->Labels, 0, (subargs + 1) * sizeof(TitleScreenLabel *));
368 				for (int k = 0; k < subargs; ++k) {
369 					lua_rawgeti(l, -1, k + 1);
370 					if (!lua_istable(l, -1)) {
371 						LuaError(l, "incorrect argument");
372 					}
373 					TitleScreens[j]->Labels[k] = new TitleScreenLabel;
374 					lua_pushnil(l);
375 					while (lua_next(l, -2)) {
376 						const char *value = LuaToString(l, -2);
377 						if (!strcmp(value, "Text")) {
378 							TitleScreens[j]->Labels[k]->Text = LuaToString(l, -1);
379 						} else if (!strcmp(value, "Font")) {
380 							TitleScreens[j]->Labels[k]->Font = CFont::Get(LuaToString(l, -1));
381 						} else if (!strcmp(value, "Pos")) {
382 							CclGetPos(l, &TitleScreens[j]->Labels[k]->Xofs, &TitleScreens[j]->Labels[k]->Yofs);
383 						} else if (!strcmp(value, "Flags")) {
384 							if (!lua_istable(l, -1)) {
385 								LuaError(l, "incorrect argument");
386 							}
387 							const int subsubargs = lua_rawlen(l, -1);
388 							for (int subk = 0; subk < subsubargs; ++subk) {
389 								const char *value = LuaToString(l, -1, subk + 1);
390 								if (!strcmp(value, "center")) {
391 									TitleScreens[j]->Labels[k]->Flags |= TitleFlagCenter;
392 								} else {
393 									LuaError(l, "incorrect flag");
394 								}
395 							}
396 						} else {
397 							LuaError(l, "Unsupported key: %s" _C_ value);
398 						}
399 						lua_pop(l, 1);
400 					}
401 					lua_pop(l, 1);
402 				}
403 			} else {
404 				LuaError(l, "Unsupported key: %s" _C_ value);
405 			}
406 			lua_pop(l, 1);
407 		}
408 	}
409 	return 0;
410 }
411 
412 /**
413 **  Return enum from string about variable component.
414 **
415 **  @param l Lua State.
416 **  @param s string to convert.
417 **
418 **  @return  Corresponding value.
419 **  @note    Stop on error.
420 */
Str2EnumVariable(lua_State * l,const char * s)421 EnumVariable Str2EnumVariable(lua_State *l, const char *s)
422 {
423 	static struct {
424 		const char *s;
425 		EnumVariable e;
426 	} list[] = {
427 		{"Value", VariableValue},
428 		{"Max", VariableMax},
429 		{"Increase", VariableIncrease},
430 		{"Diff", VariableDiff},
431 		{"Percent", VariablePercent},
432 		{"Name", VariableName},
433 		//Wyrmgus start
434 		{"Change", VariableChange},
435 		{"IncreaseChange", VariableIncreaseChange},
436 		//Wyrmgus end
437 		{0, VariableValue}
438 	}; // List of possible values.
439 
440 	for (int i = 0; list[i].s; ++i) {
441 		if (!strcmp(s, list[i].s)) {
442 			return list[i].e;
443 		}
444 	}
445 	LuaError(l, "'%s' is a invalid variable component" _C_ s);
446 	return VariableValue;
447 }
448 
449 /**
450 **  Parse the condition Panel.
451 **
452 **  @param l   Lua State.
453 */
ParseConditionPanel(lua_State * l)454 static ConditionPanel *ParseConditionPanel(lua_State *l)
455 {
456 	Assert(lua_istable(l, -1));
457 
458 	ConditionPanel *condition = new ConditionPanel;
459 
460 	for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) {
461 		const char *key = LuaToString(l, -2);
462 		if (!strcmp(key, "ShowOnlySelected")) {
463 			condition->ShowOnlySelected = LuaToBoolean(l, -1);
464 		} else if (!strcmp(key, "HideNeutral")) {
465 			condition->HideNeutral = LuaToBoolean(l, -1);
466 		} else if (!strcmp(key, "HideAllied")) {
467 			condition->HideAllied = LuaToBoolean(l, -1);
468 		} else if (!strcmp(key, "ShowOpponent")) {
469 			condition->ShowOpponent = LuaToBoolean(l, -1);
470 		} else if (!strcmp(key, "ShowIfCanCastAnySpell")) {
471 			condition->ShowIfCanCastAnySpell = LuaToBoolean(l, -1);
472 		//Wyrmgus start
473 		} else if (!strcmp(key, "Affixed")) {
474 			condition->Affixed = Ccl2Condition(l, LuaToString(l, -1));
475 		} else if (!strcmp(key, "Unique")) {
476 			condition->Unique = Ccl2Condition(l, LuaToString(l, -1));
477 		} else if (!strcmp(key, "Replenishment")) {
478 			condition->Replenishment = Ccl2Condition(l, LuaToString(l, -1));
479 		//Wyrmgus end
480 		} else {
481 			int index = UnitTypeVar.BoolFlagNameLookup[key];
482 			if (index != -1) {
483 				if (!condition->BoolFlags) {
484 					size_t new_bool_size = UnitTypeVar.GetNumberBoolFlag();
485 					condition->BoolFlags = new char[new_bool_size];
486 					memset(condition->BoolFlags, 0, new_bool_size * sizeof(char));
487 				}
488 				condition->BoolFlags[index] = Ccl2Condition(l, LuaToString(l, -1));
489 				continue;
490 			}
491 			index = UnitTypeVar.VariableNameLookup[key];
492 			if (index != -1) {
493 				if (!condition->Variables) {
494 					size_t new_variables_size = UnitTypeVar.GetNumberVariable();
495 					condition->Variables = new char[new_variables_size];
496 					memset(condition->Variables, 0, new_variables_size * sizeof(char));
497 				}
498 				condition->Variables[index] = Ccl2Condition(l, LuaToString(l, -1));
499 				continue;
500 			}
501 			LuaError(l, "'%s' invalid for Condition in DefinePanelContents" _C_ key);
502 		}
503 	}
504 	return condition;
505 }
506 
CclParseContent(lua_State * l)507 static CContentType *CclParseContent(lua_State *l)
508 {
509 	Assert(lua_istable(l, -1));
510 
511 	CContentType *content = nullptr;
512 	ConditionPanel *condition = nullptr;
513 	PixelPos pos(0, 0);
514 	//Wyrmgus start
515 	std::string textColor("white");
516 	std::string highColor("red");
517 	//Wyrmgus end
518 
519 	for (lua_pushnil(l); lua_next(l, -2); lua_pop(l, 1)) {
520 		const char *key = LuaToString(l, -2);
521 		if (!strcmp(key, "Pos")) {
522 			CclGetPos(l, &pos.x, &pos.y);
523 		//Wyrmgus start
524 		} else if (!strcmp(key, "TextColor")) {
525 			textColor = LuaToString(l, -1);
526 		} else if (!strcmp(key, "HighlightColor")) {
527 			highColor = LuaToString(l, -1);
528 		//Wyrmgus end
529 		} else if (!strcmp(key, "More")) {
530 			Assert(lua_istable(l, -1));
531 			lua_rawgeti(l, -1, 1); // Method name
532 			lua_rawgeti(l, -2, 2); // Method data
533 			key = LuaToString(l, -2);
534 			if (!strcmp(key, "Text")) {
535 				content = new CContentTypeText;
536 			} else if (!strcmp(key, "FormattedText")) {
537 				content = new CContentTypeFormattedText;
538 			} else if (!strcmp(key, "FormattedText2")) {
539 				content = new CContentTypeFormattedText2;
540 			} else if (!strcmp(key, "Icon")) {
541 				content = new CContentTypeIcon;
542 			} else if (!strcmp(key, "LifeBar")) {
543 				content = new CContentTypeLifeBar;
544 			} else if (!strcmp(key, "CompleteBar")) {
545 				content = new CContentTypeCompleteBar;
546 			} else {
547 				LuaError(l, "Invalid drawing method '%s' in DefinePanelContents" _C_ key);
548 			}
549 			content->Parse(l);
550 			lua_pop(l, 2); // Pop Variable Name and Method
551 		} else if (!strcmp(key, "Condition")) {
552 			condition = ParseConditionPanel(l);
553 		} else {
554 			LuaError(l, "'%s' invalid for Contents in DefinePanelContents" _C_ key);
555 		}
556 	}
557 	content->Pos = pos;
558 	content->Condition = condition;
559 	//Wyrmgus start
560 	content->TextColor = textColor;
561 	content->HighlightColor = highColor;
562 	//Wyrmgus end
563 	return content;
564 }
565 
566 
567 /**
568 **  Define the Panels.
569 **  Define what is shown in the panel(text, icon, variables)
570 **
571 **  @param l  Lua state.
572 **  @return   0.
573 */
CclDefinePanelContents(lua_State * l)574 static int CclDefinePanelContents(lua_State *l)
575 {
576 	const int nargs = lua_gettop(l);
577 
578 	for (int i = 0; i < nargs; i++) {
579 		Assert(lua_istable(l, i + 1));
580 		CUnitInfoPanel *infopanel = new CUnitInfoPanel;
581 
582 		for (lua_pushnil(l); lua_next(l, i + 1); lua_pop(l, 1)) {
583 			const char *key = LuaToString(l, -2);
584 
585 			if (!strcmp(key, "Ident")) {
586 				infopanel->Name = LuaToString(l, -1);
587 			} else if (!strcmp(key, "Pos")) {
588 				CclGetPos(l, &infopanel->PosX, &infopanel->PosY);
589 			} else if (!strcmp(key, "DefaultFont")) {
590 				infopanel->DefaultFont = CFont::Get(LuaToString(l, -1));
591 			} else if (!strcmp(key, "Condition")) {
592 				infopanel->Condition = ParseConditionPanel(l);
593 			} else if (!strcmp(key, "Contents")) {
594 				Assert(lua_istable(l, -1));
595 				for (size_t j = 0; j < lua_rawlen(l, -1); j++, lua_pop(l, 1)) {
596 					lua_rawgeti(l, -1, j + 1);
597 					infopanel->Contents.push_back(CclParseContent(l));
598 				}
599 			} else {
600 				LuaError(l, "'%s' invalid for DefinePanelContents" _C_ key);
601 			}
602 		}
603 		for (std::vector<CContentType *>::iterator content = infopanel->Contents.begin();
604 			 content != infopanel->Contents.end(); ++content) { // Default value for invalid value.
605 			(*content)->Pos.x += infopanel->PosX;
606 			(*content)->Pos.y += infopanel->PosY;
607 		}
608 		size_t j;
609 		for (j = 0; j < UI.InfoPanelContents.size(); ++j) {
610 			if (infopanel->Name == UI.InfoPanelContents[j]->Name) {
611 				DebugPrint("Redefinition of Panel '%s'\n" _C_ infopanel->Name.c_str());
612 				delete UI.InfoPanelContents[j];
613 				UI.InfoPanelContents[j] = infopanel;
614 				break;
615 			}
616 		}
617 		if (j == UI.InfoPanelContents.size()) {
618 			UI.InfoPanelContents.push_back(infopanel);
619 		}
620 	}
621 	return 0;
622 }
623 
624 /**
625 **  Define the Panels.
626 **  Define what is shown in the panel(text, icon, variables)
627 **
628 **  @param l  Lua state.
629 **  @return   0.
630 */
CclDefinePopup(lua_State * l)631 static int CclDefinePopup(lua_State *l)
632 {
633 	Assert(lua_istable(l, 1));
634 
635 	CPopup *popup = new CPopup;
636 
637 	for (lua_pushnil(l); lua_next(l, 1); lua_pop(l, 1)) {
638 		const char *key = LuaToString(l, -2);
639 
640 		if (!strcmp(key, "Ident")) {
641 			popup->Ident = LuaToString(l, -1);
642 		} else if (!strcmp(key, "DefaultFont")) {
643 			popup->DefaultFont = CFont::Get(LuaToString(l, -1));
644 		} else if (!strcmp(key, "BackgroundColor")) {
645 			popup->BackgroundColor = LuaToUnsignedNumber(l, -1);
646 		} else if (!strcmp(key, "BorderColor")) {
647 			popup->BorderColor = LuaToUnsignedNumber(l, -1);
648 		} else if (!strcmp(key, "Margin")) {
649 			CclGetPos(l, &popup->MarginX, &popup->MarginY);
650 		} else if (!strcmp(key, "MinWidth")) {
651 			popup->MinWidth = LuaToNumber(l, -1);
652 		} else if (!strcmp(key, "MinHeight")) {
653 			popup->MinHeight = LuaToNumber(l, -1);
654 		} else if (!strcmp(key, "Contents")) {
655 			Assert(lua_istable(l, -1));
656 			for (size_t j = 0; j < lua_rawlen(l, -1); j++, lua_pop(l, 1)) {
657 				lua_rawgeti(l, -1, j + 1);
658 				popup->Contents.push_back(CPopupContentType::ParsePopupContent(l));
659 			}
660 		} else {
661 			LuaError(l, "'%s' invalid for DefinePopups" _C_ key);
662 		}
663 	}
664 	for (size_t j = 0; j < UI.ButtonPopups.size(); ++j) {
665 		if (popup->Ident == UI.ButtonPopups[j]->Ident) {
666 			DebugPrint("Redefinition of Popup '%s'\n" _C_ popup->Ident.c_str());
667 			delete UI.ButtonPopups[j];
668 			UI.ButtonPopups[j] = popup;
669 			return 0;
670 		}
671 	}
672 	UI.ButtonPopups.push_back(popup);
673 	return 0;
674 }
675 
676 /**
677 **  Define the viewports.
678 **
679 **  @param l  Lua state.
680 */
CclDefineViewports(lua_State * l)681 static int CclDefineViewports(lua_State *l)
682 {
683 	int i = 0;
684 	const int args = lua_gettop(l);
685 
686 	for (int j = 0; j < args; ++j) {
687 		const char *value = LuaToString(l, j + 1);
688 		++j;
689 		if (!strcmp(value, "mode")) {
690 			UI.ViewportMode = (ViewportModeType)LuaToNumber(l, j + 1);
691 		} else if (!strcmp(value, "viewport")) {
692 			if (!lua_istable(l, j + 1) && lua_rawlen(l, j + 1) != 3) {
693 				LuaError(l, "incorrect argument");
694 			}
695 			UI.Viewports[i].MapPos.x = LuaToNumber(l, j + 1, 1);
696 			UI.Viewports[i].MapPos.y = LuaToNumber(l, j + 1, 2);
697 			const int slot = LuaToNumber(l, j + 1, 3);
698 			if (slot != -1) {
699 				UI.Viewports[i].Unit = &UnitManager.GetSlotUnit(slot);
700 			}
701 			++i;
702 		} else {
703 			LuaError(l, "Unsupported tag: %s" _C_ value);
704 		}
705 	}
706 	UI.NumViewports = i;
707 	return 0;
708 }
709 
710 /**
711 **  Fighter right button attacks as default.
712 **
713 **  @param l  Lua state.
714 */
CclRightButtonAttacks(lua_State * l)715 static int CclRightButtonAttacks(lua_State *l)
716 {
717 	LuaCheckArgs(l, 0);
718 	RightButtonAttacks = true;
719 	return 0;
720 }
721 
722 /**
723 **  Fighter right button moves as default.
724 **
725 **  @param l  Lua state.
726 */
CclRightButtonMoves(lua_State * l)727 static int CclRightButtonMoves(lua_State *l)
728 {
729 	LuaCheckArgs(l, 0);
730 	RightButtonAttacks = false;
731 	return 0;
732 }
733 
734 /**
735 **  Enable/disable the fancy buildings.
736 **
737 **  @param l  Lua state.
738 */
CclSetFancyBuildings(lua_State * l)739 static int CclSetFancyBuildings(lua_State *l)
740 {
741 	LuaCheckArgs(l, 1);
742 	FancyBuildings = LuaToBoolean(l, 1);
743 	return 0;
744 }
745 
746 /**
747 **  Find a button style
748 **
749 **  @param style  Name of the style to find.
750 **
751 **  @return       Button style, null if not found.
752 */
FindButtonStyle(const std::string & style)753 ButtonStyle *FindButtonStyle(const std::string &style)
754 {
755 	return ButtonStyleHash[style];
756 }
757 
758 /**
759 **  Parse button style properties
760 **
761 **  @param l  Lua state.
762 **  @param p  Properties to fill in.
763 */
ParseButtonStyleProperties(lua_State * l,ButtonStyleProperties * p)764 static void ParseButtonStyleProperties(lua_State *l, ButtonStyleProperties *p)
765 {
766 	if (!lua_istable(l, -1)) {
767 		LuaError(l, "incorrect argument");
768 	}
769 	std::string file;
770 	int w = 0;
771 	int h = 0;
772 
773 	lua_pushnil(l);
774 	while (lua_next(l, -2)) {
775 		const char *value = LuaToString(l, -2);
776 		if (!strcmp(value, "File")) {
777 			file = LuaToString(l, -1);
778 		} else if (!strcmp(value, "Size")) {
779 			CclGetPos(l, &w, &h);
780 		} else if (!strcmp(value, "Frame")) {
781 			p->Frame = LuaToNumber(l, -1);
782 		} else if (!strcmp(value, "Border")) {
783 			if (!lua_istable(l, -1)) {
784 				LuaError(l, "incorrect argument");
785 			}
786 			lua_pushnil(l);
787 			while (lua_next(l, -2)) {
788 				value = LuaToString(l, -2);
789 				if (!strcmp(value, "Color")) {
790 					p->BorderColorRGB.Parse(l);
791 				} else if (!strcmp(value, "Size")) {
792 					p->BorderSize = LuaToNumber(l, -1);
793 				} else {
794 					LuaError(l, "Unsupported tag: %s" _C_ value);
795 				}
796 				lua_pop(l, 1);
797 			}
798 		} else if (!strcmp(value, "TextPos")) {
799 			CclGetPos(l, &p->TextPos.x, &p->TextPos.y);
800 		} else if (!strcmp(value, "TextAlign")) {
801 			value = LuaToString(l, -1);
802 			if (!strcmp(value, "Center")) {
803 				p->TextAlign = TextAlignCenter;
804 			} else if (!strcmp(value, "Right")) {
805 				p->TextAlign = TextAlignRight;
806 			} else if (!strcmp(value, "Left")) {
807 				p->TextAlign = TextAlignLeft;
808 			} else {
809 				LuaError(l, "Invalid text alignment: %s" _C_ value);
810 			}
811 		} else if (!strcmp(value, "TextNormalColor")) {
812 			p->TextNormalColor = LuaToString(l, -1);
813 		} else if (!strcmp(value, "TextReverseColor")) {
814 			p->TextReverseColor = LuaToString(l, -1);
815 		} else {
816 			LuaError(l, "Unsupported tag: %s" _C_ value);
817 		}
818 		lua_pop(l, 1);
819 	}
820 
821 	if (!file.empty()) {
822 		p->Sprite = CGraphic::New(file, w, h);
823 	}
824 }
825 
826 /**
827 **  Define a button style
828 **
829 **  @param l  Lua state.
830 */
CclDefineButtonStyle(lua_State * l)831 static int CclDefineButtonStyle(lua_State *l)
832 {
833 	LuaCheckArgs(l, 2);
834 	if (!lua_istable(l, 2)) {
835 		LuaError(l, "incorrect argument");
836 	}
837 	const char *style = LuaToString(l, 1);
838 	ButtonStyle *&b = ButtonStyleHash[style];
839 	if (!b) {
840 		b = new ButtonStyle;
841 		// Set to bogus value to see if it was set later
842 		b->Default.TextPos.x = b->Hover.TextPos.x = b->Clicked.TextPos.x = 0xFFFFFF;
843 	}
844 
845 	lua_pushnil(l);
846 	while (lua_next(l, 2)) {
847 		const char *value = LuaToString(l, -2);
848 
849 		if (!strcmp(value, "Size")) {
850 			CclGetPos(l, &b->Width, &b->Height);
851 		} else if (!strcmp(value, "Font")) {
852 			b->Font = CFont::Get(LuaToString(l, -1));
853 		} else if (!strcmp(value, "TextNormalColor")) {
854 			b->TextNormalColor = LuaToString(l, -1);
855 		} else if (!strcmp(value, "TextReverseColor")) {
856 			b->TextReverseColor = LuaToString(l, -1);
857 		} else if (!strcmp(value, "TextPos")) {
858 			CclGetPos(l, &b->TextX, &b->TextY);
859 		} else if (!strcmp(value, "TextAlign")) {
860 			value = LuaToString(l, -1);
861 			if (!strcmp(value, "Center")) {
862 				b->TextAlign = TextAlignCenter;
863 			} else if (!strcmp(value, "Right")) {
864 				b->TextAlign = TextAlignRight;
865 			} else if (!strcmp(value, "Left")) {
866 				b->TextAlign = TextAlignLeft;
867 			} else {
868 				LuaError(l, "Invalid text alignment: %s" _C_ value);
869 			}
870 		} else if (!strcmp(value, "Default")) {
871 			ParseButtonStyleProperties(l, &b->Default);
872 		} else if (!strcmp(value, "Hover")) {
873 			ParseButtonStyleProperties(l, &b->Hover);
874 		} else if (!strcmp(value, "Clicked")) {
875 			ParseButtonStyleProperties(l, &b->Clicked);
876 		} else {
877 			LuaError(l, "Unsupported tag: %s" _C_ value);
878 		}
879 		lua_pop(l, 1);
880 	}
881 
882 	if (b->Default.TextPos.x == 0xFFFFFF) {
883 		b->Default.TextPos.x = b->TextX;
884 		b->Default.TextPos.y = b->TextY;
885 	}
886 	if (b->Hover.TextPos.x == 0xFFFFFF) {
887 		b->Hover.TextPos.x = b->TextX;
888 		b->Hover.TextPos.y = b->TextY;
889 	}
890 	if (b->Clicked.TextPos.x == 0xFFFFFF) {
891 		b->Clicked.TextPos.x = b->TextX;
892 		b->Clicked.TextPos.y = b->TextY;
893 	}
894 
895 	if (b->Default.TextAlign == TextAlignUndefined) {
896 		b->Default.TextAlign = b->TextAlign;
897 	}
898 	if (b->Hover.TextAlign == TextAlignUndefined) {
899 		b->Hover.TextAlign = b->TextAlign;
900 	}
901 	if (b->Clicked.TextAlign == TextAlignUndefined) {
902 		b->Clicked.TextAlign = b->TextAlign;
903 	}
904 	return 0;
905 }
906 
907 /**
908 **  Add a Lua handler
909 **  FIXME: when should these be freed?
910 */
AddHandler(lua_State * l)911 int AddHandler(lua_State *l)
912 {
913 	lua_getglobal(l, "_handlers_");
914 	if (lua_isnil(l, -1)) {
915 		lua_pop(l, 1);
916 		lua_newtable(l);
917 		lua_setglobal(l, "_handlers_");
918 		lua_getglobal(l, "_handlers_");
919 	}
920 	lua_pushvalue(l, -2);
921 	lua_rawseti(l, -2, HandleCount);
922 	lua_pop(l, 1);
923 
924 	return HandleCount++;
925 }
926 
927 /**
928 **  Call a Lua handler
929 */
CallHandler(unsigned int handle,int value)930 void CallHandler(unsigned int handle, int value)
931 {
932 	lua_getglobal(Lua, "_handlers_");
933 	lua_rawgeti(Lua, -1, handle);
934 	lua_pushnumber(Lua, value);
935 	LuaCall(1, 1);
936 	lua_pop(Lua, 1);
937 }
938 
939 /**
940 **  Define a button.
941 **
942 **  @param l  Lua state.
943 */
CclDefineButton(lua_State * l)944 static int CclDefineButton(lua_State *l)
945 {
946 	LuaCheckArgs(l, 1);
947 	if (!lua_istable(l, 1)) {
948 		LuaError(l, "incorrect argument");
949 	}
950 	ButtonAction ba;
951 
952 	//
953 	// Parse the arguments
954 	//
955 	lua_pushnil(l);
956 	while (lua_next(l, 1)) {
957 		const char *value = LuaToString(l, -2);
958 		if (!strcmp(value, "Pos")) {
959 			ba.Pos = LuaToNumber(l, -1);
960 		} else if (!strcmp(value, "Level")) {
961 			ba.Level = CButtonLevel::GetButtonLevel(LuaToString(l, -1));
962 		} else if (!strcmp(value, "AlwaysShow")) {
963 			ba.AlwaysShow = LuaToBoolean(l, -1);
964 		} else if (!strcmp(value, "Icon")) {
965 			ba.Icon.Name = LuaToString(l, -1);
966 		} else if (!strcmp(value, "Action")) {
967 			value = LuaToString(l, -1);
968 			int button_action_id = GetButtonActionIdByName(std::string(value));
969 			if (button_action_id != -1) {
970 				ba.Action = ButtonCmd(button_action_id);
971 			} else {
972 				LuaError(l, "Unsupported button action: %s" _C_ value);
973 			}
974 			//Wyrmgus end
975 		} else if (!strcmp(value, "Value")) {
976 			if (!lua_isnumber(l, -1) && !lua_isstring(l, -1) && !lua_isfunction(l, -1)) {
977 				LuaError(l, "incorrect argument");
978 			}
979 			if (lua_isfunction(l, -1)) {
980 				ba.Payload = new LuaCallback(l, -1);
981 			} else {
982 				char buf[64];
983 				const char *s2;
984 
985 				if (lua_isnumber(l, -1)) {
986 					snprintf(buf, sizeof(buf), "%ld", (long int)lua_tonumber(l, -1));
987 					s2 = buf;
988 				} else {
989 					s2 = lua_tostring(l, -1);
990 				}
991 				ba.ValueStr = s2;
992 			}
993 		} else if (!strcmp(value, "Allowed")) {
994 			value = LuaToString(l, -1);
995 			if (!strcmp(value, "check-true")) {
996 				ba.Allowed = ButtonCheckTrue;
997 			} else if (!strcmp(value, "check-false")) {
998 				ba.Allowed = ButtonCheckFalse;
999 			} else if (!strcmp(value, "check-upgrade")) {
1000 				ba.Allowed = ButtonCheckUpgrade;
1001 			} else if (!strcmp(value, "check-upgrade-not")) {
1002 				ba.Allowed = ButtonCheckUpgradeNot;
1003 			} else if (!strcmp(value, "check-upgrade-or")) {
1004 				ba.Allowed = ButtonCheckUpgradeOr;
1005 			} else if (!strcmp(value, "check-individual-upgrade")) {
1006 				ba.Allowed = ButtonCheckIndividualUpgrade;
1007 			} else if (!strcmp(value, "check-individual-upgrade-or")) {
1008 				ba.Allowed = ButtonCheckIndividualUpgradeOr;
1009 			} else if (!strcmp(value, "check-unit-variable")) {
1010 				ba.Allowed = ButtonCheckUnitVariable;
1011 			} else if (!strcmp(value, "check-units-or")) {
1012 				ba.Allowed = ButtonCheckUnitsOr;
1013 			} else if (!strcmp(value, "check-units-and")) {
1014 				ba.Allowed = ButtonCheckUnitsAnd;
1015 			} else if (!strcmp(value, "check-units-not")) {
1016 				ba.Allowed = ButtonCheckUnitsNot;
1017 			} else if (!strcmp(value, "check-network")) {
1018 				ba.Allowed = ButtonCheckNetwork;
1019 			} else if (!strcmp(value, "check-no-network")) {
1020 				ba.Allowed = ButtonCheckNoNetwork;
1021 			} else if (!strcmp(value, "check-no-work")) {
1022 				ba.Allowed = ButtonCheckNoWork;
1023 			} else if (!strcmp(value, "check-no-research")) {
1024 				ba.Allowed = ButtonCheckNoResearch;
1025 			} else if (!strcmp(value, "check-attack")) {
1026 				ba.Allowed = ButtonCheckAttack;
1027 			} else if (!strcmp(value, "check-upgrade-to")) {
1028 				ba.Allowed = ButtonCheckUpgradeTo;
1029 			} else if (!strcmp(value, "check-research")) {
1030 				ba.Allowed = ButtonCheckResearch;
1031 			} else if (!strcmp(value, "check-single-research")) {
1032 				ba.Allowed = ButtonCheckSingleResearch;
1033 			} else if (!strcmp(value, "check-has-inventory")) {
1034 				ba.Allowed = ButtonCheckHasInventory;
1035 			} else if (!strcmp(value, "check-has-sub-buttons")) {
1036 				ba.Allowed = ButtonCheckHasSubButtons;
1037 			} else {
1038 				LuaError(l, "Unsupported action: %s" _C_ value);
1039 			}
1040 		} else if (!strcmp(value, "AllowArg")) {
1041 			if (!lua_istable(l, -1)) {
1042 				LuaError(l, "incorrect argument");
1043 			}
1044 			std::string allowstr;
1045 			const unsigned int subargs = lua_rawlen(l, -1);
1046 
1047 			for (unsigned int k = 0; k < subargs; ++k) {
1048 				const char *s2 = LuaToString(l, -1, k + 1);
1049 				allowstr += s2;
1050 				if (k != subargs - 1) {
1051 					allowstr += ",";
1052 				}
1053 			}
1054 			ba.AllowStr = allowstr;
1055 		} else if (!strcmp(value, "Key")) {
1056 			std::string key(LuaToString(l, -1));
1057 			ba.Key = GetHotKey(key);
1058 		} else if (!strcmp(value, "Hint")) {
1059 			ba.Hint = LuaToString(l, -1);
1060 		} else if (!strcmp(value, "Description")) {
1061 			ba.Description = LuaToString(l, -1);
1062 		} else if (!strcmp(value, "CommentSound")) {
1063 			ba.CommentSound.Name = LuaToString(l, -1);
1064 		} else if (!strcmp(value, "ButtonCursor")) {
1065 			ba.ButtonCursor = LuaToString(l, -1);
1066 		} else if (!strcmp(value, "Popup")) {
1067 			ba.Popup = LuaToString(l, -1);
1068 		} else if (!strcmp(value, "ForUnit")) {
1069 			if (!lua_istable(l, -1)) {
1070 				LuaError(l, "incorrect argument");
1071 			}
1072 			// FIXME: ba.UnitMask shouldn't be a string
1073 			std::string umask = ",";
1074 			const unsigned subargs = lua_rawlen(l, -1);
1075 			for (unsigned int k = 0; k < subargs; ++k) {
1076 				const char *s2 = LuaToString(l, -1, k + 1);
1077 				umask += s2;
1078 				umask += ",";
1079 			}
1080 			ba.UnitMask = umask;
1081 			if (!strncmp(ba.UnitMask.c_str(), ",*,", 3)) {
1082 				ba.UnitMask = "*";
1083 			}
1084 		//Wyrmgus start
1085 		} else if (!strcmp(value, "Mod")) {
1086 			ba.Mod = LuaToString(l, -1);
1087 		//Wyrmgus end
1088 		} else {
1089 			LuaError(l, "Unsupported tag: %s" _C_ value);
1090 		}
1091 		lua_pop(l, 1);
1092 	}
1093 	AddButton(ba.Pos, ba.Level, ba.Icon.Name, ba.Action, ba.ValueStr, ba.Payload,
1094 			  ba.Allowed, ba.AllowStr, ba.Key, ba.Hint, ba.Description, ba.CommentSound.Name,
1095 			  //Wyrmgus start
1096 //			  ba.ButtonCursor, ba.UnitMask, ba.Popup, ba.AlwaysShow);
1097 			  ba.ButtonCursor, ba.UnitMask, ba.Popup, ba.AlwaysShow, ba.Mod);
1098 			  //Wyrmgus end
1099 	return 0;
1100 }
1101 
1102 /**
1103 **  Run the set-selection-changed-hook.
1104 */
SelectionChanged()1105 void SelectionChanged()
1106 {
1107 	// We Changed out selection, anything pending buttonwise must be cleared
1108 	UI.StatusLine.Clear();
1109 	UI.StatusLine.ClearCosts();
1110 	CurrentButtonLevel = nullptr;
1111 	LastDrawnButtonPopup = nullptr;
1112 
1113 	UI.ButtonPanel.Update();
1114 	GameCursor = UI.Point.Cursor;
1115 	CursorBuilding = nullptr;
1116 	CursorState = CursorStatePoint;
1117 	UI.ButtonPanel.Update();
1118 }
1119 
1120 /**
1121 **  The selected unit has been altered.
1122 */
SelectedUnitChanged()1123 void SelectedUnitChanged()
1124 {
1125 	UI.ButtonPanel.Update();
1126 }
1127 
1128 /**
1129 **  Set selection style.
1130 **
1131 **  @param l  Lua state.
1132 */
CclSetSelectionStyle(lua_State * l)1133 static int CclSetSelectionStyle(lua_State *l)
1134 {
1135 	LuaCheckArgs(l, 1);
1136 
1137 	const char *style = LuaToString(l, 1);
1138 	if (!strcmp(style, "rectangle")) {
1139 		DrawSelection = DrawSelectionRectangle;
1140 	} else if (!strcmp(style, "alpha-rectangle")) {
1141 		DrawSelection = DrawSelectionRectangleWithTrans;
1142 	} else if (!strcmp(style, "circle")) {
1143 		DrawSelection = DrawSelectionCircle;
1144 	} else if (!strcmp(style, "alpha-circle")) {
1145 		DrawSelection = DrawSelectionCircleWithTrans;
1146 	} else if (!strcmp(style, "corners")) {
1147 		DrawSelection = DrawSelectionCorners;
1148 	} else {
1149 		LuaError(l, "Unsupported selection style");
1150 	}
1151 	return 0;
1152 }
1153 
1154 /**
1155 **  Add a new message.
1156 **
1157 **  @param l  Lua state.
1158 */
CclAddMessage(lua_State * l)1159 static int CclAddMessage(lua_State *l)
1160 {
1161 	LuaCheckArgs(l, 1);
1162 	SetMessage("%s", LuaToString(l, 1));
1163 	return 0;
1164 }
1165 
1166 //Wyrmgus start
1167 /**
1168 **  Add a new objective.
1169 **
1170 **  @param l  Lua state.
1171 */
CclAddObjective(lua_State * l)1172 static int CclAddObjective(lua_State *l)
1173 {
1174 	LuaCheckArgs(l, 1);
1175 	SetObjective("%s", LuaToString(l, 1));
1176 	return 0;
1177 }
1178 
1179 /**
1180 **  Clean objectives.
1181 **
1182 **  @param l  Lua state.
1183 */
CclClearObjectives(lua_State * l)1184 static int CclClearObjectives(lua_State *l)
1185 {
1186 	LuaCheckArgs(l, 0);
1187 	CleanObjectives();
1188 	return 0;
1189 }
1190 //Wyrmgus end
1191 
1192 /**
1193 **  Set the keys which are use for grouping units, helpful for other keyboards
1194 **
1195 **  @param l  Lua state.
1196 */
CclSetGroupKeys(lua_State * l)1197 static int CclSetGroupKeys(lua_State *l)
1198 {
1199 	LuaCheckArgs(l, 1);
1200 	UiGroupKeys = LuaToString(l, 1);
1201 	return 0;
1202 }
1203 
1204 /**
1205 ** Set basic map caracteristics.
1206 **
1207 **  @param l  Lua state.
1208 */
CclPresentMap(lua_State * l)1209 static int CclPresentMap(lua_State *l)
1210 {
1211 	//Wyrmgus start
1212 	/*
1213 	LuaCheckArgs(l, 5);
1214 
1215 	Map.Info.Description = LuaToString(l, 1);
1216 	// Number of players in LuaToNumber(l, 3); // Not used yet.
1217 	Map.Info.MapWidth = LuaToNumber(l, 3);
1218 	Map.Info.MapHeight = LuaToNumber(l, 4);
1219 	Map.Info.MapUID = LuaToNumber(l, 5);
1220 	*/
1221 
1222 	Map.Info.Description = LuaToString(l, 1);
1223 
1224 	if (lua_gettop(l) > 1) {
1225 		LuaCheckArgs(l, 5);
1226 
1227 		// Number of players in LuaToNumber(l, 3); // Not used yet.
1228 		Map.Info.MapWidth = LuaToNumber(l, 3);
1229 		Map.Info.MapHeight = LuaToNumber(l, 4);
1230 		Map.Info.MapUID = LuaToNumber(l, 5);
1231 	}
1232 	//Wyrmgus end
1233 
1234 	return 0;
1235 }
1236 
1237 /**
1238 ** Define the lua file that will build the map
1239 **
1240 **  @param l  Lua state.
1241 */
CclDefineMapSetup(lua_State * l)1242 static int CclDefineMapSetup(lua_State *l)
1243 {
1244 	LuaCheckArgs(l, 1);
1245 	Map.Info.Filename = LuaToString(l, 1);
1246 
1247 	return 0;
1248 }
1249 
1250 //Wyrmgus start
CclGetIcons(lua_State * l)1251 static int CclGetIcons(lua_State *l)
1252 {
1253 	std::vector<std::string> icons;
1254 	for (IconMap::iterator it = Icons.begin(); it != Icons.end(); ++it) {
1255 		icons.push_back(it->first);
1256 	}
1257 
1258 	lua_createtable(l, icons.size(), 0);
1259 	for (size_t i = 1; i <= icons.size(); ++i)
1260 	{
1261 		lua_pushstring(l, icons[i-1].c_str());
1262 		lua_rawseti(l, -2, i);
1263 	}
1264 	return 1;
1265 }
1266 //Wyrmgus end
1267 
1268 /**
1269 **  Register CCL features for UI.
1270 */
UserInterfaceCclRegister()1271 void UserInterfaceCclRegister()
1272 {
1273 	CursorCclRegister();
1274 	lua_register(Lua, "AddMessage", CclAddMessage);
1275 	//Wyrmgus start
1276 	lua_register(Lua, "AddObjective", CclAddObjective);
1277 	lua_register(Lua, "ClearObjectives", CclClearObjectives);
1278 	//Wyrmgus end
1279 
1280 	lua_register(Lua, "SetKeyScrollSpeed", CclSetKeyScrollSpeed);
1281 	lua_register(Lua, "GetKeyScrollSpeed", CclGetKeyScrollSpeed);
1282 	lua_register(Lua, "SetMouseScrollSpeed", CclSetMouseScrollSpeed);
1283 	lua_register(Lua, "GetMouseScrollSpeed", CclGetMouseScrollSpeed);
1284 	lua_register(Lua, "SetMouseScrollSpeedDefault", CclSetMouseScrollSpeedDefault);
1285 	lua_register(Lua, "GetMouseScrollSpeedDefault", CclGetMouseScrollSpeedDefault);
1286 	lua_register(Lua, "SetMouseScrollSpeedControl", CclSetMouseScrollSpeedControl);
1287 	lua_register(Lua, "GetMouseScrollSpeedControl", CclGetMouseScrollSpeedControl);
1288 
1289 	lua_register(Lua, "SetClickMissile", CclSetClickMissile);
1290 	lua_register(Lua, "SetDamageMissile", CclSetDamageMissile);
1291 
1292 	lua_register(Lua, "SetMaxOpenGLTexture", CclSetMaxOpenGLTexture);
1293 	lua_register(Lua, "SetUseTextureCompression", CclSetUseTextureCompression);
1294 	lua_register(Lua, "SetUseOpenGL", CclSetUseOpenGL);
1295 	lua_register(Lua, "SetZoomNoResize", CclSetZoomNoResize);
1296 	lua_register(Lua, "SetVideoResolution", CclSetVideoResolution);
1297 	lua_register(Lua, "GetVideoResolution", CclGetVideoResolution);
1298 	lua_register(Lua, "SetVideoFullScreen", CclSetVideoFullScreen);
1299 	lua_register(Lua, "GetVideoFullScreen", CclGetVideoFullScreen);
1300 
1301 	lua_register(Lua, "SetTitleScreens", CclSetTitleScreens);
1302 
1303 	lua_register(Lua, "DefinePanelContents", CclDefinePanelContents);
1304 	lua_register(Lua, "DefinePopup", CclDefinePopup);
1305 	lua_register(Lua, "DefineViewports", CclDefineViewports);
1306 
1307 	lua_register(Lua, "RightButtonAttacks", CclRightButtonAttacks);
1308 	lua_register(Lua, "RightButtonMoves", CclRightButtonMoves);
1309 	lua_register(Lua, "SetFancyBuildings", CclSetFancyBuildings);
1310 
1311 	lua_register(Lua, "DefineButton", CclDefineButton);
1312 
1313 	lua_register(Lua, "DefineButtonStyle", CclDefineButtonStyle);
1314 
1315 	lua_register(Lua, "PresentMap", CclPresentMap);
1316 	lua_register(Lua, "DefineMapSetup", CclDefineMapSetup);
1317 
1318 	//
1319 	// Look and feel of units
1320 	//
1321 	lua_register(Lua, "SetSelectionStyle", CclSetSelectionStyle);
1322 
1323 	lua_register(Lua, "SetGroupKeys", CclSetGroupKeys);
1324 
1325 	//Wyrmgus start
1326 	lua_register(Lua, "GetIcons", CclGetIcons);
1327 	//Wyrmgus end
1328 }
1329 
1330 //@}
1331