1 /*-------------------------------------------------------------------------------
2 
3 	BARONY
4 	File: editor.cpp
5 	Desc: main code for the level editor
6 
7 	Copyright 2013-2016 (c) Turning Wheel LLC, all rights reserved.
8 	See LICENSE for details.
9 
10 -------------------------------------------------------------------------------*/
11 
12 #include "main.hpp"
13 #include "draw.hpp"
14 #include "editor.hpp"
15 #include "entity.hpp"
16 #include "items.hpp"
17 #include "player.hpp"
18 #include "interface/interface.hpp"
19 #include "files.hpp"
20 #include "init.hpp"
21 #include <sys/stat.h>
22 #define EDITOR
23 
24 #ifdef STEAMWORKS
25 #include <steam/steam_api.h>
26 #include "steam.hpp"
27 #endif // STEAMWORKS
28 
29 
30 //#include "player.hpp"
31 
32 Entity* selectedEntity = nullptr;
33 Entity* lastSelectedEntity = nullptr;
34 Sint32 mousex = 0, mousey = 0;
35 Sint32 omousex = 0, omousey = 0;
36 Sint32 mousexrel = 0, mouseyrel = 0;
37 int itemSelect = 0;
38 int itemSlotSelected = -1;
39 char itemName[128];
40 bool splitscreen = false; //Unused variable, for game only.
41 real_t prev_x = 0;
42 real_t prev_y = 0;
43 bool duplicatedSprite = false;
44 int game = 0;
45 // function prototypes
46 Uint32 timerCallback(Uint32 interval, void* param);
47 void handleEvents(void);
48 void mainLogic(void);
49 std::vector<Entity*> groupedEntities;
50 bool moveSelectionNegativeX = false;
51 bool moveSelectionNegativeY = false;
52 std::vector<std::string> mapNames;
53 std::list<std::string> modFolderNames;
54 std::string physfs_saveDirectory = BASE_DATA_DIR;
55 std::string physfs_openDirectory = BASE_DATA_DIR;
56 float limbs[NUMMONSTERS][20][3]; // dummy variable for files.cpp limbs reloading in Barony.
buttonStartSingleplayer(button_t * my)57 void buttonStartSingleplayer(button_t* my) {} // dummy function for mod_tools.cpp
steamStatisticUpdate(int statisticNum,ESteamStatTypes type,int value)58 void steamStatisticUpdate(int statisticNum, ESteamStatTypes type, int value) {} // dummy function for mod_tools.cpp
59 AchievementObserver achievementObserver; // dummy function for mod_tools.cpp
initClass(int i)60 void initClass(int i) {} // dummy function for mod_tools.cpp
updateGlobalStat(int index,int value)61 void AchievementObserver::updateGlobalStat(int index, int value) {}
62 std::vector<std::pair<SDL_Surface**, std::string>> systemResourceImages; // dummy variable for files.cpp system resource reloading in Barony.
initMenuOptions()63 void initMenuOptions() {} // dummy
64 int textInsertCaratPosition = -1;
65 GenericGUIMenu GenericGUI;
66 Item* selectedItem = nullptr; //Because it won't compile without this.
67 
68 map_t copymap;
69 
70 int errorMessage = 0;
71 int errorArr[12] =
72 {
73 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
74 };
75 
76 char monsterPropertyNames[14][16] =
77 {
78 	"Name:",
79 	"MAX HP:",
80 	"HP:",
81 	"MAX MP:",
82 	"MP:",
83 	"LEVEL:",
84 	"GOLD:",
85 	"STR:",
86 	"DEX:",
87 	"CON:",
88 	"INT:",
89 	"PER:",
90 	"CHR:",
91 	"Is NPC:"
92 };
93 
94 char chestPropertyNames[3][40] =
95 {
96 	"Orientation: (0-3)",
97 	"Chest Type: (0-7)",
98 	"Locked Chance: (0-100%)"
99 };
100 
101 char summonTrapPropertyNames[6][44] =
102 {
103 	"Monster To Spawn: (-1 to 32)",
104 	"Quantity Per Spawn: (1-9)",
105 	"Time Between Spawns: (1-999s)",
106 	"Amount of Spawn Instances: (1-99)",
107 	"Requires Power to Disable: (0-1)",
108 	"Chance to Stop Working Each Spawn: (0-100%)"
109 };
110 
111 char itemPropertyNames[6][36] =
112 {
113 	"Item ID: (1-255)",
114 	"Status: (0-5)",
115 	"Blessing: (-9 to +9)",
116 	"Quantity: (1-99)",
117 	"Identified: (0-2)",
118 	"Category: (0-16, if random_item)"
119 };
120 
121 char itemCategoryNames[17][32] =
122 {
123 	"random",
124 	"weapon",
125 	"armor",
126 	"amulet",
127 	"potion",
128 	"scroll",
129 	"magicstaff",
130 	"ring",
131 	"spellbook",
132 	"gem",
133 	"thrown",
134 	"tool",
135 	"food",
136 	"book",
137 	"equipment",
138 	"jewelry",
139 	"magical"
140 };
141 
142 char powerCrystalPropertyNames[4][39] =
143 {
144 	"Orientation: (0-3)",
145 	"Powered Distance (0-99)",
146 	"Rotation Direction: (0-1)",
147 	"Require Unlock Spell to Activate (0-1)"
148 };
149 
150 char monsterItemPropertyNames[7][36] =
151 {
152 	"Item ID: (0-255)",
153 	"Status: (0-5)",
154 	"Blessing: (-9 to +9)",
155 	"Quantity: (1-99)",
156 	"Identified: (0-2)",
157 	"Chance (1-100)",
158 	"Category: (0-16, if default_random)"
159 };
160 
161 char leverTimerPropertyNames[1][26] =
162 {
163 	"Powered Duration (1-999s)"
164 };
165 
166 char boulderTrapPropertyNames[3][42] =
167 {
168 	"Amount of times to re-fire (-1 - 99)",
169 	"Delay between re-fire (2-999s)",
170 	"Pre-delay for first time trigger (0-999s)"
171 };
172 
173 char pedestalPropertyNames[5][35] =
174 {
175 	"Orb Type (0-3)",
176 	"Pre-loaded with Orb (0-1)",
177 	"Inverted power generation (0-1)",
178 	"Pedestal start beneath ground(0-1)",
179 	"Lock orb when placed(0-1)"
180 };
181 
182 char teleporterPropertyNames[3][25] =
183 {
184 	"X Coordinate to teleport",
185 	"Y Coordinate to teleport",
186 	"Type of sprite (0-2)"
187 };
188 
189 char ceilingTilePropertyNames[1][30] =
190 {
191 	"Model texture to use (0-9999)"
192 };
193 
194 char spellTrapPropertyNames[5][38] =
195 {
196 	"Spell Type: (-1 - 9)",
197 	"Amount of times to refire (-1 - 99)",
198 	"Power once to continuously fire (0-1)",
199 	"Ceiling model to use (0-9999)",
200 	"Trap refire rate (1-999s)",
201 };
202 
203 char furniturePropertyNames[1][19] =
204 {
205 	"Direction (-1 - 7)"
206 };
207 
208 char floorDecorationPropertyNames[9][59] =
209 {
210 	"Model texture to use (0-9999)",
211 	"Direction (-1 - 7)",
212 	"Height Offset (Qtrs of a voxel, +ive is higher)",
213 	"X Offset (L/R, Qtrs of a voxel, +ive is right)",
214 	"Y Offset (U/D, Qtrs of a voxel, +ive is down)",
215 	"Interact Text",
216 	"",
217 	"",
218 	""
219 };
220 
221 char soundSourcePropertyNames[5][59] =
222 {
223 	"Sound source line number to play from sounds.txt (0-999)",
224 	"Volume (0-255)",
225 	"Play once only (0-1)",
226 	"Activation delay (0-9999 ticks, 50 ticks / sec)",
227 	"Sound origin (0 = this entity, 1 = global)"
228 };
229 
230 char lightSourcePropertyNames[7][48] =
231 {
232 	"Light always on (0-1)",
233 	"Brightness (0-255)",
234 	"Invert power (0-1)",
235 	"Light/unlight once only (0-1)",
236 	"Tile radius of light source (0-64)",
237 	"Light flicker enable (0-1)",
238 	"Activation delay (0-9999 ticks, 50 ticks / sec)"
239 };
240 
241 char textSourcePropertyNames[10][45] =
242 {
243 	"Color (R, G, B) (0-255):",
244 	"",
245 	"",
246 	"Text:",
247 	"",
248 	"",
249 	"",
250 	"",
251 	"Message delay (0-9999 ticks, 50 ticks / sec)",
252 	"Send message once only (0 - 1)"
253 };
254 
255 char customPortalPropertyNames[7][54] =
256 {
257 	"Model texture to use (0-9999)",
258 	"Animation frames (0-9)",
259 	"Model Height Offset (Qtrs of a voxel, +ive is higher)",
260 	"Levels to advance (-99 - 99)",
261 	"Level name to jump to (Can be used with above option)",
262 	"Requires power to be visible (0-1)",
263 	"Exit toggle between secret levels file (0-1)"
264 };
265 
266 char signalTimerPropertyNames[5][55] =
267 {
268 	"Input signal direction (0 - 3)",
269 	"Output activation delay (0-9999 ticks, 50 ticks / sec)",
270 	"Output pulse time (0 - 9999 ticks, 50 ticks / sec)",
271 	"Output repeat count (0 - 9999)",
272 	"Latch input and keep powered (0 - 1)"
273 };
274 
275 char tablePropertyNames[3][34] =
276 {
277 	"Direction (-1 - 7)",
278 	"Spawn chairs (-1 - 4)",
279 	"Spawn item on table % (-1 - 100)",
280 };
281 
282 char readableBookPropertyNames[4][32] =
283 {
284 	"Status: (0-5)",
285 	"Blessing: (-9 to +9)",
286 	"Identified: (0-2)",
287 	"Book Title:"
288 };
289 
290 char doorPropertyNames[3][42] =
291 {
292 	"Force Door Locked/Unlocked (0-2)",
293 	"Disable unlocking with lockpick (0-1)",
294 	"Disable unlocking with spell (0-1)"
295 };
296 
297 char gatePropertyNames[1][35] =
298 {
299 	"Disable unlocking with spell (0-1)"
300 };
301 
302 char playerSpawnPropertyNames[1][35] =
303 {
304 	"Spawn Facing Direction (-1 - 7)"
305 };
306 
playerClassLangEntry(int classnum,int playernum)307 const char* playerClassLangEntry(int classnum, int playernum)
308 {
309 	if ( classnum >= CLASS_BARBARIAN && classnum <= CLASS_JOKER )
310 	{
311 		return language[1900 + classnum];
312 	}
313 	else if ( classnum >= CLASS_CONJURER )
314 	{
315 		return language[3223 + classnum - CLASS_CONJURER];
316 	}
317 	else if ( classnum >= CLASS_SEXTON && classnum <= CLASS_MONK )
318 	{
319 		return language[2550 + classnum - CLASS_SEXTON];
320 	}
321 	else
322 	{
323 		return "undefined classname";
324 	}
325 }
326 
327 /*-------------------------------------------------------------------------------
328 
329 mouseInBounds
330 
331 Returns true if the mouse is within the rectangle specified, otherwise
332 returns false
333 
334 -------------------------------------------------------------------------------*/
335 
mouseInBounds(int x1,int x2,int y1,int y2)336 bool mouseInBounds(int x1, int x2, int y1, int y2)
337 {
338 	if ( omousey >= y1 && omousey < y2 )
339 		if ( omousex >= x1 && omousex < x2 )
340 		{
341 			return true;
342 		}
343 
344 	return false;
345 }
346 
347 int recentUsedTiles[9][9] = { 0 };
348 int recentUsedTilePalette = 0;
349 int lockTilePalette[9] = { 0 };
350 int lastPaletteTileSelected = 0;
351 
closeNetworkInterfaces()352 void closeNetworkInterfaces()
353 {
354 	//Because Dennis.
355 }
356 
357 /*-------------------------------------------------------------------------------
358 
359 	mainLogic
360 
361 	handles time dependent procedures
362 
363 -------------------------------------------------------------------------------*/
364 
365 view_t camera_vel;
366 view_t camera;
367 
mainLogic(void)368 void mainLogic(void)
369 {
370 	// messages
371 	if ( messagetime > 0 )
372 	{
373 		messagetime--;
374 	}
375 
376 	if ( errorMessage > 0 )
377 	{
378 		errorMessage--;
379 		if ( errorMessage == 0 )
380 		{
381 			for ( int i = 0; i < sizeof(errorArr) / sizeof(int); i++ )
382 				errorArr[i] = 0;
383 		}
384 	}
385 
386 
387 	// basic editing functions are not available under these cases
388 	if ( subwindow || tilepalette || spritepalette )
389 	{
390 		return;
391 	}
392 
393 	// scroll camera on minimap
394 	if ( mousestatus[SDL_BUTTON_LEFT] && toolbox )
395 	{
396 		if ( omousex >= xres - 120 && omousex < xres - 8 )
397 		{
398 			if ( omousey >= 24 && omousey < 136 )
399 			{
400 				camx = ((long)map.width << TEXTUREPOWER) * (real_t)(mousex - xres + 120) / 112 - xres / 2;
401 				camy = ((long)map.height << TEXTUREPOWER) * (real_t)(mousey - 24) / 112 - yres / 2;
402 			}
403 		}
404 	}
405 	camx -= camx % TEXTURESIZE; // make sure the camera is a multiple of 32 for hover text to work.
406 	camy -= camy % TEXTURESIZE; // make sure the camera is a multiple of 32 for hover text to work.
407 
408 	// basic editor functions
409 	if ( mode3d == false )
410 	{
411 		camx += (keystatus[SDL_SCANCODE_RIGHT] - keystatus[SDL_SCANCODE_LEFT]) * TEXTURESIZE;
412 		camy += (keystatus[SDL_SCANCODE_DOWN] - keystatus[SDL_SCANCODE_UP]) * TEXTURESIZE;
413 	}
414 	else
415 	{
416 		// camera velocity
417 		camera_vel.x += cos(camera.ang) * (keystatus[SDL_SCANCODE_UP] - keystatus[SDL_SCANCODE_DOWN]) * .05;
418 		camera_vel.y += sin(camera.ang) * (keystatus[SDL_SCANCODE_UP] - keystatus[SDL_SCANCODE_DOWN]) * .05;
419 		camera_vel.z += (keystatus[SDL_SCANCODE_PAGEDOWN] - keystatus[SDL_SCANCODE_PAGEUP]) * .25;
420 		camera_vel.ang += (keystatus[SDL_SCANCODE_RIGHT] - keystatus[SDL_SCANCODE_LEFT]) * .04;
421 
422 		// camera position
423 		camera.x += camera_vel.x;
424 		camera.y += camera_vel.y;
425 		camera.z += camera_vel.z;
426 		camera.ang += camera_vel.ang;
427 		while ( camera.ang >= PI * 2 )
428 		{
429 			camera.ang -= PI * 2;
430 		}
431 		while ( camera.ang < 0 )
432 		{
433 			camera.ang += PI * 2;
434 		}
435 
436 		// friction
437 		camera_vel.x *= .65;
438 		camera_vel.y *= .65;
439 		camera_vel.z *= .65;
440 		camera_vel.ang *= .5;
441 	}
442 	if ( camx < -xres / 2 )
443 	{
444 		camx = -xres / 2;
445 	}
446 	if ( camx > ((long)map.width << TEXTUREPOWER) - ((long)xres / 2) )
447 	{
448 		camx = ((long)map.width << TEXTUREPOWER) - ((long)xres / 2);
449 	}
450 	if ( camy < -yres / 2 )
451 	{
452 		camy = -yres / 2;
453 	}
454 	if ( camy > ((long)map.height << TEXTUREPOWER) - ((long)yres / 2) )
455 	{
456 		camy = ((long)map.height << TEXTUREPOWER) - ((long)yres / 2);
457 	}
458 
459 	if (scroll < 0 )   // mousewheel up
460 	{
461 		if ( keystatus[SDL_SCANCODE_LCTRL] || keystatus[SDL_SCANCODE_RCTRL] )
462 		{
463 			recentUsedTilePalette++; //scroll through palettes 1-9
464 			if ( recentUsedTilePalette == 9 )
465 			{
466 				recentUsedTilePalette = 0;
467 			}
468 		}
469 		else if ( keystatus[SDL_SCANCODE_LSHIFT] || keystatus[SDL_SCANCODE_RSHIFT] )
470 		{
471 			drawlayer = std::min(drawlayer + 1, MAPLAYERS - 1);
472 		}
473 		else
474 		{
475 			lastPaletteTileSelected++; //scroll through tiles 1-9
476 			if ( lastPaletteTileSelected == 9 )
477 			{
478 				lastPaletteTileSelected = 0;
479 			}
480 			selectedTile = selectedTile = recentUsedTiles[recentUsedTilePalette][lastPaletteTileSelected];
481 		}
482 		scroll = 0;
483 	}
484 	if (scroll > 0 )   // mousewheel down
485 	{
486 		if ( keystatus[SDL_SCANCODE_LCTRL] || keystatus[SDL_SCANCODE_RCTRL] )
487 		{
488 			recentUsedTilePalette--; //scroll through palettes 1-9
489 			if ( recentUsedTilePalette == -1 )
490 			{
491 				recentUsedTilePalette = 8;
492 			}
493 		}
494 		else if ( keystatus[SDL_SCANCODE_LSHIFT] || keystatus[SDL_SCANCODE_RSHIFT] )
495 		{
496 			drawlayer = std::max(drawlayer - 1, 0);
497 		}
498 		else
499 		{
500 			lastPaletteTileSelected--; //scroll through tiles 1-9
501 			if ( lastPaletteTileSelected == -1 )
502 			{
503 				lastPaletteTileSelected = 8;
504 			}
505 			selectedTile = selectedTile = recentUsedTiles[recentUsedTilePalette][lastPaletteTileSelected];
506 
507 		}
508 		scroll = 0;
509 	}
510 
511 	switch ( drawlayer )
512 	{
513 		case 0:
514 			strcpy(layerstatus, "FLOOR");
515 			break;
516 		case 1:
517 			strcpy(layerstatus, "WALLS");
518 			break;
519 		case 2:
520 			strcpy(layerstatus, "CEILING");
521 			break;
522 		default:
523 			strcpy(layerstatus, "UNKNOWN");
524 			break;
525 	}
526 }
527 
528 /*-------------------------------------------------------------------------------
529 
530 	handleButtons
531 
532 	Draws buttons and processes clicks
533 
534 -------------------------------------------------------------------------------*/
535 
handleButtons(void)536 void handleButtons(void)
537 {
538 	node_t* node;
539 	node_t* nextnode;
540 	button_t* button;
541 	int w, h;
542 
543 	// handle buttons
544 	for ( node = button_l.first; node != NULL; node = nextnode )
545 	{
546 		nextnode = node->next;
547 		button = (button_t*)node->element;
548 		if ( !subwindow && button->focused )
549 		{
550 			list_RemoveNode(button->node);
551 			continue;
552 		}
553 		if ( button->visible == 0 )
554 		{
555 			continue;    // invisible buttons are not processed
556 		}
557 		w = strlen(button->label) * 8;
558 		h = 8;
559 		if ( subwindow && !button->focused )
560 		{
561 			// unfocused buttons do not work when a subwindow is active
562 			drawWindow(button->x, button->y, button->x + button->sizex, button->y + button->sizey);
563 			printText(font8x8_bmp, button->x + (button->sizex - w) / 2, button->y + (button->sizey - h) / 2, button->label);
564 		}
565 		else
566 		{
567 			if ( omousex >= button->x && omousex < button->x + button->sizex )
568 			{
569 				if ( omousey >= button->y && omousey < button->y + button->sizey )
570 				{
571 					if ( button == butFile && menuVisible )
572 					{
573 						menuVisible = 1;
574 					}
575 					if ( button == butEdit && menuVisible )
576 					{
577 						menuVisible = 2;
578 					}
579 					if ( button == butView && menuVisible )
580 					{
581 						menuVisible = 3;
582 					}
583 					if ( button == butMap && menuVisible )
584 					{
585 						menuVisible = 4;
586 					}
587 					if ( button == butHelp && menuVisible )
588 					{
589 						menuVisible = 5;
590 					}
591 					if ( mousestatus[SDL_BUTTON_LEFT] )
592 					{
593 						button->pressed = true;
594 					}
595 				}
596 			}
597 			if ( button->pressed )
598 			{
599 				if ( omousex >= button->x && omousex < button->x + button->sizex && mousex >= button->x && mousex < button->x + button->sizex )
600 				{
601 					if ( omousey >= button->y && omousey < button->y + button->sizey && mousey >= button->y && mousey < button->y + button->sizey )
602 					{
603 						drawDepressed(button->x, button->y, button->x + button->sizex, button->y + button->sizey);
604 						printText(font8x8_bmp, button->x + (button->sizex - w) / 2, button->y + (button->sizey - h) / 2, button->label);
605 						if ( !mousestatus[SDL_BUTTON_LEFT] )   // releasing the mouse over the button
606 						{
607 							button->pressed = false;
608 							if ( button->action != NULL )
609 							{
610 								(*button->action)(button); // run the button's assigned action
611 								if ( !subwindow && button->focused )
612 								{
613 									list_RemoveNode(button->node);
614 								}
615 							}
616 						}
617 					}
618 					else
619 					{
620 						drawWindow(button->x, button->y, button->x + button->sizex, button->y + button->sizey);
621 						printText(font8x8_bmp, button->x + (button->sizex - w) / 2, button->y + (button->sizey - h) / 2, button->label);
622 						if ( !mousestatus[SDL_BUTTON_LEFT] )   // releasing the mouse over nothing
623 						{
624 							button->pressed = false;
625 						}
626 					}
627 				}
628 				else
629 				{
630 					drawWindow(button->x, button->y, button->x + button->sizex, button->y + button->sizey);
631 					printText(font8x8_bmp, button->x + (button->sizex - w) / 2, button->y + (button->sizey - h) / 2, button->label);
632 					if ( !mousestatus[SDL_BUTTON_LEFT] )   // releasing the mouse over nothing
633 					{
634 						button->pressed = false;
635 					}
636 				}
637 			}
638 			else
639 			{
640 				if ( (button != butFile || menuVisible != 1) && (button != butEdit || menuVisible != 2) && (button != butView || menuVisible != 3) && (button != butMap || menuVisible != 4) && (button != butHelp || menuVisible != 5) )
641 				{
642 					drawWindow(button->x, button->y, button->x + button->sizex, button->y + button->sizey);
643 					printText(font8x8_bmp, button->x + (button->sizex - w) / 2, button->y + (button->sizey - h) / 2, button->label);
644 				}
645 				else
646 				{
647 					drawDepressed(button->x, button->y, button->x + button->sizex, button->y + button->sizey);
648 					printText(font8x8_bmp, button->x + (button->sizex - w) / 2, button->y + (button->sizey - h) / 2, button->label);
649 				}
650 			}
651 		}
652 	}
653 }
654 
655 /*-------------------------------------------------------------------------------
656 
657 	handleEvents
658 
659 	Handles all SDL events; receives input, updates gamestate, etc.
660 
661 -------------------------------------------------------------------------------*/
662 
handleEvents(void)663 void handleEvents(void)
664 {
665 	real_t d;
666 	int j;
667 
668 	// calculate app rate
669 	t = clock();
670 	timesync = t - ot;
671 	ot = t;
672 
673 	// calculate fps
674 	if ( timesync != 0 )
675 	{
676 		frameval[cycles & (AVERAGEFRAMES - 1)] = 1.0 / timesync;
677 	}
678 	else
679 	{
680 		frameval[cycles & (AVERAGEFRAMES - 1)] = 1.0;
681 	}
682 	d = frameval[0];
683 	for (j = 1; j < AVERAGEFRAMES; j++)
684 	{
685 		d += frameval[j];
686 	}
687 	fps = d / AVERAGEFRAMES * 1000;
688 
689 	while ( SDL_PollEvent(&event) )   // poll SDL events
690 	{
691 		// Global events
692 		switch ( event.type )
693 		{
694 			case SDL_QUIT: // if SDL receives the shutdown signal
695 				buttonExit(NULL);
696 				break;
697 			case SDL_KEYDOWN: // if a key is pressed...
698 				if ( SDL_IsTextInputActive() )
699 				{
700 #ifdef APPLE
701 					if ( (event.key.keysym.sym == SDLK_DELETE || event.key.keysym.sym == SDLK_BACKSPACE) && strlen(inputstr) > 0 )
702 					{
703 						inputstr[strlen(inputstr) - 1] = 0;
704 						cursorflash = ticks;
705 					}
706 #else
707 					if ( event.key.keysym.sym == SDLK_BACKSPACE && strlen(inputstr) > 0 )
708 					{
709 						if ( textInsertCaratPosition >= 0 && newwindow == 20 && textInsertCaratPosition != strlen(inputstr) )
710 						{
711 							if ( textInsertCaratPosition != 0 )
712 							{
713 								std::string tmp = inputstr;
714 								tmp.erase(textInsertCaratPosition - 1, 1);
715 								strcpy(inputstr, tmp.c_str());
716 								textInsertCaratPosition = std::max(textInsertCaratPosition - 1, 0);
717 							}
718 						}
719 						else
720 						{
721 							inputstr[strlen(inputstr) - 1] = 0;
722 						}
723 						cursorflash = ticks;
724 					}
725 					else if ( event.key.keysym.sym == SDLK_BACKQUOTE && strlen(inputstr) > 0 )
726 					{
727 						if ( textInsertCaratPosition >= 0 && newwindow == 20 && textInsertCaratPosition != strlen(inputstr) )
728 						{
729 							if ( textInsertCaratPosition != 0 )
730 							{
731 								std::string tmp = inputstr;
732 								tmp.erase(textInsertCaratPosition - 1, 1);
733 								strcpy(inputstr, tmp.c_str());
734 								textInsertCaratPosition = std::max(textInsertCaratPosition - 1, 0);
735 							}
736 						}
737 						else
738 						{
739 							inputstr[strlen(inputstr) - 1] = 0;
740 						}
741 						cursorflash = ticks;
742 					}
743 #endif
744 					else if ( event.key.keysym.sym == SDLK_c && SDL_GetModState()&KMOD_CTRL )
745 					{
746 						SDL_SetClipboardText(inputstr);
747 						cursorflash = ticks;
748 					}
749 					else if ( event.key.keysym.sym == SDLK_v && SDL_GetModState()&KMOD_CTRL )
750 					{
751 						strncpy(inputstr, SDL_GetClipboardText(), inputlen);
752 						cursorflash = ticks;
753 					}
754 				}
755 				lastkeypressed = event.key.keysym.sym;
756 				keystatus[event.key.keysym.scancode] = 1; // set this key's index to 1
757 				break;
758 			case SDL_KEYUP: // if a key is unpressed...
759 				keystatus[event.key.keysym.scancode] = 0; // set this key's index to 0
760 				break;
761 			case SDL_TEXTINPUT:
762 				if ( (event.text.text[0] != 'c' && event.text.text[0] != 'C') || !(SDL_GetModState()&KMOD_CTRL) )
763 				{
764 					if ( (event.text.text[0] != 'v' && event.text.text[0] != 'V') || !(SDL_GetModState()&KMOD_CTRL) )
765 					{
766 						if ( event.text.text[0] != '`' )
767 						{
768 							if ( textInsertCaratPosition >= 0 && newwindow == 20 )
769 							{
770 								if ( textInsertCaratPosition == strlen(inputstr) )
771 								{
772 									strncat(inputstr, event.text.text, std::max<size_t>(0, inputlen - strlen(inputstr)));
773 									textInsertCaratPosition = std::min((int)strlen(inputstr), textInsertCaratPosition + 1);
774 								}
775 								else if ( inputlen - ((int)strlen(inputstr) + 1) >= 0)
776 								{
777 									std::string tmp = inputstr;
778 									tmp.insert(textInsertCaratPosition, event.text.text);
779 									strcpy(inputstr, tmp.c_str());
780 									textInsertCaratPosition = std::min((int)strlen(inputstr), textInsertCaratPosition + 1);
781 								}
782 							}
783 							else
784 							{
785 								strncat(inputstr, event.text.text, std::max<size_t>(0, inputlen - strlen(inputstr)));
786 							}
787 							cursorflash = ticks;
788 						}
789 					}
790 				}
791 				break;
792 			case SDL_MOUSEMOTION: // if the mouse is moved...
793 				mousex = event.motion.x;
794 				mousey = event.motion.y;
795 				mousexrel = event.motion.xrel;
796 				mouseyrel = event.motion.yrel;
797 				break;
798 			case SDL_MOUSEBUTTONDOWN: // if a mouse button is pressed...
799 				mousestatus[event.button.button] = 1; // set this mouse button to 1
800 				break;
801 			case SDL_MOUSEBUTTONUP: // if a mouse button is released...
802 				mousestatus[event.button.button] = 0; // set this mouse button to 0
803 				break;
804 			case SDL_MOUSEWHEEL:
805 				if ( event.wheel.y > 0 )
806 				{
807 					mousestatus[SDL_BUTTON_WHEELUP] = 1;
808 				}
809 				else if ( event.wheel.y < 0 )
810 				{
811 					mousestatus[SDL_BUTTON_WHEELDOWN] = 1;
812 				}
813 				if (mousestatus[4])
814 				{
815 					scroll = 1;
816 				}
817 				else if (mousestatus[5])
818 				{
819 					scroll = -1;
820 				}
821 				mousestatus[SDL_BUTTON_WHEELUP] = 0;
822 				mousestatus[SDL_BUTTON_WHEELDOWN] = 0;
823 				break;
824 			case SDL_USEREVENT: // if the game timer elapses
825 				mainLogic();
826 				mousexrel = 0;
827 				mouseyrel = 0;
828 				break;
829 			case SDL_WINDOWEVENT: // if the window is resized
830 				if ( event.window.event == SDL_WINDOWEVENT_RESIZED )
831 				{
832 					if (fullscreen || ticks == 0)
833 					{
834 						break;
835 					}
836 					xres = std::max(event.window.data1, 100);
837 					yres = std::max(event.window.data2, 75);
838 					if ( zbuffer != NULL )
839 					{
840 						free(zbuffer);
841 					}
842 					zbuffer = (real_t*) malloc(sizeof(real_t) * xres * yres);
843 					if ( clickmap != NULL )
844 					{
845 						free(clickmap);
846 					}
847 					clickmap = (Entity**) malloc(sizeof(Entity*)*xres * yres);
848 					if (palette != NULL)
849 					{
850 						free(palette);
851 					}
852 					palette = (int*) malloc(sizeof(unsigned int) * xres * yres);
853 					if ( !changeVideoMode() )
854 					{
855 						printlog("critical error! Attempting to abort safely...\n");
856 						mainloop = 0;
857 					}
858 				}
859 				break;
860 		}
861 	}
862 	if (!mousestatus[SDL_BUTTON_LEFT])
863 	{
864 		omousex = mousex;
865 		omousey = mousey;
866 		ocamx = camx;
867 		ocamy = camy;
868 	}
869 }
870 
871 /*-------------------------------------------------------------------------------
872 
873 	timerCallback
874 
875 	A callback function for the game timer which pushes an SDL event
876 
877 -------------------------------------------------------------------------------*/
878 
timerCallback(Uint32 interval,void * param)879 Uint32 timerCallback(Uint32 interval, void* param)
880 {
881 	SDL_Event event;
882 	SDL_UserEvent userevent;
883 
884 	userevent.type = SDL_USEREVENT;
885 	userevent.code = 0;
886 	userevent.data1 = NULL;
887 	userevent.data2 = NULL;
888 
889 	event.type = SDL_USEREVENT;
890 	event.user = userevent;
891 
892 	ticks++;
893 	SDL_PushEvent(&event);
894 	return (interval);
895 }
896 
897 /*-------------------------------------------------------------------------------
898 
899 	editFill
900 
901 	Fills a region of the map with a certain tile
902 
903 -------------------------------------------------------------------------------*/
904 
editFill(int x,int y,int layer,int type)905 void editFill(int x, int y, int layer, int type)
906 {
907 	int repeat = 1;
908 	int fillspot;
909 
910 	if ( type == map.tiles[layer + y * MAPLAYERS + x * MAPLAYERS * map.height] )
911 	{
912 		return;
913 	}
914 
915 	fillspot = map.tiles[layer + y * MAPLAYERS + x * MAPLAYERS * map.height];
916 	map.tiles[layer + y * MAPLAYERS + x * MAPLAYERS * map.height] = type + numtiles;
917 
918 	while ( repeat )
919 	{
920 		repeat = 0;
921 		for ( x = 0; x < map.width; x++ )
922 		{
923 			for ( y = 0; y < map.height; y++ )
924 			{
925 				if ( map.tiles[layer + y * MAPLAYERS + x * MAPLAYERS * map.height] == type + numtiles )
926 				{
927 					if ( x < map.width - 1 )
928 					{
929 						if ( map.tiles[layer + y * MAPLAYERS + (x + 1)*MAPLAYERS * map.height] == fillspot )
930 						{
931 							map.tiles[layer + y * MAPLAYERS + (x + 1)*MAPLAYERS * map.height] = type + numtiles;
932 							repeat = 1;
933 						}
934 					}
935 					if ( x > 0 )
936 					{
937 						if ( map.tiles[layer + y * MAPLAYERS + (x - 1)*MAPLAYERS * map.height] == fillspot )
938 						{
939 							map.tiles[layer + y * MAPLAYERS + (x - 1)*MAPLAYERS * map.height] = type + numtiles;
940 							repeat = 1;
941 						}
942 					}
943 					if ( y < map.height - 1 )
944 					{
945 						if ( map.tiles[layer + (y + 1)*MAPLAYERS + x * MAPLAYERS * map.height] == fillspot )
946 						{
947 							map.tiles[layer + (y + 1)*MAPLAYERS + x * MAPLAYERS * map.height] = type + numtiles;
948 							repeat = 1;
949 						}
950 					}
951 					if ( y > 0 )
952 					{
953 						if ( map.tiles[layer + (y - 1)*MAPLAYERS + x * MAPLAYERS * map.height] == fillspot )
954 						{
955 							map.tiles[layer + (y - 1)*MAPLAYERS + x * MAPLAYERS * map.height] = type + numtiles;
956 							repeat = 1;
957 						}
958 					}
959 				}
960 			}
961 		}
962 	}
963 
964 	for ( x = 0; x < map.width; x++ )
965 	{
966 		for ( y = 0; y < map.height; y++ )
967 		{
968 			if ( map.tiles[layer + y * MAPLAYERS + x * MAPLAYERS * map.height] == type + numtiles )
969 			{
970 				map.tiles[layer + y * MAPLAYERS + x * MAPLAYERS * map.height] = type;
971 			}
972 		}
973 	}
974 }
975 
976 /*-------------------------------------------------------------------------------
977 
978 	makeUndo
979 
980 	adds an undomap to the undolist
981 
982 -------------------------------------------------------------------------------*/
983 
984 #define MAXUNDOS 10
985 
986 node_t* undospot = nullptr;
987 node_t* redospot = nullptr;
988 list_t undolist;
makeUndo()989 void makeUndo()
990 {
991 	node_t* node, *nextnode;
992 
993 	// eliminate any undo nodes beyond the one we are currently on
994 	if ( undospot != nullptr )
995 	{
996 		for ( node = undospot->next; node != nullptr; node = nextnode )
997 		{
998 			nextnode = node->next;
999 			list_RemoveNode(node);
1000 		}
1001 	}
1002 	else
1003 	{
1004 		if ( redospot )
1005 		{
1006 			list_FreeAll(&undolist);
1007 		}
1008 	}
1009 
1010 	// copy all the current map data
1011 	map_t* undomap = (map_t*) malloc(sizeof(map_t));
1012 	strcpy(undomap->author, map.author);
1013 	strcpy(undomap->name, map.name);
1014 	undomap->skybox = map.skybox;
1015 	undomap->width = map.width;
1016 	undomap->height = map.height;
1017 	for ( int c = 0; c < MAPFLAGS; c++ )
1018 	{
1019 		undomap->flags[c] = map.flags[c];
1020 	}
1021 	undomap->tiles = (Sint32*) malloc(sizeof(Sint32) * undomap->width * undomap->height * MAPLAYERS);
1022 	memcpy(undomap->tiles, map.tiles, sizeof(Sint32)*undomap->width * undomap->height * MAPLAYERS);
1023 	undomap->entities = (list_t*) malloc(sizeof(list_t));
1024 	undomap->entities->first = nullptr;
1025 	undomap->entities->last = nullptr;
1026 	undomap->creatures = nullptr;
1027 	for ( node = map.entities->first; node != nullptr; node = node->next )
1028 	{
1029 		Entity* entity = newEntity(((Entity*)node->element)->sprite, 1, undomap->entities, nullptr);
1030 
1031 		setSpriteAttributes(entity, (Entity*)node->element, (Entity*)node->element);
1032 	}
1033 
1034 	// add the new node to the undo list
1035 	node = list_AddNodeLast(&undolist);
1036 	node->element = undomap;
1037 	node->deconstructor = &mapDeconstructor;
1038 	if ( list_Size(&undolist) > MAXUNDOS + 1 )
1039 	{
1040 		list_RemoveNode(undolist.first);
1041 	}
1042 	undospot = node;
1043 	redospot = nullptr;
1044 }
1045 
clearUndos()1046 void clearUndos()
1047 {
1048 	list_FreeAll(&undolist);
1049 	undospot = nullptr;
1050 	redospot = nullptr;
1051 }
1052 
1053 /*-------------------------------------------------------------------------------
1054 
1055 	undo() / redo()
1056 
1057 	self explanatory
1058 
1059 -------------------------------------------------------------------------------*/
1060 
undo()1061 void undo()
1062 {
1063 	node_t* node;
1064 	if ( undospot == NULL )
1065 	{
1066 		return;
1067 	}
1068 	selectedEntity = NULL;
1069 	if ( undospot == undolist.last )
1070 	{
1071 		node_t* tempnode = undospot;
1072 		makeUndo();
1073 		undospot = tempnode;
1074 	}
1075 	free(map.tiles);
1076 	map_t* undomap = (map_t*)undospot->element;
1077 	map.width = undomap->width;
1078 	map.height = undomap->height;
1079 	map.tiles = (Sint32*) malloc(sizeof(Sint32) * map.width * map.height * MAPLAYERS);
1080 	memcpy(map.tiles, undomap->tiles, sizeof(Sint32)*undomap->width * undomap->height * MAPLAYERS);
1081 	list_FreeAll(map.entities);
1082 	for ( node = undomap->entities->first; node != NULL; node = node->next )
1083 	{
1084 		Entity* entity = newEntity(((Entity*)node->element)->sprite, 1, map.entities, nullptr);
1085 
1086 		setSpriteAttributes(entity, (Entity*)node->element, (Entity*)node->element);
1087 	}
1088 	if ( redospot != NULL )
1089 	{
1090 		redospot = redospot->prev;
1091 	}
1092 	else
1093 	{
1094 		redospot = undospot->next;
1095 	}
1096 	undospot = undospot->prev;
1097 }
1098 
redo()1099 void redo()
1100 {
1101 	node_t* node;
1102 
1103 	if ( redospot == NULL )
1104 	{
1105 		return;
1106 	}
1107 	selectedEntity = NULL;
1108 	free(map.tiles);
1109 	map_t* undomap = (map_t*)redospot->element;
1110 	map.width = undomap->width;
1111 	map.height = undomap->height;
1112 	map.tiles = (Sint32*) malloc(sizeof(Sint32) * map.width * map.height * MAPLAYERS);
1113 	memcpy(map.tiles, undomap->tiles, sizeof(Sint32)*undomap->width * undomap->height * MAPLAYERS);
1114 	list_FreeAll(map.entities);
1115 	for ( node = undomap->entities->first; node != NULL; node = node->next )
1116 	{
1117 		Entity* entity = newEntity(((Entity*)node->element)->sprite, 1, map.entities, nullptr);
1118 
1119 		setSpriteAttributes(entity, (Entity*)node->element, (Entity*)node->element);
1120 	}
1121 	if ( undospot != NULL )
1122 	{
1123 		undospot = undospot->next;
1124 	}
1125 	else
1126 	{
1127 		undospot = redospot->prev;
1128 	}
1129 	redospot = redospot->next;
1130 }
1131 
processCommandLine(int argc,char ** argv)1132 void processCommandLine(int argc, char** argv)
1133 {
1134 	int c = 0;
1135 	size_t datadirsz = std::min(sizeof(datadir) - 1, strlen(BASE_DATA_DIR));
1136 	strncpy(datadir, BASE_DATA_DIR, datadirsz);
1137 	datadir[datadirsz] = '\0';
1138 	if ( argc > 1 )
1139 	{
1140 		for ( c = 1; c < argc; c++ )
1141 		{
1142 			if ( argv[c] != nullptr )
1143 			{
1144 				if ( !strncmp(argv[c], "-map=", 5) )
1145 				{
1146 					strcpy(maptoload, argv[c] + 5);
1147 					loadingmap = true;
1148 				}
1149 				else if (!strncmp(argv[c], "-datadir=", 9))
1150 				{
1151 					datadirsz = std::min(sizeof(datadir) - 1, strlen(argv[c] + 9));
1152 					strncpy(datadir, argv[c] + 9, datadirsz);
1153 					datadir[datadirsz] = '\0';
1154 				}
1155 			}
1156 		}
1157 	}
1158 	printlog("Data path is %s", datadir);
1159 }
1160 
1161 /*-------------------------------------------------------------------------------
1162 
1163 loadTilePalettes
1164 
1165 loads the tile palette file for the editor.
1166 
1167 -------------------------------------------------------------------------------*/
1168 
loadTilePalettes()1169 int loadTilePalettes()
1170 {
1171 	char filename[128] = { 0 };
1172 	FILE* fp;
1173 	int c;
1174 
1175 	// open log file
1176 	if ( !logfile )
1177 	{
1178 		openLogFile();
1179 	}
1180 
1181 	// compose filename
1182 	strcpy(filename, "editor/tilepalettes.txt");
1183 
1184 	// check if palette file is valid
1185 	if ( !dataPathExists(filename) )
1186 	{
1187 		// palette file doesn't exist
1188 		printlog("error: unable to locate tile palette file: '%s'", filename);
1189 		return 1;
1190 	}
1191 
1192 	// open palette file
1193 	if ( (fp = openDataFile(filename, "r")) == NULL )
1194 	{
1195 		printlog("error: unable to load tile palette file: '%s'", filename);
1196 		return 1;
1197 	}
1198 
1199 	// read file
1200 	int paletteNumber = 0;
1201 	int paletteTile = 0;
1202 	bool lockValueEntry = 0;
1203 	for (; !feof(fp); )
1204 	{
1205 		//printlog( "loading line %d...\n", line);
1206 		char data[1024];
1207 
1208 		// read line from file
1209 		int i;
1210 		bool fileEnd = false;
1211 		for ( i = 0; ; i++ )
1212 		{
1213 			data[i] = fgetc(fp);
1214 			if ( feof(fp) )
1215 			{
1216 				fileEnd = true;
1217 				break;
1218 			}
1219 
1220 			// blank or comment lines stop reading at a newline
1221 			if ( data[i] == '\n' )
1222 			{
1223 				break;
1224 			}
1225 		}
1226 
1227 		if ( fileEnd )
1228 		{
1229 			break;
1230 		}
1231 
1232 		// skip blank and comment lines
1233 		if ( data[0] == '\n' || data[0] == '#' )
1234 		{
1235 			continue;
1236 		}
1237 
1238 		// process line
1239 		if ( !lockValueEntry )
1240 		{
1241 			recentUsedTiles[paletteNumber][paletteTile] = atoi(data);
1242 			//printlog("read tile number '%d', pattern '%d', data '%d' \n", paletteTile, paletteNumber, atoi(data));
1243 			++paletteTile;
1244 			if ( paletteTile == 9 )
1245 			{
1246 				paletteTile = 0;
1247 				paletteNumber++;
1248 				lockValueEntry = true;
1249 			}
1250 		}
1251 		else
1252 		{
1253 			lockTilePalette[paletteNumber - 1] = atoi(data);
1254 			//printlog("read lock value for palette '%d', data '%d' \n", paletteNumber - 1, atoi(data));
1255 			lockValueEntry = false;
1256 		}
1257 	}
1258 
1259 	// close file
1260 	fclose(fp);
1261 	printlog("successfully loaded tile palette file '%s'\n", filename);
1262 	return 0;
1263 }
1264 
1265 /*-------------------------------------------------------------------------------
1266 
1267 saveTilePalettes()
1268 
1269 saves the tile palette file for the editor.
1270 
1271 -------------------------------------------------------------------------------*/
1272 
saveTilePalettes()1273 int saveTilePalettes()
1274 {
1275 	char filename[128] = { 0 };
1276 	FILE* fp;
1277 	int c;
1278 
1279 	// open log file
1280 	if ( !logfile )
1281 	{
1282 		openLogFile();
1283 	}
1284 
1285 	// compose filename
1286 	strcpy(filename, "editor/tilepalettes.txt");
1287 
1288 	// check if palette file is valid
1289 	if ( !dataPathExists(filename) )
1290 	{
1291 		// palette file doesn't exist
1292 		printlog("error: unable to locate existing tile palette file: '%s'...\ncreating...", filename);
1293 	}
1294 
1295 	// open/create palette file
1296 	if ( (fp = openDataFile(filename, "w")) == NULL )
1297 	{
1298 		printlog("error: unable to save or create tile palette file: '%s'", filename);
1299 		return 1;
1300 	}
1301 
1302 	// write file
1303 	Uint32 line;
1304 	int paletteNumber = 0;
1305 	int paletteTile = 0;
1306 	bool lockValueEntry = 0;
1307 	char data[128];
1308 
1309 	fputs("# Tile palette file\n", fp);
1310 	fputs("# lines beginning with pound character are a comment\n", fp);
1311 	fputs("# blank lines are ignored\n", fp);
1312 	fputs("", fp);
1313 
1314 	for ( paletteNumber = 0; paletteNumber < 9; paletteNumber++ )
1315 	{
1316 		paletteTile = 0;
1317 		snprintf(data, sizeof(data), "# palette %d tiles\n", paletteNumber + 1);
1318 		fputs(data, fp);
1319 		fputs("\n", fp);
1320 		for ( paletteTile = 0; paletteTile < 9; paletteTile++ )
1321 		{
1322 			if ( paletteTile == 3 || paletteTile == 6 )
1323 			{
1324 				fputs("\n", fp);
1325 			}
1326 			snprintf(data, sizeof(data), "%d\n", recentUsedTiles[paletteNumber][paletteTile]);
1327 			fputs(data, fp);
1328 		}
1329 		fputs("\n", fp);
1330 		snprintf(data, sizeof(data), "# palette %d locked (1) or unlocked (0)\n", paletteNumber + 1);
1331 		fputs(data, fp);
1332 		fputs("\n", fp);
1333 		snprintf(data, sizeof(data), "%d\n", lockTilePalette[paletteNumber]);
1334 		fputs(data, fp);
1335 		fputs("\n", fp);
1336 	}
1337 
1338 	fputs("# end\n", fp);
1339 
1340 	// close file
1341 	fclose(fp);
1342 	printlog("saved tile palette file '%s'\n", filename);
1343 	return 0;
1344 }
1345 
1346 /*-------------------------------------------------------------------------------
1347 
1348 updateRecentTileList
1349 
1350 Updates the tile palette in the editor if not locked, takes tile as input and either
1351 inserts into an empty slot, or shifts the palette to accomodate.
1352 
1353 -------------------------------------------------------------------------------*/
1354 
updateRecentTileList(int tile)1355 void updateRecentTileList(int tile)
1356 {
1357 	int checkEmpty = -1;
1358 
1359 	for ( int i = 0; i < 9; i++ )
1360 	{
1361 		if ( recentUsedTiles[recentUsedTilePalette][i] == tile )
1362 		{
1363 			lastPaletteTileSelected = i;
1364 			return; // tile exists in recent list.
1365 		}
1366 
1367 		if ( recentUsedTiles[recentUsedTilePalette][i] == 0 && checkEmpty == -1 )
1368 		{
1369 			checkEmpty = i; // index of next empty tile.
1370 			lastPaletteTileSelected = checkEmpty;
1371 		}
1372 	}
1373 
1374 	if ( lockTilePalette[recentUsedTilePalette] == 1 )
1375 	{
1376 		return; // palette locked, don't change.
1377 	}
1378 
1379 	if ( checkEmpty == -1 )
1380 	{
1381 		for ( int j = 8; j > 0; j-- )
1382 		{
1383 			recentUsedTiles[recentUsedTilePalette][j] = recentUsedTiles[recentUsedTilePalette][j - 1]; // shift array by 1 to insert new tile as the array is full.
1384 		}
1385 		recentUsedTiles[recentUsedTilePalette][0] = tile; // insert tile into array.
1386 		lastPaletteTileSelected = 0;
1387 	}
1388 	else
1389 	{
1390 		recentUsedTiles[recentUsedTilePalette][checkEmpty] = tile; // insert tile into array.
1391 	}
1392 
1393 	return;
1394 }
1395 
1396 /*-------------------------------------------------------------------------------
1397 
1398 	main
1399 
1400 	Initializes program resources, harbors main loop, and cleans up
1401 	afterwords
1402 
1403 -------------------------------------------------------------------------------*/
1404 
1405 bool selectingspace = false;
1406 int selectedarea_x1, selectedarea_x2;
1407 int selectedarea_y1, selectedarea_y2;
1408 bool selectedarea = false;
1409 bool pasting = false;
1410 
1411 #ifdef APPLE
1412 #include <mach-o/dyld.h> //For _NSGetExecutablePath()
1413 #endif
1414 
main(int argc,char ** argv)1415 int main(int argc, char** argv)
1416 {
1417 #ifdef APPLE
1418 	uint32_t buffsize = 4096;
1419 	char binarypath[buffsize];
1420 	int result = _NSGetExecutablePath(binarypath, &buffsize);
1421 	if (result == 0)   //It worked.
1422 	{
1423 		printlog( "Binary path: %s\n", binarypath);
1424 		char* last = strrchr(binarypath, '/');
1425 		*last = '\0';
1426 		char execpath[buffsize];
1427 		strcpy(execpath, binarypath);
1428 		//char* last = strrchr(execpath, '/');
1429 		//strcat(execpath, '/');
1430 		//strcat(execpath, "/../../../");
1431 		printlog( "Chrooting to directory: %s\n", execpath);
1432 		chdir(execpath);
1433 		///Users/ciprian/barony/barony-sdl2-take2/barony.app/Contents/MacOS/barony
1434 		chdir("..");
1435 		chdir("..");
1436 		chdir("..");
1437 		chdir("barony.app/Contents/Resources");
1438 		//chdir("..");
1439 	}
1440 	else
1441 	{
1442 		printlog( "Failed to get binary path. Program may not work correctly!\n");
1443 	}
1444 #endif
1445 	button_t* button;
1446 	node_t* node;
1447 	node_t* nextnode;
1448 	Entity* entity;
1449 	SDL_Rect pos;
1450 	int c;
1451 	int x, y, z;
1452 	int x2, y2;
1453 	//char action[32];
1454 	int oslidery = 0;
1455 	light_t* light = nullptr;
1456 	bool savedundo = false;
1457 	smoothlighting = true;
1458 
1459 	Stat* spriteStats = nullptr;
1460 
1461 	processCommandLine(argc, argv);
1462 
1463 #ifdef WINDOWS
1464 	strcpy(outputdir, "./");
1465 #else
1466 	char *basepath = getenv("HOME");
1467 	snprintf(outputdir, sizeof(outputdir), "%s/.barony", basepath);
1468 	if ( access(outputdir, F_OK) == -1 )
1469 		mkdir(outputdir, 0777);
1470 #endif
1471 
1472 	// load default language file (english)
1473 	if ( loadLanguage("en") )
1474 	{
1475 		exit(1);
1476 	}
1477 
1478 	// initialize
1479 	useModelCache = true;
1480 	verticalSync = true;
1481 	if ( (x = initApp("Barony Editor", fullscreen)) )
1482 	{
1483 		printlog("Critical error: %d\n", x);
1484 #ifdef STEAMWORKS
1485 		SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Uh oh",
1486 								"Barony has encountered a critical error and cannot start.\n\n"
1487 								"Please check the log.txt file in the game directory for additional info\n"
1488 								"and verify Steam is running. Alternatively, contact us through our website\n"
1489 								"at http://www.baronygame.com/ for support.",
1490 								screen);
1491 #else
1492 		SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Uh oh",
1493 								"Barony has encountered a critical error and cannot start.\n\n"
1494 								"Please check the log.txt file in the game directory for additional info,\n"
1495 								"or contact us through our website at http://www.baronygame.com/ for support.",
1496 								screen);
1497 #endif
1498 		deinitApp();
1499 		exit(x);
1500 	}
1501 
1502 #ifdef STEAMWORKS
1503 	g_SteamStatistics->RequestStats();
1504 #endif // STEAMWORKS
1505 
1506 
1507 	copymap.tiles = nullptr;
1508 	copymap.entities = nullptr;
1509 	copymap.creatures = nullptr;
1510 	undolist.first = nullptr;
1511 	undolist.last = nullptr;
1512 
1513 	// Load Cursors
1514 	cursorArrow = SDL_GetCursor();
1515 	cursorPencil = newCursor(cursor_pencil);
1516 	cursorPoint = newCursor(cursor_point);
1517 	cursorBrush = newCursor(cursor_brush);
1518 	cursorSelect = cursorArrow;
1519 	cursorFill = newCursor(cursor_fill);
1520 
1521 	// instatiate a timer
1522 	timer = SDL_AddTimer(1000 / TICKS_PER_SECOND, timerCallback, NULL);
1523 	srand(time(nullptr));
1524 
1525 	// create an empty map
1526 	map.width = 32;
1527 	map.height = 24;
1528 	map.entities = (list_t*) malloc(sizeof(list_t));
1529 	map.creatures = nullptr;
1530 	map.entities->first = nullptr;
1531 	map.entities->last = nullptr;
1532 	map.tiles = (int*) malloc(sizeof(int) * map.width * map.height * MAPLAYERS);
1533 	strcpy(map.name, "");
1534 	strcpy(map.author, "");
1535 	map.skybox = 0;
1536 	for ( c = 0; c < MAPFLAGS; c++ )
1537 	{
1538 		map.flags[c] = 0;
1539 	}
1540 	for ( z = 0; z < MAPLAYERS; z++ )
1541 	{
1542 		for ( y = 0; y < map.height; y++ )
1543 		{
1544 			for ( x = 0; x < map.width; x++ )
1545 			{
1546 				if (z == OBSTACLELAYER)
1547 				{
1548 					if (x == 0 || y == 0 || x == map.width - 1 || y == map.height - 1)
1549 					{
1550 						map.tiles[z + y * MAPLAYERS + x * MAPLAYERS * map.height] = 2;
1551 					}
1552 					else
1553 					{
1554 						map.tiles[z + y * MAPLAYERS + x * MAPLAYERS * map.height] = 0;
1555 					}
1556 				}
1557 				else
1558 				{
1559 					map.tiles[z + y * MAPLAYERS + x * MAPLAYERS * map.height] = 1;
1560 				}
1561 			}
1562 		}
1563 	}
1564 	vismap = (bool*) malloc(sizeof(bool) * map.width * map.height);
1565 	lightmap = (int*)malloc(sizeof(Sint32) * map.width * map.height);
1566 	lightmapSmoothed = (int*)malloc(sizeof(Sint32) * map.width * map.height);
1567 	for ( c = 0; c < map.width * map.height; c++ )
1568 	{
1569 		lightmap[c] = 0;
1570 		lightmapSmoothed[c] = 0;
1571 	}
1572 
1573 	// initialize camera position
1574 	camera.x = 4;
1575 	camera.y = 4;
1576 	camera.z = 0;
1577 	camera.ang = 0;
1578 	camera.vang = 0;
1579 
1580 	// initialize editor settings
1581 	strcpy(layerstatus, "BACKGROUND");
1582 	palette = (int*) malloc(sizeof(unsigned int) * xres * yres);
1583 
1584 	// main interface
1585 	button = butFile = newButton();
1586 	strcpy(button->label, "File");
1587 	button->x = 0;
1588 	button->y = 0;
1589 	button->sizex = 40;
1590 	button->sizey = 16;
1591 	button->action = &buttonFile;
1592 
1593 	button = butEdit = newButton();
1594 	strcpy(button->label, "Edit");
1595 	button->x = 40;
1596 	button->y = 0;
1597 	button->sizex = 40;
1598 	button->sizey = 16;
1599 	button->action = &buttonEdit;
1600 
1601 	button = butView = newButton();
1602 	strcpy(button->label, "View");
1603 	button->x = 80;
1604 	button->y = 0;
1605 	button->sizex = 40;
1606 	button->sizey = 16;
1607 	button->action = &buttonView;
1608 
1609 	button = butMap = newButton();
1610 	strcpy(button->label, "Map");
1611 	button->x = 120;
1612 	button->y = 0;
1613 	button->sizex = 32;
1614 	button->sizey = 16;
1615 	button->action = &buttonMap;
1616 
1617 	button = butHelp = newButton();
1618 	strcpy(button->label, "Help");
1619 	button->x = 152;
1620 	button->y = 0;
1621 	button->sizex = 40;
1622 	button->sizey = 16;
1623 	button->action = &buttonHelp;
1624 
1625 	button = butX = newButton();
1626 	strcpy(button->label, "X");
1627 	button->x = xres - 16;
1628 	button->y = 0;
1629 	button->sizex = 16;
1630 	button->sizey = 16;
1631 	button->action = &buttonExit;
1632 	button->visible = 0;
1633 
1634 	button = but_ = newButton();
1635 	strcpy(button->label, "_");
1636 	button->x = xres - 32;
1637 	button->y = 0;
1638 	button->sizex = 16;
1639 	button->sizey = 16;
1640 	button->action = &buttonIconify;
1641 	button->visible = 0;
1642 
1643 	// toolbox
1644 	button = butTilePalette = newButton();
1645 	strcpy(button->label, "Palette ...");
1646 	button->x = xres - 112;
1647 	button->y = 152;
1648 	button->sizex = 96;
1649 	button->sizey = 16;
1650 	button->action = &buttonTilePalette;
1651 
1652 	button = butSprite = newButton();
1653 	strcpy(button->label, "Sprite  ...");
1654 	button->x = xres - 112;
1655 	button->y = 168;
1656 	button->sizex = 96;
1657 	button->sizey = 16;
1658 	button->action = &buttonSprite;
1659 
1660 	// Pencil Tool Button
1661 	button = butPencil = newButton();
1662 	strcpy(button->label, "Pencil");
1663 	button->x = xres - 96;
1664 	button->y = 204;
1665 	button->sizex = 64;
1666 	button->sizey = 16;
1667 	button->action = &buttonPencil;
1668 
1669 	// Point Tool Button
1670 	button = butPoint = newButton();
1671 	strcpy(button->label, "Point");
1672 	button->x = xres - 96;
1673 	button->y = 220;
1674 	button->sizex = 64;
1675 	button->sizey = 16;
1676 	button->action = &buttonPoint;
1677 
1678 	// Brush Tool Button
1679 	button = butBrush = newButton();
1680 	strcpy(button->label, "Brush");
1681 	button->x = xres - 96;
1682 	button->y = 236;
1683 	button->sizex = 64;
1684 	button->sizey = 16;
1685 	button->action = &buttonBrush;
1686 
1687 	// Select Tool Button
1688 	button = butSelect = newButton();
1689 	strcpy(button->label, "Select");
1690 	button->x = xres - 96;
1691 	button->y = 252;
1692 	button->sizex = 64;
1693 	button->sizey = 16;
1694 	button->action = &buttonSelect;
1695 
1696 	// Fill Tool Button
1697 	button = butFill = newButton();
1698 	strcpy(button->label, "Fill");
1699 	button->x = xres - 96;
1700 	button->y = 268;
1701 	button->sizex = 64;
1702 	button->sizey = 16;
1703 	button->action = &buttonFill;
1704 
1705 	// file menu
1706 	butNew = button = newButton();
1707 	strcpy(button->label, "New          Ctrl+N");
1708 	button->x = 16;
1709 	button->y = 16;
1710 	button->sizex = 160;
1711 	button->sizey = 16;
1712 	button->action = &buttonNew;
1713 	button->visible = 0;
1714 
1715 	butOpen = button = newButton();
1716 	strcpy(button->label, "Open ...     Ctrl+O");
1717 	button->x = 16;
1718 	button->y = 32;
1719 	button->sizex = 160;
1720 	button->sizey = 16;
1721 	button->action = &buttonOpen;
1722 	button->visible = 0;
1723 
1724 	butDir = button = newButton();
1725 	strcpy(button->label, "Directory... Ctrl+D");
1726 	button->x = 16;
1727 	button->y = 48;
1728 	button->sizex = 160;
1729 	button->sizey = 16;
1730 	button->action = &buttonOpenDirectory;
1731 	button->visible = 0;
1732 
1733 	butSave = button = newButton();
1734 	strcpy(button->label, "Save         Ctrl+S");
1735 	button->x = 16;
1736 	button->y = 64;
1737 	button->sizex = 160;
1738 	button->sizey = 16;
1739 	button->action = &buttonSave;
1740 	button->visible = 0;
1741 
1742 	butSaveAs = button = newButton();
1743 	strcpy(button->label, "Save As ...        ");
1744 	button->x = 16;
1745 	button->y = 80;
1746 	button->sizex = 160;
1747 	button->sizey = 16;
1748 	button->action = &buttonSaveAs;
1749 	button->visible = 0;
1750 
1751 	butExit = button = newButton();
1752 	strcpy(button->label, "Exit         Alt+F4");
1753 	button->x = 16;
1754 	button->y = 96;
1755 	button->sizex = 160;
1756 	button->sizey = 16;
1757 	button->action = &buttonExit;
1758 	button->visible = 0;
1759 
1760 	// edit menu
1761 	butCut = button = newButton();
1762 	strcpy(button->label, "Cut         Ctrl+X");
1763 	button->x = 56;
1764 	button->y = 16;
1765 	button->sizex = 152;
1766 	button->sizey = 16;
1767 	button->action = &buttonCut;
1768 	button->visible = 0;
1769 
1770 	butCopy = button = newButton();
1771 	strcpy(button->label, "Copy        Ctrl+C");
1772 	button->x = 56;
1773 	button->y = 32;
1774 	button->sizex = 152;
1775 	button->sizey = 16;
1776 	button->action = &buttonCopy;
1777 	button->visible = 0;
1778 
1779 	butPaste = button = newButton();
1780 	strcpy(button->label, "Paste       Ctrl+V");
1781 	button->x = 56;
1782 	button->y = 48;
1783 	button->sizex = 152;
1784 	button->sizey = 16;
1785 	button->action = &buttonPaste;
1786 	button->visible = 0;
1787 
1788 	butDelete = button = newButton();
1789 	strcpy(button->label, "Delete      Del   ");
1790 	button->x = 56;
1791 	button->y = 64;
1792 	button->sizex = 152;
1793 	button->sizey = 16;
1794 	button->action = &buttonDelete;
1795 	button->visible = 0;
1796 
1797 	butSelectAll = button = newButton();
1798 	strcpy(button->label, "Select All  Ctrl+A");
1799 	button->x = 56;
1800 	button->y = 80;
1801 	button->sizex = 152;
1802 	button->sizey = 16;
1803 	button->action = &buttonSelectAll;
1804 	button->visible = 0;
1805 
1806 	butUndo = button = newButton();
1807 	strcpy(button->label, "Undo        Ctrl+Z");
1808 	button->x = 56;
1809 	button->y = 96;
1810 	button->sizex = 152;
1811 	button->sizey = 16;
1812 	button->action = &buttonUndo;
1813 	button->visible = 0;
1814 
1815 	butRedo = button = newButton();
1816 	strcpy(button->label, "Redo        Ctrl+Y");
1817 	button->x = 56;
1818 	button->y = 112;
1819 	button->sizex = 152;
1820 	button->sizey = 16;
1821 	button->action = &buttonRedo;
1822 	button->visible = 0;
1823 
1824 	// view menu
1825 	butStatusBar = button = newButton();
1826 	strcpy(button->label, "Statusbar   Ctrl+I");
1827 	button->x = 96;
1828 	button->y = 16;
1829 	button->sizex = 152;
1830 	button->sizey = 16;
1831 	button->action = &buttonStatusBar;
1832 	button->visible = 0;
1833 
1834 	butToolbox = button = newButton();
1835 	strcpy(button->label, "Toolbox     Ctrl+T");
1836 	button->x = 96;
1837 	button->y = 32;
1838 	button->sizex = 152;
1839 	button->sizey = 16;
1840 	button->action = &buttonToolbox;
1841 	button->visible = 0;
1842 
1843 	butAllLayers = button = newButton();
1844 	strcpy(button->label, "All Layers  Ctrl+L");
1845 	button->x = 96;
1846 	button->y = 48;
1847 	button->sizex = 152;
1848 	button->sizey = 16;
1849 	button->action = &buttonAllLayers;
1850 	button->visible = 0;
1851 
1852 	butViewSprites = button = newButton();
1853 	strcpy(button->label, "Sprites     Ctrl+E");
1854 	button->x = 96;
1855 	button->y = 64;
1856 	button->sizex = 152;
1857 	button->sizey = 16;
1858 	button->action = &buttonViewSprites;
1859 	button->visible = 0;
1860 
1861 	butGrid = button = newButton();
1862 	strcpy(button->label, "Grid        Ctrl+G");
1863 	button->x = 96;
1864 	button->y = 80;
1865 	button->sizex = 152;
1866 	button->sizey = 16;
1867 	button->action = &buttonGrid;
1868 	button->visible = 0;
1869 
1870 	but3DMode = button = newButton();
1871 	strcpy(button->label, "3D Mode     Ctrl+F");
1872 	button->x = 96;
1873 	button->y = 96;
1874 	button->sizex = 152;
1875 	button->sizey = 16;
1876 	button->action = &button3DMode;
1877 	button->visible = 0;
1878 
1879 	butHoverText = button = newButton();
1880 	strcpy(button->label, "Hover Text  Ctrl+H");
1881 	button->x = 96;
1882 	button->y = 112;
1883 	button->sizex = 152;
1884 	button->sizey = 16;
1885 	button->action = &buttonHoverText;
1886 	button->visible = 0;
1887 
1888 	// map menu
1889 	butAttributes = button = newButton();
1890 	strcpy(button->label, "Attributes ...  Ctrl+M      ");
1891 	button->x = 136;
1892 	button->y = 16;
1893 	button->sizex = 232;
1894 	button->sizey = 16;
1895 	button->action = &buttonAttributes;
1896 	button->visible = 0;
1897 
1898 	butClearMap = button = newButton();
1899 	strcpy(button->label, "Clear Map       Ctrl+Shift+N");
1900 	button->x = 136;
1901 	button->y = 32;
1902 	button->sizex = 232;
1903 	button->sizey = 16;
1904 	button->action = &buttonClearMap;
1905 	button->visible = 0;
1906 
1907 	// help menu
1908 	butAbout = button = newButton();
1909 	strcpy(button->label, "About            F1");
1910 	button->x = 168;
1911 	button->y = 16;
1912 	button->sizex = 160;
1913 	button->sizey = 16;
1914 	button->action = &buttonAbout;
1915 	button->visible = 0;
1916 
1917 	// controls menu
1918 	butEditorControls = button = newButton();
1919 	strcpy(button->label, "Editor Help       H");
1920 	button->x = 168;
1921 	button->y = 32;
1922 	button->sizex = 160;
1923 	button->sizey = 16;
1924 	button->action = &buttonEditorControls;
1925 	button->visible = 0;
1926 
1927 	if ( loadingmap )
1928 	{
1929 		if ( loadMap(physfsFormatMapName(maptoload).c_str(), &map, map.entities, map.creatures) == -1 )
1930 		{
1931 			strcpy(message, "Failed to open ");
1932 			strcat(message, maptoload);
1933 		}
1934 		else
1935 		{
1936 			strcpy(filename, maptoload);
1937 		}
1938 	}
1939 
1940 	loadItems();
1941 	loadTilePalettes();
1942 
1943 	bool achievementCartographer = false;
1944 
1945 	// main loop
1946 	printlog( "running main loop.\n");
1947 	while (mainloop)
1948 	{
1949 		// game logic
1950 		handleEvents();
1951 
1952 #ifdef STEAMWORKS
1953 		SteamAPI_RunCallbacks();
1954 		if ( SteamUser()->BLoggedOn() && !achievementCartographer )
1955 		{
1956 			SteamUserStats()->SetAchievement("BARONY_ACH_CARTOGRAPHER");
1957 			achievementCartographer = true;
1958 			SteamUserStats()->StoreStats();
1959 			//printlog("STEAM ACHIEVEMENT\n");
1960 		}
1961 #endif
1962 
1963 		// move buttons
1964 		/*if( !fullscreen ) {
1965 			butX->visible = 0;
1966 			but_->visible = 0;
1967 		} else {
1968 			butX->visible = 1;
1969 			but_->visible = 1;
1970 			butX->x = xres-16;
1971 			but_->x = xres-32;
1972 		}*/
1973 		butTilePalette->x = xres - 112;
1974 		butSprite->x = xres - 112;
1975 		butPencil->x = xres - 96;
1976 		butPoint->x = xres - 96;
1977 		butBrush->x = xres - 96;
1978 		butSelect->x = xres - 96;
1979 		butFill->x = xres - 96;
1980 
1981 		bool wasTextEditable = SDL_IsTextInputActive();
1982 		if ( !wasTextEditable )
1983 		{
1984 			textInsertCaratPosition = -1;
1985 		}
1986 
1987 		if ( !spritepalette && !tilepalette )
1988 		{
1989 			allowediting = 1;
1990 			if ( (omousex >= xres - 128 && toolbox) || omousey < 16 || (omousey >= yres - 16 && statusbar) || subwindow || menuVisible )
1991 			{
1992 				allowediting = 0;
1993 			}
1994 			if ( mode3d )
1995 			{
1996 				allowediting = 0;
1997 			}
1998 			if ( menuVisible == 1 )
1999 			{
2000 				if ((omousex > 16 + butNew->sizex || omousey > 112 || (omousey < 16 && omousex > 192)) && mousestatus[SDL_BUTTON_LEFT])
2001 				{
2002 					menuVisible = 0;
2003 					menuDisappear = 1;
2004 				}
2005 			}
2006 			else if ( menuVisible == 2 )
2007 			{
2008 				if ((omousex > 56 + butCut->sizex || omousex < 40 || omousey > 128 || (omousey < 16 && omousex > 192)) && mousestatus[SDL_BUTTON_LEFT])
2009 				{
2010 					menuVisible = 0;
2011 					menuDisappear = 1;
2012 				}
2013 			}
2014 			else if ( menuVisible == 3 )
2015 			{
2016 				if ((omousex > 96 + butToolbox->sizex || omousex < 80 || omousey > 128 || (omousey < 16 && omousex > 192)) && mousestatus[SDL_BUTTON_LEFT])
2017 				{
2018 					menuVisible = 0;
2019 					menuDisappear = 1;
2020 				}
2021 			}
2022 			else if ( menuVisible == 4 )
2023 			{
2024 				if ((omousex > 136 + butClearMap->sizex || omousex < 120 || omousey > 48 || (omousey < 16 && omousex > 192)) && mousestatus[SDL_BUTTON_LEFT])
2025 				{
2026 					menuVisible = 0;
2027 					menuDisappear = 1;
2028 				}
2029 			}
2030 			else if ( menuVisible == 5 )
2031 			{
2032 				if ((omousex > 168 + butAbout->sizex || omousex < 152 || omousey > 48 || (omousey < 32 && omousex > 192)) && mousestatus[SDL_BUTTON_LEFT])
2033 				{
2034 					menuVisible = 0;
2035 					menuDisappear = 1;
2036 				}
2037 			}
2038 			if ( !mousestatus[SDL_BUTTON_LEFT] )
2039 			{
2040 				menuDisappear = 0;
2041 			}
2042 
2043 			if ( allowediting && !menuDisappear )
2044 			{
2045 				// MAIN LEVEL EDITING
2046 				drawx = (mousex + camx) >> TEXTUREPOWER;
2047 				drawy = (mousey + camy) >> TEXTUREPOWER;
2048 				odrawx = (omousex + ocamx) >> TEXTUREPOWER;
2049 				odrawy = (omousey + ocamy) >> TEXTUREPOWER;
2050 
2051 				// Set the Cursor to the corresponding tool
2052 				switch ( selectedTool )
2053 				{
2054 					case 0: // Pencil
2055 						SDL_SetCursor(cursorPencil);
2056 						break;
2057 					case 1: // Point
2058 						SDL_SetCursor(cursorPoint);
2059 						break;
2060 					case 2: // Brush
2061 						SDL_SetCursor(cursorBrush);
2062 						break;
2063 					case 3: // Select
2064 						SDL_SetCursor(cursorSelect);
2065 						break;
2066 					case 4: // Fill
2067 						SDL_SetCursor(cursorFill);
2068 						break;
2069 					default:
2070 						SDL_SetCursor(cursorArrow);
2071 						break;
2072 				}
2073 
2074 				// Move Entities
2075 				if ( map.entities->first != NULL && viewsprites && allowediting )
2076 				{
2077 					for ( node = map.entities->first; node != NULL; node = nextnode )
2078 					{
2079 						nextnode = node->next;
2080 						entity = (Entity*)node->element;
2081 						if ( entity == selectedEntity )
2082 						{
2083 							if ( mousestatus[SDL_BUTTON_LEFT] )
2084 							{
2085 								if ( newwindow == 0 )
2086 								{
2087 									// if the entity moved from where it was picked up, or if the sprite was right click duplicated, store an undo.
2088 									if ( selectedEntity->x / 16 != prev_x || selectedEntity->y / 16 != prev_y || duplicatedSprite )
2089 									{
2090 										duplicatedSprite = false;
2091 										makeUndo();
2092 									}
2093 								}
2094 								mousestatus[SDL_BUTTON_LEFT] = 0;
2095 								selectedEntity = NULL;
2096 								break;
2097 							}
2098 							else if ( mousestatus[SDL_BUTTON_RIGHT] )
2099 							{
2100 								if ( newwindow == 0 )
2101 								{
2102 									// if previous sprite was duplicated and another right click is registered, store an undo.
2103 									if ( duplicatedSprite )
2104 									{
2105 										makeUndo();
2106 									}
2107 									duplicatedSprite = true;
2108 								}
2109 								selectedEntity = newEntity(entity->sprite, 0, map.entities, nullptr);
2110 
2111 								setSpriteAttributes(selectedEntity, entity, lastSelectedEntity);
2112 
2113 								lastSelectedEntity = selectedEntity;
2114 
2115 								mousestatus[SDL_BUTTON_RIGHT] = 0;
2116 								break;
2117 							}
2118 							entity->x = (long)(drawx << 4);
2119 							entity->y = (long)(drawy << 4);
2120 						}
2121 						else
2122 						{
2123 							if ( (omousex + camx) >> TEXTUREPOWER == entity->x / 16 && (omousey + camy) >> TEXTUREPOWER == entity->y / 16 )
2124 							{
2125 								if ( mousestatus[SDL_BUTTON_LEFT] && selectedTool == 1 )
2126 								{
2127 									// select sprite
2128 									selectedEntity = entity;
2129 									lastSelectedEntity = selectedEntity;
2130 									prev_x = entity->x / 16;
2131 									prev_y = entity->y / 16;
2132 									mousestatus[SDL_BUTTON_LEFT] = 0;
2133 									if ( newwindow == 0 && selectedEntity != NULL )
2134 									{
2135 										makeUndo();
2136 									}
2137 								}
2138 								else if ( mousestatus[SDL_BUTTON_RIGHT] && selectedTool == 1 )
2139 								{
2140 									// duplicate sprite
2141 									duplicatedSprite = true;
2142 									if ( newwindow == 0 )
2143 									{
2144 										makeUndo();
2145 									}
2146 									selectedEntity = newEntity(entity->sprite, 0, map.entities, nullptr);
2147 									lastSelectedEntity = selectedEntity;
2148 
2149 									setSpriteAttributes(selectedEntity, entity, entity);
2150 
2151 									mousestatus[SDL_BUTTON_RIGHT] = 0;
2152 								}
2153 							}
2154 						}
2155 					}
2156 				}
2157 
2158 				// Modify World
2159 				if ( mousestatus[SDL_BUTTON_LEFT] && selectedEntity == NULL )
2160 				{
2161 					if ( allowediting )
2162 					{
2163 						if ( !savedundo )
2164 						{
2165 							savedundo = true;
2166 							makeUndo();
2167 						}
2168 						if ( !pasting )   // Not Pasting, Normal Editing Mode
2169 						{
2170 							if ( selectedTool == 0 )		// Process Pencil Tool functionality
2171 							{
2172 								if ( drawx >= 0 && drawx < map.width && drawy >= 0 && drawy < map.height )
2173 								{
2174 									map.tiles[drawlayer + drawy * MAPLAYERS + drawx * MAPLAYERS * map.height] = selectedTile;
2175 								}
2176 							}
2177 							else if ( selectedTool == 1 )	// Process Point Tool functionality
2178 							{
2179 								// All functionality of the Point Tool is encapsulated above in the "Move Entities" section
2180 							}
2181 							else if ( selectedTool == 2 )	// Process Brush Tool functionality
2182 							{
2183 								for ( x = drawx - 1; x <= drawx + 1; x++ )
2184 								{
2185 									for ( y = drawy - 1; y <= drawy + 1; y++ )
2186 									{
2187 										if ( (x != drawx - 1 || y != drawy - 1) && (x != drawx + 1 || y != drawy - 1) && (x != drawx - 1 || y != drawy + 1) && (x != drawx + 1 || y != drawy + 1) )
2188 										{
2189 											if ( x >= 0 && x < map.width && y >= 0 && y < map.height )
2190 											{
2191 												map.tiles[drawlayer + y * MAPLAYERS + x * MAPLAYERS * map.height] = selectedTile;
2192 											}
2193 										}
2194 									}
2195 								}
2196 							}
2197 							else if ( selectedTool == 3 )	// Process Select Tool functionality
2198 							{
2199 								if ( selectingspace == false )
2200 								{
2201 									if ( drawx >= 0 && drawy >= 0 && drawx < map.width && drawy < map.height )
2202 									{
2203 										selectingspace = true;
2204 										selectedarea_x1 = drawx;
2205 										selectedarea_x2 = drawx;
2206 										selectedarea_y1 = drawy;
2207 										selectedarea_y2 = drawy;
2208 										selectedarea = true;
2209 									}
2210 									else
2211 									{
2212 										selectedarea = false;
2213 									}
2214 								}
2215 								else
2216 								{
2217 									if ( drawx < odrawx )
2218 									{
2219 										selectedarea_x1 = std::min<unsigned int>(std::max(0, drawx), map.width - 1); //TODO: Why are int and unsigned int being compared?
2220 										selectedarea_x2 = std::min<unsigned int>(std::max(0, odrawx), map.width - 1); //TODO: Why are int and unsigned int being compared?
2221 									}
2222 									else
2223 									{
2224 										selectedarea_x1 = std::min<unsigned int>(std::max(0, odrawx), map.width - 1); //TODO: Why are int and unsigned int being compared?
2225 										selectedarea_x2 = std::min<unsigned int>(std::max(0, drawx), map.width - 1); //TODO: Why are int and unsigned int being compared?
2226 									}
2227 									if ( drawy < odrawy )
2228 									{
2229 										selectedarea_y1 = std::min<unsigned int>(std::max(0, drawy), map.height - 1); //TODO: Why are int and unsigned int being compared?
2230 										selectedarea_y2 = std::min<unsigned int>(std::max(0, odrawy), map.height - 1); //TODO: Why are int and unsigned int being compared?
2231 									}
2232 									else
2233 									{
2234 										selectedarea_y1 = std::min<unsigned int>(std::max(0, odrawy), map.height - 1); //TODO: Why are int and unsigned int being compared?
2235 										selectedarea_y2 = std::min<unsigned int>(std::max(0, drawy), map.height - 1); //TODO: Why are int and unsigned int being compared?
2236 									}
2237 									if ( map.entities->first != nullptr && viewsprites && allowediting )
2238 									{
2239 										reselectEntityGroup();
2240 										moveSelectionNegativeX = false;
2241 										moveSelectionNegativeY = false;
2242 									}
2243 								}
2244 							}
2245 							else if ( selectedTool == 4 )	// Process Fill Tool functionality
2246 							{
2247 								if ( drawx >= 0 && drawx < map.width && drawy >= 0 && drawy < map.height )
2248 								{
2249 									editFill(drawx, drawy, drawlayer, selectedTile);
2250 								}
2251 							}
2252 						}
2253 						else
2254 						{
2255 							// pasting from copymap
2256 							mousestatus[SDL_BUTTON_LEFT] = false;
2257 							for ( x = 0; x < copymap.width; x++ )
2258 							{
2259 								for ( y = 0; y < copymap.height; y++ )
2260 								{
2261 									if ( drawx + x >= 0 && drawx + x < map.width && drawy + y >= 0 && drawy + y < map.height )
2262 									{
2263 										z = copymap.name[0] + y * MAPLAYERS + x * MAPLAYERS * copymap.height;
2264 										if ( copymap.tiles[z] )
2265 										{
2266 											map.tiles[drawlayer + (drawy + y)*MAPLAYERS + (drawx + x)*MAPLAYERS * map.height] = copymap.tiles[z];
2267 										}
2268 									}
2269 								}
2270 							}
2271 							pasting = false;
2272 						}
2273 					}
2274 				}
2275 				else if ( !mousestatus[SDL_BUTTON_LEFT] )
2276 				{
2277 					selectingspace = false;
2278 					savedundo = false;
2279 				}
2280 				if ( mousestatus[SDL_BUTTON_RIGHT] && selectedEntity == NULL )
2281 				{
2282 					if ( selectedTool != 3 )
2283 					{
2284 						if ( drawx >= 0 && drawx < map.width && drawy >= 0 && drawy < map.height )
2285 						{
2286 							selectedTile = map.tiles[drawlayer + drawy * MAPLAYERS + drawx * MAPLAYERS * map.height];
2287 							updateRecentTileList(selectedTile);
2288 						}
2289 					}
2290 					else
2291 					{
2292 						selectedarea = false;
2293 					}
2294 				}
2295 			}
2296 			else
2297 			{
2298 				SDL_SetCursor(cursorArrow);
2299 			}
2300 
2301 			// main drawing
2302 			drawClearBuffers();
2303 			if ( mode3d == false )
2304 			{
2305 				if ( alllayers )
2306 					for (c = 0; c <= drawlayer; c++)
2307 					{
2308 						drawLayer(camx, camy, c, &map);
2309 					}
2310 				else
2311 				{
2312 					drawLayer(camx, camy, drawlayer, &map);
2313 				}
2314 				if ( pasting )
2315 				{
2316 					drawLayer(camx - (drawx << TEXTUREPOWER), camy - (drawy << TEXTUREPOWER), copymap.name[0], &copymap);
2317 				}
2318 				if ( selectedarea )
2319 				{
2320 					pos.x = (selectedarea_x1 << TEXTUREPOWER) - camx;
2321 					pos.y = (selectedarea_y1 << TEXTUREPOWER) - camy;
2322 					pos.w = (selectedarea_x2 - selectedarea_x1 + 1) << TEXTUREPOWER;
2323 					pos.h = (selectedarea_y2 - selectedarea_y1 + 1) << TEXTUREPOWER;
2324 					drawRect(&pos, SDL_MapRGB(mainsurface->format, 255, 255, 255), 127);
2325 				}
2326 				if ( viewsprites )
2327 				{
2328 					drawEntities2D(camx, camy);
2329 				}
2330 				if ( showgrid )
2331 				{
2332 					drawGrid(camx, camy);
2333 				}
2334 			}
2335 			else
2336 			{
2337 				camera.winx = 0;
2338 				camera.winy = 16;
2339 				camera.winw = xres - 128;
2340 				camera.winh = yres - 32;
2341 				light = lightSphere(camera.x, camera.y, 16, 255);
2342 				for ( node = map.entities->first; node != NULL; node = node->next )
2343 				{
2344 					entity = (Entity*)node->element;
2345 					entity->flags[SPRITE] = true; // all entities rendered as SPRITES in the editor
2346 					entity->x += 8;
2347 					entity->y += 8;
2348 				}
2349 				raycast(&camera, REALCOLORS);
2350 				glDrawWorld(&camera, REALCOLORS);
2351 				//drawFloors(&camera);
2352 				drawEntities3D(&camera, REALCOLORS);
2353 				printTextFormatted(font8x8_bmp, 8, yres - 64, "x = %3.3f\ny = %3.3f\nz = %3.3f\nang = %3.3f\nfps = %3.1f", camera.x, camera.y, camera.z, camera.ang, fps);
2354 				list_RemoveNode(light->node);
2355 				for ( node = map.entities->first; node != NULL; node = node->next )
2356 				{
2357 					entity = (Entity*)node->element;
2358 					entity->x -= 8;
2359 					entity->y -= 8;
2360 				}
2361 			}
2362 
2363 			// primary interface
2364 			drawWindowFancy(0, 0, xres, 16);
2365 			if ( toolbox )
2366 			{
2367 				if ( statusbar )
2368 				{
2369 					drawWindowFancy(xres - 128, 16, xres, yres - 16);
2370 				}
2371 				else
2372 				{
2373 					drawWindowFancy(xres - 128, 16, xres, yres);
2374 				}
2375 				drawEditormap(camx, camy);
2376 
2377 				// draw selected tile / hovering tile
2378 				pos.x = xres - 48;
2379 				pos.y = 320;
2380 				pos.w = 0;
2381 				pos.h = 0;
2382 				if ( selectedTile >= 0 && selectedTile < numtiles )
2383 				{
2384 					if ( tiles[selectedTile] != NULL )
2385 					{
2386 						drawImage(tiles[selectedTile], NULL, &pos);
2387 					}
2388 					else
2389 					{
2390 						drawImage(sprites[0], NULL, &pos);
2391 					}
2392 				}
2393 				else
2394 				{
2395 					drawImage(sprites[0], NULL, &pos);
2396 				}
2397 				pos.x = xres - 48;
2398 				pos.y = 360;
2399 				pos.w = 0;
2400 				pos.h = 0;
2401 				if ( drawx >= 0 && drawx < map.width && drawy >= 0 && drawy < map.height )
2402 				{
2403 					c = map.tiles[drawlayer + drawy * MAPLAYERS + drawx * MAPLAYERS * map.height];
2404 					if ( c >= 0 && c < numtiles )
2405 					{
2406 						if ( tiles[c] != NULL )
2407 						{
2408 							drawImage(tiles[c], NULL, &pos);
2409 						}
2410 						else
2411 						{
2412 							drawImage(sprites[0], NULL, &pos);
2413 						}
2414 					}
2415 					else
2416 					{
2417 						drawImage(sprites[0], NULL, &pos);
2418 					}
2419 				}
2420 				else
2421 				{
2422 					drawImage(sprites[0], NULL, &pos);
2423 				}
2424 				printText(font8x8_bmp, xres - 124, 332, "Selected:");
2425 				printText(font8x8_bmp, xres - 124, 372, "   Above:");
2426 
2427 				// Print the name of the selected tool below the Tool Buttons
2428 				switch ( selectedTool )
2429 				{
2430 					case 0: // Pencil
2431 						printText(font8x8_bmp, xres - 84, 292, "PENCIL");
2432 						break;
2433 					case 1: // Point
2434 						printText(font8x8_bmp, xres - 84, 292, "POINT");
2435 						break;
2436 					case 2: // Brush
2437 						printText(font8x8_bmp, xres - 84, 292, "BRUSH");
2438 						break;
2439 					case 3: // Select
2440 						printText(font8x8_bmp, xres - 88, 292, "SELECT");
2441 						break;
2442 					case 4: // Fill
2443 						printText(font8x8_bmp, xres - 80, 292, "FILL");
2444 						break;
2445 				}
2446 
2447 				int recentTileStartx = xres - 114;
2448 				int recentTileStarty = 420;
2449 				int recentIndex = 0;
2450 				int pad_x = 34;
2451 				int pad_y = 34;
2452 				char tmpStr[32] = "PALETTE: ";
2453 				char tmpStr2[2] = "";
2454 				pos.x = recentTileStartx;
2455 				pos.y = recentTileStarty;
2456 				pos.w = 32;
2457 				pos.h = 32;
2458 				SDL_Rect boxPos;
2459 				snprintf(tmpStr2, sizeof(tmpStr2), "%d", recentUsedTilePalette + 1); //reset
2460 				strcat(tmpStr, tmpStr2);
2461 				printText(font8x8_bmp, xres - 110, recentTileStarty - 16, tmpStr);
2462 
2463 				for ( recentIndex = 0; recentIndex < 9; recentIndex++ )
2464 				{
2465 					if ( recentIndex == 3 || recentIndex == 6 )
2466 					{
2467 						pos.x = recentTileStartx;
2468 						pos.y += pad_y;
2469 					}
2470 
2471 
2472 					if ( mousestatus[SDL_BUTTON_LEFT] )
2473 					{
2474 						if ( omousex >= pos.x && omousex < pos.x + 32 && omousey >= pos.y && omousey < pos.y + 32 )
2475 						{
2476 							selectedTile = recentUsedTiles[recentUsedTilePalette][recentIndex];
2477 							lastPaletteTileSelected = recentIndex;
2478 						}
2479 					}
2480 					if ( mousestatus[SDL_BUTTON_RIGHT] )
2481 					{
2482 						if ( omousex >= pos.x && omousex < pos.x + 32 && omousey >= pos.y && omousey < pos.y + 32 )
2483 						{
2484 							if ( lockTilePalette[recentUsedTilePalette] != 1 )
2485 							{
2486 								recentUsedTiles[recentUsedTilePalette][recentIndex] = 0;
2487 							}
2488 						}
2489 					}
2490 
2491 					boxPos.x = pos.x - 2;
2492 					boxPos.y = pos.y - 2;
2493 					boxPos.w = pos.w + 4;
2494 					boxPos.h = pos.h + 4;
2495 
2496 					if ( lastPaletteTileSelected == recentIndex )
2497 					{
2498 						drawRect(&boxPos, SDL_MapRGB(mainsurface->format, 255, 0, 0), 255);
2499 					}
2500 					drawImage(tiles[recentUsedTiles[recentUsedTilePalette][recentIndex]], NULL, &pos);
2501 					pos.x += pad_x;
2502 				}
2503 
2504 				if ( lockTilePalette[recentUsedTilePalette] == 1 )
2505 				{
2506 					printText(font8x8_bmp, xres - 100, pos.y + 40, "LOCKED");
2507 				}
2508 				else
2509 				{
2510 					printText(font8x8_bmp, xres - 100, pos.y + 40, "UNLOCKED");
2511 				}
2512 			}
2513 			if ( statusbar )
2514 			{
2515 				drawWindowFancy(0, yres - 16, xres, yres);
2516 				printTextFormatted(font8x8_bmp, 4, yres - 12, "X: %4d Y: %4d Z: %d %s", drawx, drawy, drawlayer + 1, layerstatus);
2517 				if ( messagetime )
2518 				{
2519 					printText(font8x8_bmp, xres - 8 * (strlen(message)) - 12, yres - 12, message);
2520 				}
2521 			}
2522 
2523 			// handle main menus
2524 			if ( menuVisible == 1 )
2525 			{
2526 				drawWindowFancy(0, 16, 16, 112);
2527 				butNew->visible = 1;
2528 				butOpen->visible = 1;
2529 				butDir->visible = 1;
2530 				butSave->visible = 1;
2531 				butSaveAs->visible = 1;
2532 				butExit->visible = 1;
2533 			}
2534 			else
2535 			{
2536 				butNew->visible = 0;
2537 				butOpen->visible = 0;
2538 				butDir->visible = 0;
2539 				butSave->visible = 0;
2540 				butSaveAs->visible = 0;
2541 				butExit->visible = 0;
2542 			}
2543 			if ( menuVisible == 2 )
2544 			{
2545 				drawWindowFancy(40, 16, 56, 128);
2546 				butPaste->visible = 1;
2547 				butCut->visible = 1;
2548 				butCopy->visible = 1;
2549 				butDelete->visible = 1;
2550 				butSelectAll->visible = 1;
2551 				butUndo->visible = 1;
2552 				butRedo->visible = 1;
2553 			}
2554 			else
2555 			{
2556 				butPaste->visible = 0;
2557 				butCut->visible = 0;
2558 				butCopy->visible = 0;
2559 				butDelete->visible = 0;
2560 				butSelectAll->visible = 0;
2561 				butUndo->visible = 0;
2562 				butRedo->visible = 0;
2563 			}
2564 			if ( menuVisible == 3 )
2565 			{
2566 				drawWindowFancy(80, 16, 96, 128);
2567 				butToolbox->visible = 1;
2568 				butStatusBar->visible = 1;
2569 				butAllLayers->visible = 1;
2570 				butHoverText->visible = 1;
2571 				butViewSprites->visible = 1;
2572 				butGrid->visible = 1;
2573 				but3DMode->visible = 1;
2574 				if ( statusbar )
2575 				{
2576 					printText(font8x8_bmp, 84, 20, "x");
2577 				}
2578 				if ( toolbox )
2579 				{
2580 					printText(font8x8_bmp, 84, 36, "x");
2581 				}
2582 				if ( alllayers )
2583 				{
2584 					printText(font8x8_bmp, 84, 52, "x");
2585 				}
2586 				if ( viewsprites )
2587 				{
2588 					printText(font8x8_bmp, 84, 68, "x");
2589 				}
2590 				if ( showgrid )
2591 				{
2592 					printText(font8x8_bmp, 84, 84, "x");
2593 				}
2594 				if ( mode3d )
2595 				{
2596 					printText(font8x8_bmp, 84, 100, "x");
2597 				}
2598 				if ( hovertext )
2599 				{
2600 					printText(font8x8_bmp, 84, 116, "x");
2601 				}
2602 			}
2603 			else
2604 			{
2605 				butToolbox->visible = 0;
2606 				butStatusBar->visible = 0;
2607 				butAllLayers->visible = 0;
2608 				butHoverText->visible = 0;
2609 				butViewSprites->visible = 0;
2610 				butGrid->visible = 0;
2611 				but3DMode->visible = 0;
2612 			}
2613 			if ( menuVisible == 4 )
2614 			{
2615 				drawWindowFancy(120, 16, 136, 48);
2616 				butAttributes->visible = 1;
2617 				butClearMap->visible = 1;
2618 			}
2619 			else
2620 			{
2621 				butAttributes->visible = 0;
2622 				butClearMap->visible = 0;
2623 			}
2624 			if ( menuVisible == 5 )
2625 			{
2626 				drawWindowFancy(152, 16, 168, 48);
2627 				butAbout->visible = 1;
2628 				butEditorControls->visible = 1;
2629 			}
2630 			else
2631 			{
2632 				butAbout->visible = 0;
2633 				butEditorControls->visible = 0;
2634 			}
2635 
2636 			// subwindows
2637 			if ( subwindow )
2638 			{
2639 				drawWindowFancy(subx1, suby1, subx2, suby2);
2640 				if ( subtext != NULL )
2641 				{
2642 					printText(font8x8_bmp, subx1 + 8, suby1 + 8, subtext);
2643 				}
2644 
2645 				// open and save windows
2646 				if ( (openwindow == 1 || savewindow) )
2647 				{
2648 					drawDepressed(subx1 + 4, suby1 + 20, subx2 - 20, suby2 - 52);
2649 					drawDepressed(subx2 - 20, suby1 + 20, subx2 - 4, suby2 - 52);
2650 					if ( !mapNames.empty() )
2651 					{
2652 						slidersize = std::min<int>(((suby2 - 53) - (suby1 + 21)), ((suby2 - 53) - (suby1 + 21)) / ((real_t)mapNames.size() / 20)); //TODO: Why are int and real_t being compared?
2653 						slidery = std::min(std::max(suby1 + 21, slidery), suby2 - 53 - slidersize);
2654 						drawWindowFancy(subx2 - 19, slidery, subx2 - 5, slidery + slidersize);
2655 
2656 						// directory list offset from slider
2657 						y2 = ((real_t)(slidery - suby1 - 20) / ((suby2 - 52) - (suby1 + 20))) * (mapNames.size() + 1);
2658 						if ( scroll )
2659 						{
2660 							slidery -= 8 * scroll;
2661 							slidery = std::min(std::max(suby1 + 21, slidery), suby2 - 53 - slidersize);
2662 							y2 = ((real_t)(slidery - suby1 - 20) / ((suby2 - 52) - (suby1 + 20))) * (mapNames.size() + 1);
2663 							selectedFile = std::min<long unsigned int>(std::max(y2, selectedFile), std::min<long unsigned int>(mapNames.size() - 1, y2 + 19)); //TODO: Why are long unsigned int and int being compared? TWICE. On the same line.
2664 							strcpy(filename, mapNames[selectedFile].c_str());
2665 							inputstr = filename;
2666 							scroll = 0;
2667 						}
2668 						if ( mousestatus[SDL_BUTTON_LEFT] && omousex >= subx2 - 20 && omousex < subx2 - 4 && omousey >= suby1 + 20 && omousey < suby2 - 52 )
2669 						{
2670 							slidery = oslidery + mousey - omousey;
2671 							slidery = std::min(std::max(suby1 + 21, slidery), suby2 - 53 - slidersize);
2672 							y2 = ((real_t)(slidery - suby1 - 20) / ((suby2 - 52) - (suby1 + 20))) * (mapNames.size() + 1);
2673 							mclick = 1;
2674 							selectedFile = std::min<long unsigned int>(std::max(y2, selectedFile), std::min<long unsigned int>(mapNames.size() - 1, y2 + 19)); //TODO: Why are long unsigned int and int being compared? TWICE. On the same line.
2675 							strcpy(filename, mapNames[selectedFile].c_str());
2676 							inputstr = filename;
2677 						}
2678 						else
2679 						{
2680 							oslidery = slidery;
2681 						}
2682 
2683 						// select a file
2684 						if ( mousestatus[SDL_BUTTON_LEFT] )
2685 						{
2686 							if ( omousex >= subx1 + 8 && omousex < subx2 - 24 && omousey >= suby1 + 24 && omousey < suby2 - 56 )
2687 							{
2688 								selectedFile = y2 + ((omousey - suby1 - 24) >> 3);
2689 								selectedFile = std::min<long unsigned int>(std::max(y2, selectedFile), std::min<long unsigned int>(mapNames.size() - 1, y2 + 19)); //TODO: Why are long unsigned int and int being compared? TWICE. On the same line.
2690 								strcpy(filename, mapNames[selectedFile].c_str());
2691 								inputstr = filename;
2692 							}
2693 						}
2694 						pos.x = subx1 + 8;
2695 						pos.y = suby1 + 24 + (std::max(selectedFile - y2, 0)) * 8;
2696 						pos.w = subx2 - subx1 - 32;
2697 						pos.h = 8;
2698 						drawRect(&pos, SDL_MapRGB(mainsurface->format, 64, 64, 64), 255);
2699 
2700 						// print all the files within the directory
2701 						x = subx1 + 8;
2702 						y = suby1 + 24;
2703 						c = std::min<long unsigned int>(mapNames.size(), 20 + y2); //TODO: Why are long unsigned int and int being compared?
2704 						for (z = y2; z < c; z++)
2705 						{
2706 							printText(font8x8_bmp, x, y, mapNames[z].c_str());
2707 							y += 8;
2708 						}
2709 					}
2710 
2711 					// text box to enter file
2712 					drawDepressed(subx1 + 4, suby2 - 48, subx2 - 68, suby2 - 32);
2713 					printText(font8x8_bmp, subx1 + 8, suby2 - 44, filename);
2714 
2715 					// enter filename
2716 					if ( !SDL_IsTextInputActive() )
2717 					{
2718 						SDL_StartTextInput();
2719 						inputstr = filename;
2720 					}
2721 					//strncpy(filename,inputstr,28);
2722 					inputlen = 28;
2723 					if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
2724 					{
2725 						printText(font8x8_bmp, subx1 + 8 + strlen(filename) * 8, suby2 - 44, "\26");
2726 					}
2727 				}
2728 				else if ( openwindow == 2 )
2729 				{
2730 					drawDepressed(subx1 + 4, suby1 + 20, subx2 - 20, suby2 - 112);
2731 					drawDepressed(subx2 - 20, suby1 + 20, subx2 - 4, suby2 - 112);
2732 					if ( !modFolderNames.empty() )
2733 					{
2734 						slidersize = std::min<int>(((suby2 - 113) - (suby1 + 21)), ((suby2 - 113) - (suby1 + 21)) / ((real_t)modFolderNames.size() / 20)); //TODO: Why are int and real_t being compared?
2735 						slidery = std::min(std::max(suby1 + 21, slidery), suby2 - 113 - slidersize);
2736 						drawWindowFancy(subx2 - 19, slidery, subx2 - 5, slidery + slidersize);
2737 
2738 						// directory list offset from slider
2739 						y2 = ((real_t)(slidery - suby1 - 20) / ((suby2 - 52) - (suby1 + 20))) * modFolderNames.size();
2740 						if ( scroll )
2741 						{
2742 							slidery -= 8 * scroll;
2743 							slidery = std::min(std::max(suby1 + 21, slidery), suby2 - 113 - slidersize);
2744 							y2 = ((real_t)(slidery - suby1 - 20) / ((suby2 - 112) - (suby1 + 20))) * modFolderNames.size();
2745 							selectedFile = std::min<long unsigned int>(std::max(y2, selectedFile), std::min<long unsigned int>(modFolderNames.size() - 1, y2 + 19)); //TODO: Why are long unsigned int and int being compared? TWICE. On the same line.
2746 							std::list<std::string>::iterator it = modFolderNames.begin();
2747 							std::advance(it, selectedFile);
2748 							strcpy(foldername, it->c_str());
2749 							inputstr = foldername;
2750 							scroll = 0;
2751 						}
2752 						if ( mousestatus[SDL_BUTTON_LEFT] && omousex >= subx2 - 20 && omousex < subx2 - 4 && omousey >= suby1 + 20 && omousey < suby2 - 113 )
2753 						{
2754 							slidery = oslidery + mousey - omousey;
2755 							slidery = std::min(std::max(suby1 + 21, slidery), suby2 - 113 - slidersize);
2756 							y2 = ((real_t)(slidery - suby1 - 20) / ((suby2 - 112) - (suby1 + 20))) * modFolderNames.size();
2757 							mclick = 1;
2758 							selectedFile = std::min<long unsigned int>(std::max(y2, selectedFile), std::min<long unsigned int>(modFolderNames.size() - 1, y2 + 19)); //TODO: Why are long unsigned int and int being compared? TWICE. On the same line.
2759 							std::list<std::string>::iterator it = modFolderNames.begin();
2760 							std::advance(it, selectedFile);
2761 							strcpy(foldername, it->c_str());
2762 							inputstr = foldername;
2763 						}
2764 						else
2765 						{
2766 							oslidery = slidery;
2767 						}
2768 
2769 						// select a file
2770 						if ( mousestatus[SDL_BUTTON_LEFT] )
2771 						{
2772 							if ( omousex >= subx1 + 8 && omousex < subx2 - 24 && omousey >= suby1 + 24 && omousey < suby2 - 116 )
2773 							{
2774 								selectedFile = y2 + ((omousey - suby1 - 24) >> 3);
2775 								selectedFile = std::min<long unsigned int>(std::max(y2, selectedFile), std::min<long unsigned int>(modFolderNames.size() - 1, y2 + 19)); //TODO: Why are long unsigned int and int being compared? TWICE. On the same line.
2776 								std::list<std::string>::iterator it = modFolderNames.begin();
2777 								std::advance(it, selectedFile);
2778 								strcpy(foldername, it->c_str());
2779 								inputstr = foldername;
2780 							}
2781 						}
2782 						pos.x = subx1 + 8;
2783 						pos.y = suby1 + 24 + (selectedFile - y2) * 8;
2784 						pos.w = subx2 - subx1 - 32;
2785 						pos.h = 8;
2786 						drawRect(&pos, SDL_MapRGB(mainsurface->format, 64, 64, 64), 255);
2787 
2788 						// print all the files within the directory
2789 						x = subx1 + 8;
2790 						y = suby1 + 24;
2791 						c = std::min<long unsigned int>(modFolderNames.size(), 20 + y2); //TODO: Why are long unsigned int and int being compared?
2792 						for ( z = y2; z < c; z++ )
2793 						{
2794 							std::list<std::string>::iterator it = modFolderNames.begin();
2795 							std::advance(it, z);
2796 							printText(font8x8_bmp, x, y, it->c_str());
2797 							y += 8;
2798 						}
2799 					}
2800 
2801 					// text box to enter file
2802 					drawDepressed(subx1 + 4, suby2 - 108, subx2 - 4, suby2 - 92);
2803 					printText(font8x8_bmp, subx1 + 8, suby2 - 104, foldername);
2804 
2805 					printTextFormatted(font8x8_bmp, subx1 + 8, suby2 - 32, "Save Dir: %smaps/", physfs_saveDirectory.c_str());
2806 					printTextFormatted(font8x8_bmp, subx1 + 8, suby2 - 16, "Load Dir: %smaps/", physfs_openDirectory.c_str());
2807 
2808 					// enter filename
2809 					if ( !SDL_IsTextInputActive() )
2810 					{
2811 						SDL_StartTextInput();
2812 						inputstr = foldername;
2813 					}
2814 					//strncpy(filename,inputstr,28);
2815 					inputlen = 28;
2816 					if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
2817 					{
2818 						printText(font8x8_bmp, subx1 + 8 + strlen(foldername) * 8, suby2 - 104, "\26");
2819 					}
2820 				}
2821 
2822 				// new map and attributes windows
2823 				if ( newwindow == 1 )
2824 				{
2825 					int pad_y1 = 0;
2826 					int start_y = suby1 + 28;
2827 					int rowheight = 16;
2828 
2829 					printText(font8x8_bmp, subx1 + 8, start_y + pad_y1, "Map Name:");
2830 					drawDepressed(subx1 + 4, suby1 + 40, subx2 - 4, suby1 + 56);
2831 					printText(font8x8_bmp, subx1 + 8, start_y + 16, nametext);
2832 					pad_y1 += 24;
2833 					printText(font8x8_bmp, subx1 + 8, start_y + pad_y1 + 12, "Author Name:");
2834 					drawDepressed(subx1 + 4, suby1 + 76, subx2 - 4, suby1 + 92);
2835 					printText(font8x8_bmp, subx1 + 8, start_y + 16 + 36, authortext);
2836 
2837 					start_y = suby1 + 104;
2838 					pad_y1 = 0;
2839 					int start_x2 = subx1 + 180;
2840 					int start_x3 = subx2 - 32;
2841 					printText(font8x8_bmp, subx1 + 8, start_y + pad_y1, "Map Skybox:");
2842 					drawDepressed(subx1 + 104, start_y + pad_y1 - 4, subx1 + 168, start_y + pad_y1 + rowheight - 4);
2843 					printText(font8x8_bmp, subx1 + 108, start_y + pad_y1, skyboxtext);
2844 
2845 					printText(font8x8_bmp, start_x2, start_y + pad_y1, "Disable Traps:");
2846 					printText(font8x8_bmp, start_x3, start_y + pad_y1, mapflagtext[MAP_FLAG_DISABLETRAPS]);
2847 					pad_y1 += 24;
2848 					printText(font8x8_bmp, subx1 + 8, start_y + pad_y1, "Map Ceiling:");
2849 					drawDepressed(subx1 + 104, start_y + pad_y1 - 4, subx1 + 168, start_y + pad_y1 + rowheight - 4);
2850 					printText(font8x8_bmp, subx1 + 108, start_y + pad_y1, mapflagtext[MAP_FLAG_CEILINGTILE]);
2851 
2852 					printText(font8x8_bmp, start_x2, start_y + pad_y1, "Disable Monster Spawns:");
2853 					printText(font8x8_bmp, start_x3, start_y + pad_y1, mapflagtext[MAP_FLAG_DISABLEMONSTERS]);
2854 					pad_y1 += 24;
2855 					printText(font8x8_bmp, subx1 + 8, start_y + pad_y1, "Entity Qty:");
2856 					drawDepressed(subx1 + 104, start_y + pad_y1 - 4, subx1 + 128, start_y + pad_y1 + rowheight - 4);
2857 					printText(font8x8_bmp, subx1 + 108, start_y + pad_y1, mapflagtext[MAP_FLAG_GENTOTALMIN]);
2858 					printText(font8x8_bmp, subx1 + 132, start_y + pad_y1, "-");
2859 					drawDepressed(subx1 + 144, start_y + pad_y1 - 4, subx1 + 168, start_y + pad_y1 + rowheight - 4);
2860 					printText(font8x8_bmp, subx1 + 144 + 4, start_y + pad_y1, mapflagtext[MAP_FLAG_GENTOTALMAX]);
2861 
2862 					printText(font8x8_bmp, start_x2, start_y + pad_y1, "Disable Loot Spawns:");
2863 					printText(font8x8_bmp, start_x3, start_y + pad_y1, mapflagtext[MAP_FLAG_DISABLELOOT]);
2864 
2865 					pad_y1 += 24;
2866 					printText(font8x8_bmp, subx1 + 8, start_y + pad_y1, "Monster Qty:");
2867 					drawDepressed(subx1 + 104, start_y + pad_y1 - 4, subx1 + 128, start_y + pad_y1 + rowheight - 4);
2868 					printText(font8x8_bmp, subx1 + 108, start_y + pad_y1, mapflagtext[MAP_FLAG_GENMONSTERMIN]);
2869 					printText(font8x8_bmp, subx1 + 132, start_y + pad_y1, "-");
2870 					drawDepressed(subx1 + 144, start_y + pad_y1 - 4, subx1 + 168, start_y + pad_y1 + rowheight - 4);
2871 					printText(font8x8_bmp, subx1 + 144 + 4, start_y + pad_y1, mapflagtext[MAP_FLAG_GENMONSTERMAX]);
2872 
2873 					printText(font8x8_bmp, start_x2, start_y + pad_y1, "Disable Digging:");
2874 					printText(font8x8_bmp, start_x3, start_y + pad_y1, mapflagtext[MAP_FLAG_DISABLEDIGGING]);
2875 
2876 					pad_y1 += 24;
2877 					printText(font8x8_bmp, subx1 + 8, start_y + pad_y1, "Item Qty:");
2878 					drawDepressed(subx1 + 104, start_y + pad_y1 - 4, subx1 + 128, start_y + pad_y1 + rowheight - 4);
2879 					printText(font8x8_bmp, subx1 + 108, start_y + pad_y1, mapflagtext[MAP_FLAG_GENLOOTMIN]);
2880 					printText(font8x8_bmp, subx1 + 132, start_y + pad_y1, "-");
2881 					drawDepressed(subx1 + 144, start_y + pad_y1 - 4, subx1 + 168, start_y + pad_y1 + rowheight - 4);
2882 					printText(font8x8_bmp, subx1 + 144 + 4, start_y + pad_y1, mapflagtext[MAP_FLAG_GENLOOTMAX]);
2883 
2884 					printText(font8x8_bmp, start_x2, start_y + pad_y1, "Disable Teleportation:");
2885 					printText(font8x8_bmp, start_x3, start_y + pad_y1, mapflagtext[MAP_FLAG_DISABLETELEPORT]);
2886 
2887 					pad_y1 += 24;
2888 					printText(font8x8_bmp, subx1 + 8, start_y + pad_y1, "Deco Qty:");
2889 					drawDepressed(subx1 + 104, start_y + pad_y1 - 4, subx1 + 128, start_y + pad_y1 + rowheight - 4);
2890 					printText(font8x8_bmp, subx1 + 108, start_y + pad_y1, mapflagtext[MAP_FLAG_GENDECORATIONMIN]);
2891 					printText(font8x8_bmp, subx1 + 132, start_y + pad_y1, "-");
2892 					drawDepressed(subx1 + 144, start_y + pad_y1 - 4, subx1 + 168, start_y + pad_y1 + rowheight - 4);
2893 					printText(font8x8_bmp, subx1 + 144 + 4, start_y + pad_y1, mapflagtext[MAP_FLAG_GENDECORATIONMAX]);
2894 
2895 					printText(font8x8_bmp, start_x2, start_y + pad_y1, "Disable Levitation:");
2896 					printText(font8x8_bmp, start_x3, start_y + pad_y1, mapflagtext[MAP_FLAG_DISABLELEVITATION]);
2897 
2898 					pad_y1 += 24;
2899 					printText(font8x8_bmp, start_x2, start_y + pad_y1, "Gen Adjacent Rooms:");
2900 					printText(font8x8_bmp, start_x3, start_y + pad_y1, mapflagtext[MAP_FLAG_GENADJACENTROOMS]);
2901 
2902 					pad_y1 += 24;
2903 					printText(font8x8_bmp, start_x2, start_y + pad_y1, "Disable Opening Spell:");
2904 					printText(font8x8_bmp, start_x3, start_y + pad_y1, mapflagtext[MAP_FLAG_DISABLEOPENING]);
2905 
2906 					pad_y1 += 24;
2907 					printText(font8x8_bmp, start_x2, start_y + pad_y1, "Disable Herx Messages:");
2908 					printText(font8x8_bmp, start_x3, start_y + pad_y1, mapflagtext[MAP_FLAG_DISABLEMESSAGES]);
2909 
2910 					pad_y1 += 24;
2911 					printText(font8x8_bmp, start_x2, start_y + pad_y1, "Disable Hunger Loss:");
2912 					printText(font8x8_bmp, start_x3, start_y + pad_y1, mapflagtext[MAP_FLAG_DISABLEHUNGER]);
2913 
2914 					start_y = suby2 - 44;
2915 					pad_y1 = 0;
2916 					printText(font8x8_bmp, subx1 + 8, start_y + pad_y1, "Map Width:");
2917 					drawDepressed(subx1 + 104, start_y + pad_y1 - 4, subx1 + 168, start_y + pad_y1 + rowheight - 4);
2918 					printText(font8x8_bmp, subx1 + 108, start_y + pad_y1, widthtext);
2919 					pad_y1 += 24;
2920 					printText(font8x8_bmp, subx1 + 8, start_y + pad_y1, "Map Height:");
2921 					drawDepressed(subx1 + 104, start_y + pad_y1 - 4, subx1 + 168, start_y + pad_y1 + rowheight - 4);
2922 					printText(font8x8_bmp, subx1 + 108, start_y + pad_y1, heighttext);
2923 
2924 					if ( keystatus[SDL_SCANCODE_TAB] )
2925 					{
2926 						keystatus[SDL_SCANCODE_TAB] = 0;
2927 						cursorflash = ticks;
2928 						editproperty++;
2929 						if ( editproperty == 14 )
2930 						{
2931 							editproperty = 0;
2932 						}
2933 						switch ( editproperty )
2934 						{
2935 							case 0:
2936 								inputstr = nametext;
2937 								break;
2938 							case 1:
2939 								inputstr = authortext;
2940 								break;
2941 							case 2:
2942 								inputstr = skyboxtext;
2943 								break;
2944 							case 3:
2945 								inputstr = mapflagtext[MAP_FLAG_CEILINGTILE];
2946 								break;
2947 							case 4:
2948 								inputstr = mapflagtext[MAP_FLAG_GENTOTALMIN];
2949 								break;
2950 							case 5:
2951 								inputstr = mapflagtext[MAP_FLAG_GENTOTALMAX];
2952 								break;
2953 							case 6:
2954 								inputstr = mapflagtext[MAP_FLAG_GENMONSTERMIN];
2955 								break;
2956 							case 7:
2957 								inputstr = mapflagtext[MAP_FLAG_GENMONSTERMAX];
2958 								break;
2959 							case 8:
2960 								inputstr = mapflagtext[MAP_FLAG_GENLOOTMIN];
2961 								break;
2962 							case 9:
2963 								inputstr = mapflagtext[MAP_FLAG_GENLOOTMAX];
2964 								break;
2965 							case 10:
2966 								inputstr = mapflagtext[MAP_FLAG_GENDECORATIONMIN];
2967 								break;
2968 							case 11:
2969 								inputstr = mapflagtext[MAP_FLAG_GENDECORATIONMAX];
2970 								break;
2971 							case 12:
2972 								inputstr = widthtext;
2973 								break;
2974 							case 13:
2975 								inputstr = heighttext;
2976 								break;
2977 						}
2978 					}
2979 
2980 					// select a textbox
2981 					if ( mousestatus[SDL_BUTTON_LEFT] )
2982 					{
2983 						if ( omousex >= start_x3 && omousey >= suby1 + 100 && omousex < start_x3 + 24 && omousey < suby1 + 116 )
2984 						{
2985 							if ( !strncmp(mapflagtext[MAP_FLAG_DISABLETRAPS], "[x]", 3) )
2986 							{
2987 								strcpy(mapflagtext[MAP_FLAG_DISABLETRAPS], "[ ]");
2988 							}
2989 							else
2990 							{
2991 								strcpy(mapflagtext[MAP_FLAG_DISABLETRAPS], "[x]");
2992 							}
2993 							mousestatus[SDL_BUTTON_LEFT] = 0;
2994 						}
2995 						if ( omousex >= start_x3 && omousey >= suby1 + 124 && omousex < start_x3 + 24 && omousey < suby1 + 140 )
2996 						{
2997 							if ( !strncmp(mapflagtext[MAP_FLAG_DISABLEMONSTERS], "[x]", 3) )
2998 							{
2999 								strcpy(mapflagtext[MAP_FLAG_DISABLEMONSTERS], "[ ]");
3000 							}
3001 							else
3002 							{
3003 								strcpy(mapflagtext[MAP_FLAG_DISABLEMONSTERS], "[x]");
3004 							}
3005 							mousestatus[SDL_BUTTON_LEFT] = 0;
3006 						}
3007 						if ( omousex >= start_x3 && omousey >= suby1 + 148 && omousex < start_x3 + 24 && omousey < suby1 + 164 )
3008 						{
3009 							if ( !strncmp(mapflagtext[MAP_FLAG_DISABLELOOT], "[x]", 3) )
3010 							{
3011 								strcpy(mapflagtext[MAP_FLAG_DISABLELOOT], "[ ]");
3012 							}
3013 							else
3014 							{
3015 								strcpy(mapflagtext[MAP_FLAG_DISABLELOOT], "[x]");
3016 							}
3017 							mousestatus[SDL_BUTTON_LEFT] = 0;
3018 						}
3019 						if ( omousex >= start_x3 && omousey >= suby1 + 172 && omousex < start_x3 + 24 && omousey < suby1 + 188 )
3020 						{
3021 							if ( !strncmp(mapflagtext[MAP_FLAG_DISABLEDIGGING], "[x]", 3) )
3022 							{
3023 								strcpy(mapflagtext[MAP_FLAG_DISABLEDIGGING], "[ ]");
3024 							}
3025 							else
3026 							{
3027 								strcpy(mapflagtext[MAP_FLAG_DISABLEDIGGING], "[x]");
3028 							}
3029 							mousestatus[SDL_BUTTON_LEFT] = 0;
3030 						}
3031 						if ( omousex >= start_x3 && omousey >= suby1 + 196 && omousex < start_x3 + 24 && omousey < suby1 + 212 )
3032 						{
3033 							if ( !strncmp(mapflagtext[MAP_FLAG_DISABLETELEPORT], "[x]", 3) )
3034 							{
3035 								strcpy(mapflagtext[MAP_FLAG_DISABLETELEPORT], "[ ]");
3036 							}
3037 							else
3038 							{
3039 								strcpy(mapflagtext[MAP_FLAG_DISABLETELEPORT], "[x]");
3040 							}
3041 							mousestatus[SDL_BUTTON_LEFT] = 0;
3042 						}
3043 						if ( omousex >= start_x3 && omousey >= suby1 + 220 && omousex < start_x3 + 24 && omousey < suby1 + 236 )
3044 						{
3045 							if ( !strncmp(mapflagtext[MAP_FLAG_DISABLELEVITATION], "[x]", 3) )
3046 							{
3047 								strcpy(mapflagtext[MAP_FLAG_DISABLELEVITATION], "[ ]");
3048 							}
3049 							else
3050 							{
3051 								strcpy(mapflagtext[MAP_FLAG_DISABLELEVITATION], "[x]");
3052 							}
3053 							mousestatus[SDL_BUTTON_LEFT] = 0;
3054 						}
3055 						if ( omousex >= start_x3 && omousey >= suby1 + 244 && omousex < start_x3 + 24 && omousey < suby1 + 260 )
3056 						{
3057 							if ( !strncmp(mapflagtext[MAP_FLAG_GENADJACENTROOMS], "[x]", 3) )
3058 							{
3059 								strcpy(mapflagtext[MAP_FLAG_GENADJACENTROOMS], "[ ]");
3060 							}
3061 							else
3062 							{
3063 								strcpy(mapflagtext[MAP_FLAG_GENADJACENTROOMS], "[x]");
3064 							}
3065 							mousestatus[SDL_BUTTON_LEFT] = 0;
3066 						}
3067 						if ( omousex >= start_x3 && omousey >= suby1 + 268 && omousex < start_x3 + 24 && omousey < suby1 + 284 )
3068 						{
3069 							if ( !strncmp(mapflagtext[MAP_FLAG_DISABLEOPENING], "[x]", 3) )
3070 							{
3071 								strcpy(mapflagtext[MAP_FLAG_DISABLEOPENING], "[ ]");
3072 							}
3073 							else
3074 							{
3075 								strcpy(mapflagtext[MAP_FLAG_DISABLEOPENING], "[x]");
3076 							}
3077 							mousestatus[SDL_BUTTON_LEFT] = 0;
3078 						}
3079 						if ( omousex >= start_x3 && omousey >= suby1 + 292 && omousex < start_x3 + 24 && omousey < suby1 + 308 )
3080 						{
3081 							if ( !strncmp(mapflagtext[MAP_FLAG_DISABLEMESSAGES], "[x]", 3) )
3082 							{
3083 								strcpy(mapflagtext[MAP_FLAG_DISABLEMESSAGES], "[ ]");
3084 							}
3085 							else
3086 							{
3087 								strcpy(mapflagtext[MAP_FLAG_DISABLEMESSAGES], "[x]");
3088 							}
3089 							mousestatus[SDL_BUTTON_LEFT] = 0;
3090 						}
3091 						if ( omousex >= start_x3 && omousey >= suby1 + 316 && omousex < start_x3 + 24 && omousey < suby1 + 332 )
3092 						{
3093 							if ( !strncmp(mapflagtext[MAP_FLAG_DISABLEHUNGER], "[x]", 3) )
3094 							{
3095 								strcpy(mapflagtext[MAP_FLAG_DISABLEHUNGER], "[ ]");
3096 							}
3097 							else
3098 							{
3099 								strcpy(mapflagtext[MAP_FLAG_DISABLEHUNGER], "[x]");
3100 							}
3101 							mousestatus[SDL_BUTTON_LEFT] = 0;
3102 						}
3103 
3104 						start_y = suby1 + 40;
3105 						pad_y1 = 0;
3106 						if ( omousex >= subx1 + 4 && omousey >= start_y + pad_y1 && omousex < subx2 - 4 && omousey < start_y + pad_y1 + 16 )
3107 						{
3108 							inputstr = nametext;
3109 							editproperty = 0;
3110 							cursorflash = ticks;
3111 						}
3112 						pad_y1 += 36;
3113 						if ( omousex >= subx1 + 4 && omousey >= start_y + pad_y1 && omousex < subx2 - 4 && omousey < start_y + pad_y1 + 16 )
3114 						{
3115 							inputstr = authortext;
3116 							editproperty = 1;
3117 							cursorflash = ticks;
3118 						}
3119 						pad_y1 += 24;
3120 						if ( omousex >= subx1 + 104 && omousey >= start_y + pad_y1 && omousex < subx1 + 104 + 64 && omousey < start_y + pad_y1 + 16 )
3121 						{
3122 							inputstr = skyboxtext;
3123 							editproperty = 2;
3124 							cursorflash = ticks;
3125 						}
3126 						pad_y1 += 24;
3127 						if ( omousex >= subx1 + 104 && omousey >= start_y + pad_y1 && omousex < subx1 + 104 + 64 && omousey < start_y + pad_y1 + 16 )
3128 						{
3129 							inputstr = mapflagtext[MAP_FLAG_CEILINGTILE];
3130 							editproperty = 3;
3131 							cursorflash = ticks;
3132 						}
3133 						pad_y1 += 24;
3134 						if ( omousex >= subx1 + 104 && omousey >= start_y + pad_y1 && omousex < subx1 + 104 + 24 && omousey < start_y + pad_y1 + 16 )
3135 						{
3136 							inputstr = mapflagtext[MAP_FLAG_GENTOTALMIN];
3137 							editproperty = 4;
3138 							cursorflash = ticks;
3139 						}
3140 						if ( omousex >= subx1 + 144 && omousey >= start_y + pad_y1 && omousex < subx1 + 144 + 24 && omousey < start_y + pad_y1 + 16 )
3141 						{
3142 							inputstr = mapflagtext[MAP_FLAG_GENTOTALMAX];
3143 							editproperty = 5;
3144 							cursorflash = ticks;
3145 						}
3146 						pad_y1 += 24;
3147 						if ( omousex >= subx1 + 104 && omousey >= start_y + pad_y1 && omousex < subx1 + 104 + 24 && omousey < start_y + pad_y1 + 16 )
3148 						{
3149 							inputstr = mapflagtext[MAP_FLAG_GENMONSTERMIN];
3150 							editproperty = 6;
3151 							cursorflash = ticks;
3152 						}
3153 						if ( omousex >= subx1 + 144 && omousey >= start_y + pad_y1 && omousex < subx1 + 144 + 24 && omousey < start_y + pad_y1 + 16 )
3154 						{
3155 							inputstr = mapflagtext[MAP_FLAG_GENMONSTERMAX];
3156 							editproperty = 7;
3157 							cursorflash = ticks;
3158 						}
3159 						pad_y1 += 24;
3160 						if ( omousex >= subx1 + 104 && omousey >= start_y + pad_y1 && omousex < subx1 + 104 + 24 && omousey < start_y + pad_y1 + 16 )
3161 						{
3162 							inputstr = mapflagtext[MAP_FLAG_GENLOOTMIN];
3163 							editproperty = 8;
3164 							cursorflash = ticks;
3165 						}
3166 						if ( omousex >= subx1 + 144 && omousey >= start_y + pad_y1 && omousex < subx1 + 144 + 24 && omousey < start_y + pad_y1 + 16 )
3167 						{
3168 							inputstr = mapflagtext[MAP_FLAG_GENLOOTMAX];
3169 							editproperty = 9;
3170 							cursorflash = ticks;
3171 						}
3172 						pad_y1 += 24;
3173 						if ( omousex >= subx1 + 104 && omousey >= start_y + pad_y1 && omousex < subx1 + 104 + 24 && omousey < start_y + pad_y1 + 16 )
3174 						{
3175 							inputstr = mapflagtext[MAP_FLAG_GENDECORATIONMIN];
3176 							editproperty = 10;
3177 							cursorflash = ticks;
3178 						}
3179 						if ( omousex >= subx1 + 144 && omousey >= start_y + pad_y1 && omousex < subx1 + 144 + 24 && omousey < start_y + pad_y1 + 16 )
3180 						{
3181 							inputstr = mapflagtext[MAP_FLAG_GENDECORATIONMAX];
3182 							editproperty = 11;
3183 							cursorflash = ticks;
3184 						}
3185 
3186 						if ( omousex >= subx1 + 104 && omousey >= suby2 - 48 && omousex < subx1 + 168 && omousey < suby2 - 32 )
3187 						{
3188 							inputstr = widthtext;
3189 							editproperty = 12;
3190 							cursorflash = ticks;
3191 						}
3192 						if ( omousex >= subx1 + 104 && omousey >= suby2 - 24 && omousex < subx1 + 168 && omousey < suby2 - 8 )
3193 						{
3194 							inputstr = heighttext;
3195 							editproperty = 13;
3196 							cursorflash = ticks;
3197 						}
3198 					}
3199 
3200 					start_y = suby1 + 44;
3201 					pad_y1 = 0;
3202 
3203 					if ( editproperty == 0 )   // edit map name
3204 					{
3205 						if ( !SDL_IsTextInputActive() )
3206 						{
3207 							SDL_StartTextInput();
3208 							inputstr = nametext;
3209 						}
3210 						//strncpy(nametext,inputstr,31);
3211 						inputlen = 31;
3212 						if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
3213 						{
3214 							printText(font8x8_bmp, subx1 + 8 + strlen(nametext) * 8, start_y + pad_y1, "\26");
3215 						}
3216 					}
3217 					pad_y1 += 36;
3218 					if ( editproperty == 1 )   // edit author name
3219 					{
3220 						if ( !SDL_IsTextInputActive() )
3221 						{
3222 							SDL_StartTextInput();
3223 							inputstr = authortext;
3224 						}
3225 						//strncpy(authortext,inputstr,31);
3226 						inputlen = 31;
3227 						if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
3228 						{
3229 							printText(font8x8_bmp, subx1 + 8 + strlen(authortext) * 8, start_y + pad_y1, "\26");
3230 						}
3231 					}
3232 					pad_y1 += 24;
3233 					if ( editproperty == 2 )   // edit map skybox
3234 					{
3235 						if ( !SDL_IsTextInputActive() )
3236 						{
3237 							SDL_StartTextInput();
3238 							inputstr = skyboxtext;
3239 						}
3240 						//strncpy(widthtext,inputstr,3);
3241 						inputlen = 3;
3242 						if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
3243 						{
3244 							printText(font8x8_bmp, subx1 + 108 + strlen(skyboxtext) * 8, start_y + pad_y1, "\26");
3245 						}
3246 					}
3247 					pad_y1 += 24;
3248 					if ( editproperty == 3 )   // edit map ceiling tiles
3249 					{
3250 						if ( !SDL_IsTextInputActive() )
3251 						{
3252 							SDL_StartTextInput();
3253 							inputstr = mapflagtext[MAP_FLAG_CEILINGTILE];
3254 						}
3255 						//strncpy(widthtext,inputstr,3);
3256 						inputlen = 3;
3257 						if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
3258 						{
3259 							printText(font8x8_bmp, subx1 + 108 + strlen(mapflagtext[MAP_FLAG_CEILINGTILE]) * 8, start_y + pad_y1, "\26");
3260 						}
3261 					}
3262 					if ( editproperty == 12 )   // edit map width
3263 					{
3264 						if ( !SDL_IsTextInputActive() )
3265 						{
3266 							SDL_StartTextInput();
3267 							inputstr = widthtext;
3268 						}
3269 						//strncpy(widthtext,inputstr,3);
3270 						inputlen = 3;
3271 						if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
3272 						{
3273 							printText(font8x8_bmp, subx1 + 108 + strlen(widthtext) * 8, suby2 - 44, "\26");
3274 						}
3275 					}
3276 					if ( editproperty == 13 )   // edit map height
3277 					{
3278 						if ( !SDL_IsTextInputActive() )
3279 						{
3280 							SDL_StartTextInput();
3281 							inputstr = heighttext;
3282 						}
3283 						//strncpy(heighttext,inputstr,3);
3284 						inputlen = 3;
3285 						if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
3286 						{
3287 							printText(font8x8_bmp, subx1 + 108 + strlen(heighttext) * 8, suby2 - 20, "\26");
3288 						}
3289 					}
3290 					pad_y1 += 24;
3291 					if ( editproperty == 4 )   // edit min entity gen
3292 					{
3293 						if ( !SDL_IsTextInputActive() )
3294 						{
3295 							SDL_StartTextInput();
3296 							inputstr = mapflagtext[MAP_FLAG_GENTOTALMIN];
3297 						}
3298 						inputlen = 2;
3299 						if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
3300 						{
3301 							printText(font8x8_bmp, subx1 + 108 + strlen(mapflagtext[MAP_FLAG_GENTOTALMIN]) * 8, start_y + pad_y1, "\26");
3302 						}
3303 					}
3304 					if ( editproperty == 5 )   // edit max entity gen
3305 					{
3306 						if ( !SDL_IsTextInputActive() )
3307 						{
3308 							SDL_StartTextInput();
3309 							inputstr = mapflagtext[MAP_FLAG_GENTOTALMAX];
3310 						}
3311 						inputlen = 2;
3312 						if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
3313 						{
3314 							printText(font8x8_bmp, subx1 + 148 + strlen(mapflagtext[MAP_FLAG_GENTOTALMAX]) * 8, start_y + pad_y1, "\26");
3315 						}
3316 					}
3317 					pad_y1 += 24;
3318 					if ( editproperty == 6 )   // edit min monster gen
3319 					{
3320 						if ( !SDL_IsTextInputActive() )
3321 						{
3322 							SDL_StartTextInput();
3323 							inputstr = mapflagtext[MAP_FLAG_GENMONSTERMIN];
3324 						}
3325 						inputlen = 2;
3326 						if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
3327 						{
3328 							printText(font8x8_bmp, subx1 + 108 + strlen(mapflagtext[MAP_FLAG_GENMONSTERMIN]) * 8, start_y + pad_y1, "\26");
3329 						}
3330 					}
3331 					if ( editproperty == 7 )   // edit max monster gen
3332 					{
3333 						if ( !SDL_IsTextInputActive() )
3334 						{
3335 							SDL_StartTextInput();
3336 							inputstr = mapflagtext[MAP_FLAG_GENMONSTERMAX];
3337 						}
3338 						inputlen = 2;
3339 						if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
3340 						{
3341 							printText(font8x8_bmp, subx1 + 148 + strlen(mapflagtext[MAP_FLAG_GENMONSTERMAX]) * 8, start_y + pad_y1, "\26");
3342 						}
3343 					}
3344 					pad_y1 += 24;
3345 					if ( editproperty == 8 )   // edit min monster gen
3346 					{
3347 						if ( !SDL_IsTextInputActive() )
3348 						{
3349 							SDL_StartTextInput();
3350 							inputstr = mapflagtext[MAP_FLAG_GENLOOTMIN];
3351 						}
3352 						inputlen = 2;
3353 						if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
3354 						{
3355 							printText(font8x8_bmp, subx1 + 108 + strlen(mapflagtext[MAP_FLAG_GENLOOTMIN]) * 8, start_y + pad_y1, "\26");
3356 						}
3357 					}
3358 					if ( editproperty == 9 )   // edit max monster gen
3359 					{
3360 						if ( !SDL_IsTextInputActive() )
3361 						{
3362 							SDL_StartTextInput();
3363 							inputstr = mapflagtext[MAP_FLAG_GENLOOTMAX];
3364 						}
3365 						inputlen = 2;
3366 						if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
3367 						{
3368 							printText(font8x8_bmp, subx1 + 148 + strlen(mapflagtext[MAP_FLAG_GENLOOTMAX]) * 8, start_y + pad_y1, "\26");
3369 						}
3370 					}
3371 					pad_y1 += 24;
3372 					if ( editproperty == 10 )   // edit min decoration gen
3373 					{
3374 						if ( !SDL_IsTextInputActive() )
3375 						{
3376 							SDL_StartTextInput();
3377 							inputstr = mapflagtext[MAP_FLAG_GENDECORATIONMIN];
3378 						}
3379 						inputlen = 2;
3380 						if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
3381 						{
3382 							printText(font8x8_bmp, subx1 + 108 + strlen(mapflagtext[MAP_FLAG_GENDECORATIONMIN]) * 8, start_y + pad_y1, "\26");
3383 						}
3384 					}
3385 					if ( editproperty == 11 )   // edit max decoration gen
3386 					{
3387 						if ( !SDL_IsTextInputActive() )
3388 						{
3389 							SDL_StartTextInput();
3390 							inputstr = mapflagtext[MAP_FLAG_GENDECORATIONMAX];
3391 						}
3392 						inputlen = 2;
3393 						if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
3394 						{
3395 							printText(font8x8_bmp, subx1 + 148 + strlen(mapflagtext[MAP_FLAG_GENDECORATIONMAX]) * 8, start_y + pad_y1, "\26");
3396 						}
3397 					}
3398 				}
3399 				else if ( newwindow == 2 )
3400 				{
3401 					if ( selectedEntity != NULL )
3402 					{
3403 						spriteStats = selectedEntity->getStats();
3404 						if ( spriteStats != nullptr )
3405 						{
3406 							int numProperties = sizeof(monsterPropertyNames) / sizeof(monsterPropertyNames[0]); //find number of entries in property list
3407 							const int lenProperties = sizeof(monsterPropertyNames[0]) / sizeof(char); //find length of entry in property list
3408 							int spacing = 20; // px between each item in the list.
3409 							int pad_y1 = suby1 + 28; // 28 px spacing from subwindow start.
3410 							int pad_x1 = subx1 + 8; // 8px spacing from subwindow start.
3411 							int pad_x2 = 64;
3412 							int pad_y2 = suby1 + 28 + 2 * spacing;
3413 							int pad_x3 = 44; //property field width
3414 							int pad_x4;
3415 							Uint32 color = SDL_MapRGB(mainsurface->format, 255, 255, 255);
3416 							char tmpPropertyName[lenProperties] = "";
3417 							for ( int i = 0; i < numProperties; i++ )
3418 							{
3419 								strcpy(tmpPropertyName, monsterPropertyNames[i]);
3420 								pad_y1 = suby1 + 28 + i * spacing;
3421 
3422 								// value of 0 is name field, should be longer
3423 								if ( i == 0 )
3424 								{
3425 									drawDepressed(pad_x1 - 4, pad_y1 + 16 - 4, subx2 - 4, pad_y1 + 28);
3426 									// print values on top of boxes
3427 									printTextFormattedColor(font8x8_bmp, pad_x1, pad_y1, color, tmpPropertyName);
3428 									printText(font8x8_bmp, pad_x1, pad_y1 + 16, spriteProperties[i]);
3429 								}
3430 								else
3431 								{
3432 									pad_y1 += spacing;
3433 									if ( i < 7 )
3434 									{
3435 										if ( i < 3 ) //hp
3436 										{
3437 											color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
3438 										}
3439 										else if ( i < 5 ) //mp
3440 										{
3441 											color = SDL_MapRGB(mainsurface->format, 0, 255, 228);
3442 										}
3443 										else if ( i == 5 ) //level
3444 										{
3445 											color = SDL_MapRGB(mainsurface->format, 255, 192, 0);
3446 										}
3447 										else if ( i == 6 ) //gold
3448 										{
3449 											color = SDL_MapRGB(mainsurface->format, 255, 192, 0);
3450 										}
3451 										drawDepressed(pad_x1 + pad_x2 - 4, pad_y1 - 4, pad_x1 + pad_x2 + pad_x3 - 4, pad_y1 + 16 - 4);
3452 										// draw another box side by side, spaced by pad_x3 + 16
3453 										drawDepressed(pad_x1 + pad_x2 - 4 + (pad_x3 + 16), pad_y1 - 4, pad_x1 + pad_x2 + pad_x3 - 4 + (pad_x3 + 16), pad_y1 + 16 - 4);
3454 										// print values on top of boxes
3455 										// print property name
3456 										printTextFormattedColor(font8x8_bmp, pad_x1, pad_y1, color, tmpPropertyName);
3457 										// print dash between boxes
3458 										printTextFormattedColor(font8x8_bmp, pad_x1 + pad_x2 - 4 + (pad_x3 + 4), pad_y1, color, "-");
3459 										// print left text
3460 										printText(font8x8_bmp, pad_x1 + pad_x2, pad_y1, spriteProperties[i]);
3461 										// print right text
3462 										printText(font8x8_bmp, pad_x1 + pad_x2 + (pad_x3 + 16), pad_y1, spriteProperties[i + 12]);
3463 									}
3464 									else if ( i < 13 )
3465 									{
3466 										color = SDL_MapRGB(mainsurface->format, 255, 255, 255);
3467 										pad_y1 += spacing + 10;
3468 										drawDepressed(pad_x1 + pad_x2 - 4, pad_y1 - 4, pad_x1 + pad_x2 + pad_x3 - 4, pad_y1 + 16 - 4);
3469 										// draw another box side by side, spaced by pad_x3 + 16
3470 										drawDepressed(pad_x1 + pad_x2 - 4 + (pad_x3 + 16), pad_y1 - 4, pad_x1 + pad_x2 + pad_x3 - 4 + (pad_x3 + 16), pad_y1 + 16 - 4);
3471 										// print values on top of boxes
3472 										// print property name
3473 										printTextFormattedColor(font8x8_bmp, pad_x1, pad_y1, color, tmpPropertyName);
3474 										// print dash between boxes
3475 										printTextFormattedColor(font8x8_bmp, pad_x1 + pad_x2 - 4 + (pad_x3 + 4), pad_y1, color, "-");
3476 										// print left text
3477 										printText(font8x8_bmp, pad_x1 + pad_x2, pad_y1, spriteProperties[i]);
3478 										// print right text
3479 										printText(font8x8_bmp, pad_x1 + pad_x2 + (pad_x3 + 16), pad_y1, spriteProperties[i + 12]);
3480 									}
3481 									else if ( i >= 13 )
3482 									{
3483 										if ( i == 13 )
3484 										{
3485 											pad_y1 += 10;
3486 										}
3487 										color = SDL_MapRGB(mainsurface->format, 255, 255, 255);
3488 										pad_y1 += spacing + 10;
3489 										drawDepressed(pad_x1 + pad_x2 - 4, pad_y1 - 4, pad_x1 + pad_x2 + pad_x3 - 4, pad_y1 + 16 - 4);
3490 										// print property name
3491 										printTextFormattedColor(font8x8_bmp, pad_x1, pad_y1, color, tmpPropertyName);
3492 										// print left text
3493 										printText(font8x8_bmp, pad_x1 + pad_x2, pad_y1, spriteProperties[i + 12]);
3494 										if ( i == 13 && spriteStats->type == SHOPKEEPER )
3495 										{
3496 											char shopTypeText[32] = "";
3497 											color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
3498 											switch ( atoi(spriteProperties[25]) )
3499 											{
3500 												case 1:
3501 													strcpy(shopTypeText, "Arms and Armor");
3502 													break;
3503 												case 2:
3504 													strcpy(shopTypeText, "Hats and Helmets");
3505 													break;
3506 												case 3:
3507 													strcpy(shopTypeText, "Jewelry");
3508 													break;
3509 												case 4:
3510 													strcpy(shopTypeText, "Bookstore");
3511 													break;
3512 												case 5:
3513 													strcpy(shopTypeText, "Apothecary");
3514 													break;
3515 												case 6:
3516 													strcpy(shopTypeText, "Magistaffs");
3517 													break;
3518 												case 7:
3519 													strcpy(shopTypeText, "Food Store");
3520 													break;
3521 												case 8:
3522 													strcpy(shopTypeText, "Hardware Store");
3523 													break;
3524 												case 9:
3525 													strcpy(shopTypeText, "Lighting Store");
3526 													break;
3527 												case 10:
3528 													strcpy(shopTypeText, "General Store");
3529 													break;
3530 												default:
3531 													strcpy(shopTypeText, "Default Random Store");
3532 													color = SDL_MapRGB(mainsurface->format, 255, 255, 255);
3533 													break;
3534 											}
3535 											printTextFormattedColor(font8x8_bmp, pad_x1 + pad_x2 + pad_x3 + 8, pad_y1, color, shopTypeText);
3536 											color = SDL_MapRGB(mainsurface->format, 255, 255, 255);
3537 										}
3538 									}
3539 								}
3540 							}
3541 
3542 							// Cycle properties with TAB.
3543 							if ( keystatus[SDL_SCANCODE_TAB] )
3544 							{
3545 								keystatus[SDL_SCANCODE_TAB] = 0;
3546 								cursorflash = ticks;
3547 								editproperty++;
3548 								if ( editproperty == numProperties * 2 - 2 )
3549 								{
3550 									// limit of properties is twice the vertical count
3551 									editproperty = 0;
3552 								}
3553 
3554 								inputstr = spriteProperties[editproperty];
3555 							}
3556 							// select a textbox
3557 							if ( mousestatus[SDL_BUTTON_LEFT] )
3558 							{
3559 								for ( int i = 0; i < numProperties; i++ )
3560 								{
3561 									pad_y1 = suby1 + 28 + i * spacing;
3562 									if ( i == 0 )
3563 									{
3564 										if ( omousex >= pad_x1 - 4 && omousey >= pad_y1 + 16 - 4 && omousex < subx2 - 4 && omousey < pad_y1 + 32 - 4 )
3565 										{
3566 											inputstr = spriteProperties[i];
3567 											editproperty = i;
3568 											cursorflash = ticks;
3569 										}
3570 									}
3571 									else
3572 									{
3573 										pad_y1 += spacing;
3574 										if ( i < 7 )
3575 										{
3576 											// check if mouse is in left property box
3577 											if ( omousex >= pad_x1 + pad_x2 - 4 && omousey >= pad_y1 - 4 && omousex < pad_x1 + pad_x2 + pad_x3 - 4 && omousey < pad_y1 + 16 - 4 )
3578 											{
3579 												inputstr = spriteProperties[i];
3580 												editproperty = i;
3581 												cursorflash = ticks;
3582 											}
3583 											// check if mouse is in right property box (offset from above by pad_x3 + 16)
3584 											else if ( omousex >= pad_x1 + pad_x2 - 4 + (pad_x3 + 16) && omousey >= pad_y1 - 4 && omousex < pad_x1 + pad_x2 + pad_x3 - 4 + (pad_x3 + 16) && omousey < pad_y1 + 16 - 4 )
3585 											{
3586 												inputstr = spriteProperties[i + 12];
3587 												editproperty = i + 12;
3588 												cursorflash = ticks;
3589 											}
3590 										}
3591 										else if ( i < 13 )
3592 										{
3593 											pad_y1 += spacing + 10;
3594 											// check if mouse is in left property box
3595 											if ( omousex >= pad_x1 + pad_x2 - 4 && omousey >= pad_y1 - 4 && omousex < pad_x1 + pad_x2 + pad_x3 - 4 && omousey < pad_y1 + 16 - 4 )
3596 											{
3597 												inputstr = spriteProperties[i];
3598 												editproperty = i;
3599 												cursorflash = ticks;
3600 											}
3601 											// check if mouse is in right property box (offset from above by pad_x3 + 16)
3602 											else if ( omousex >= pad_x1 + pad_x2 - 4 + (pad_x3 + 16) && omousey >= pad_y1 - 4 && omousex < pad_x1 + pad_x2 + pad_x3 - 4 + (pad_x3 + 16) && omousey < pad_y1 + 16 - 4 )
3603 											{
3604 												inputstr = spriteProperties[i + 12];
3605 												editproperty = i + 12;
3606 												cursorflash = ticks;
3607 											}
3608 										}
3609 										else if ( i >= 13 )
3610 										{
3611 											if ( i == 13 )
3612 											{
3613 												pad_y1 += 10;
3614 											}
3615 											pad_y1 += spacing + 10;
3616 											// check if mouse is in left property box
3617 											if ( omousex >= pad_x1 + pad_x2 - 4 && omousey >= pad_y1 - 4 && omousex < pad_x1 + pad_x2 + pad_x3 - 4 && omousey < pad_y1 + 16 - 4 )
3618 											{
3619 												inputstr = spriteProperties[i + 12];
3620 												editproperty = i + 12;
3621 												cursorflash = ticks;
3622 											}
3623 										}
3624 									}
3625 								}
3626 							}
3627 
3628 							//items for monster
3629 							pad_y2 = suby1 + 28 + 2 * spacing;
3630 							pad_x3 = 40;
3631 							pad_x4 = subx2 - 112;
3632 							printTextFormattedColor(font8x8_bmp, pad_x4 - 8, pad_y2, color, " Helm");
3633 
3634 							//pad_y2 += spacing * 2 - 16;
3635 							pad_y2 += spacing * 2;
3636 							printTextFormattedColor(font8x8_bmp, pad_x4 - 8, pad_y2, color, "Amulet");
3637 
3638 							//pad_x4 += 64 * 2;
3639 							pad_y2 += spacing * 2;
3640 							printTextFormattedColor(font8x8_bmp, pad_x4 - 4, pad_y2, color, "Armor");
3641 
3642 							//pad_x4 -= 64;
3643 							//pad_y2 += spacing * 2 - 16;
3644 							pad_y2 += spacing * 2;
3645 							printTextFormattedColor(font8x8_bmp, pad_x4 - 8 - 4, pad_y2, color, " Boots");
3646 
3647 							pad_y2 = suby1 + 28 + 2 * spacing;
3648 							pad_y2 += 16;
3649 							pad_x4 -= 64;
3650 							printTextFormattedColor(font8x8_bmp, pad_x4 - 8 - 4, pad_y2, color, " Cloak");
3651 
3652 							pad_x4 += 64 * 2;
3653 							printTextFormattedColor(font8x8_bmp, pad_x4 - 8, pad_y2, color, " Mask");
3654 
3655 							pad_x4 -= 64 * 2;
3656 							pad_y2 += spacing * 2;
3657 							printTextFormattedColor(font8x8_bmp, pad_x4 - 8, pad_y2, color, "Weapon");
3658 
3659 							pad_x4 += 64 * 2;
3660 							printTextFormattedColor(font8x8_bmp, pad_x4 - 8, pad_y2, color, "Shield");
3661 
3662 							pad_x4 -= 64 * 2;
3663 							pad_y2 += spacing * 2;
3664 							printTextFormattedColor(font8x8_bmp, pad_x4 - 8, pad_y2, color, " Ring");
3665 
3666 							pad_x4 += 64 * 2;
3667 							printTextFormattedColor(font8x8_bmp, pad_x4 - 8, pad_y2, color, "Gloves");
3668 
3669 							pad_x4 -= 64 * 2;
3670 
3671 							pad_y2 += 32 + spacing * 2;
3672 							printTextFormattedColor(font8x8_bmp, pad_x4 - 8, pad_y2, color, "Inventory");
3673 
3674 							pad_y2 += spacing * 3 + 8;
3675 							if ( !strcmp(spriteProperties[31], "disable") )
3676 							{
3677 								printTextFormattedColor(font8x8_bmp, pad_x4 - 8, pad_y2, color, "Disable Miniboss: [x]");
3678 							}
3679 							else
3680 							{
3681 								printTextFormattedColor(font8x8_bmp, pad_x4 - 8, pad_y2, color, "Disable Miniboss: [ ]");
3682 							}
3683 							if ( mousestatus[SDL_BUTTON_LEFT] )
3684 							{
3685 								int checkbox_x1 = pad_x4 - 8 + strlen("Disable Miniboss: ") * 8;
3686 								int checkbox_x2 = checkbox_x1 + strlen("[ ]") * 8;
3687 								if ( omousex >= checkbox_x1 && omousey >= pad_y2 && omousex < checkbox_x2 && omousey < pad_y2 + 8 )
3688 								{
3689 									mousestatus[SDL_BUTTON_LEFT] = 0;
3690 									if ( !strcmp(spriteProperties[31], "disable") )
3691 									{
3692 										strcpy(spriteProperties[31], "");
3693 									}
3694 									else
3695 									{
3696 										strcpy(spriteProperties[31], "disable");
3697 									}
3698 								}
3699 							}
3700 
3701 							if ( editproperty < numProperties * 2 - 2 )   // edit property values
3702 							{
3703 								// limit of properties is twice the vertical count
3704 								if ( !SDL_IsTextInputActive() )
3705 								{
3706 									SDL_StartTextInput();
3707 									inputstr = spriteProperties[0];
3708 								}
3709 								//strncpy(nametext,inputstr,31);
3710 
3711 								// value of 0 is the name field, else the input is a number
3712 								if ( editproperty == 0 )
3713 								{
3714 									inputlen = 31;
3715 								}
3716 								else
3717 								{
3718 									inputlen = 4;
3719 								}
3720 								if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
3721 								{
3722 									pad_y1 = suby1 + 28 + editproperty * spacing;
3723 
3724 									if ( editproperty == 0 )
3725 									{
3726 										printText(font8x8_bmp, pad_x1 + strlen(spriteProperties[editproperty]) * 8, pad_y1 + 16, "\26");
3727 									}
3728 									else if ( editproperty < 7 )
3729 									{
3730 										pad_y1 += spacing;
3731 										// left box
3732 										printText(font8x8_bmp, pad_x1 + pad_x2 + strlen(spriteProperties[editproperty]) * 8, pad_y1, "\26");
3733 									}
3734 									else if ( editproperty < 13 )
3735 									{
3736 										pad_y1 += spacing;
3737 										pad_y1 += spacing + 10;
3738 										// left box
3739 										printText(font8x8_bmp, pad_x1 + pad_x2 + strlen(spriteProperties[editproperty]) * 8, pad_y1, "\26");
3740 									}
3741 									else if ( editproperty < 19 )
3742 									{
3743 										pad_y1 = suby1 + 28 + (editproperty - 12) * spacing;
3744 										pad_y1 += spacing;
3745 										// right box
3746 										printText(font8x8_bmp, pad_x1 + pad_x2 + (pad_x3 + 20) + strlen(spriteProperties[editproperty]) * 8, pad_y1, "\26");
3747 									}
3748 									else if ( editproperty < 25 )
3749 									{
3750 										pad_y1 = suby1 + 28 + (editproperty - 12) * spacing;
3751 										pad_y1 += spacing;
3752 										pad_y1 += spacing + 10;
3753 										// right box
3754 										printText(font8x8_bmp, pad_x1 + pad_x2 + (pad_x3 + 20) + strlen(spriteProperties[editproperty]) * 8, pad_y1, "\26");
3755 									}
3756 									else if ( editproperty >= 25 )
3757 									{
3758 										pad_y1 = suby1 + 28 + (editproperty - 12) * spacing;
3759 										pad_y1 += spacing;
3760 										pad_y1 += spacing + 20;
3761 										// left box
3762 										printText(font8x8_bmp, pad_x1 + pad_x2 + strlen(spriteProperties[editproperty]) * 8, pad_y1, "\26");
3763 									}
3764 								}
3765 							}
3766 						}
3767 					}
3768 				}
3769 				else if ( newwindow == 3 )
3770 				{
3771 					if ( selectedEntity != NULL )
3772 					{
3773 						int numProperties = sizeof(chestPropertyNames) / sizeof(chestPropertyNames[0]); //find number of entries in property list
3774 						const int lenProperties = sizeof(chestPropertyNames[0]) / sizeof(char); //find length of entry in property list
3775 						int spacing = 36; // 36 px between each item in the list.
3776 						int pad_y1 = suby1 + 28; // 28 px spacing from subwindow start.
3777 						int pad_x1 = subx1 + 8; // 8px spacing from subwindow start.
3778 						int pad_x2 = 64;
3779 						int pad_x3 = pad_x1 + pad_x2 + 8;
3780 						int pad_y2 = 0;
3781 						char tmpPropertyName[lenProperties] = "";
3782 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
3783 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
3784 
3785 						for ( int i = 0; i < numProperties; i++ )
3786 						{
3787 							int propertyInt = atoi(spriteProperties[i]);
3788 
3789 							strcpy(tmpPropertyName, chestPropertyNames[i]);
3790 							pad_y1 = suby1 + 28 + i * spacing;
3791 							pad_y2 = suby1 + 44 + i * spacing;
3792 							// box outlines then text
3793 							drawDepressed(pad_x1 - 4, suby1 + 40 + i * spacing, pad_x1 - 4 + pad_x2, suby1 + 56 + i * spacing);
3794 							// print values on top of boxes
3795 							printText(font8x8_bmp, pad_x1, suby1 + 44 + i * spacing, spriteProperties[i]);
3796 							printText(font8x8_bmp, pad_x1, pad_y1, tmpPropertyName);
3797 
3798 							if ( errorArr[i] != 1 )
3799 							{
3800 								if ( i == 0 )
3801 								{
3802 									if ( propertyInt > 3 || propertyInt < 0 )
3803 									{
3804 										errorMessage = 60;
3805 										errorArr[i] = 1;
3806 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 1); //reset
3807 									}
3808 									else
3809 									{
3810 										color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
3811 										char tmpStr[32] = "";
3812 										if ( propertyInt == 0 )
3813 										{
3814 											strcpy(tmpStr, "EAST");
3815 										}
3816 										else if ( propertyInt == 1 )
3817 										{
3818 											strcpy(tmpStr, "SOUTH");
3819 										}
3820 										else if ( propertyInt == 2 )
3821 										{
3822 											strcpy(tmpStr, "WEST");
3823 										}
3824 										else if ( propertyInt == 3 )
3825 										{
3826 											strcpy(tmpStr, "NORTH");
3827 										}
3828 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, color, tmpStr);
3829 									}
3830 								}
3831 								else if ( i == 1 )
3832 								{
3833 									if ( propertyInt > 8 || propertyInt < 0 )
3834 									{
3835 										errorMessage = 60;
3836 										errorArr[i] = 1;
3837 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 0); //reset
3838 									}
3839 								}
3840 								else if ( i == 2 )
3841 								{
3842 									if ( propertyInt > 100 || propertyInt < -1 )
3843 									{
3844 										errorMessage = 60;
3845 										errorArr[i] = 1;
3846 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 1); //reset
3847 									}
3848 									else if ( propertyInt == -1 )
3849 									{
3850 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, colorRandom, "Default 10%");
3851 									}
3852 									else
3853 									{
3854 										color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
3855 										char tmpStr[32] = "";
3856 										strcpy(tmpStr, spriteProperties[i]); //reset
3857 										strcat(tmpStr, " %%");
3858 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, color, tmpStr);
3859 									}
3860 								}
3861 							}
3862 
3863 							if ( errorMessage )
3864 							{
3865 								color = SDL_MapRGB(mainsurface->format, 255, 0, 0);
3866 								if ( errorArr[i] == 1 )
3867 								{
3868 									printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, color, "Invalid ID!");
3869 								}
3870 							}
3871 
3872 							pad_x1 = subx1 + 8;
3873 						}
3874 
3875 						pad_y1 = suby1 + 28 + 4 * spacing + 18;
3876 						pad_x1 += 18;
3877 						spacing = 18;
3878 						//printText(font8x8_bmp, pad_x1 + 16, pad_y1, "Chest Facing");
3879 						pad_y1 = suby1 + 28 + 7 * spacing;
3880 						printText(font8x8_bmp, pad_x1 + 32, pad_y1, "NORTH(3)");
3881 						pad_y1 = suby1 + 28 + 8 * spacing;
3882 						printText(font8x8_bmp, pad_x1, pad_y1, "WEST(2)");
3883 						printText(font8x8_bmp, pad_x1 + 96 - 16, pad_y1, "EAST(0)");
3884 						pad_y1 = suby1 + 28 + 9 * spacing;
3885 						printText(font8x8_bmp, pad_x1 + 32, pad_y1, "SOUTH(1)");
3886 
3887 						spacing = 14;
3888 						pad_y1 = suby1 + 14 + 14 * spacing;
3889 						pad_x1 = subx1 + 8 + 192;
3890 						pad_y1 = suby1 + 4 + 1 * spacing;
3891 						printText(font8x8_bmp, pad_x1, pad_y1, "Chest Types");
3892 						pad_y1 += spacing;
3893 						printText(font8x8_bmp, pad_x1, pad_y1, "0 - Random");
3894 						pad_y1 += spacing;
3895 						printText(font8x8_bmp, pad_x1, pad_y1, "1 - Garbage");
3896 						pad_y1 += spacing;
3897 						printText(font8x8_bmp, pad_x1, pad_y1, "2 - Food");
3898 						pad_y1 += spacing;
3899 						printText(font8x8_bmp, pad_x1, pad_y1, "3 - Jewelry");
3900 						pad_y1 += spacing;
3901 						printText(font8x8_bmp, pad_x1, pad_y1, "4 - Equipment");
3902 						pad_y1 += spacing;
3903 						printText(font8x8_bmp, pad_x1, pad_y1, "5 - Tools");
3904 						pad_y1 += spacing;
3905 						printText(font8x8_bmp, pad_x1, pad_y1, "6 - Magical");
3906 						pad_y1 += spacing;
3907 						printText(font8x8_bmp, pad_x1, pad_y1, "7 - Potions");
3908 						pad_y1 += spacing;
3909 						printText(font8x8_bmp, pad_x1, pad_y1, "8 - Empty");
3910 
3911 						pad_x1 = subx1 + 8;
3912 						pad_y1 = suby1 + 28;
3913 						spacing = 36;
3914 
3915 						// Cycle properties with TAB.
3916 						if ( keystatus[SDL_SCANCODE_TAB] )
3917 						{
3918 							keystatus[SDL_SCANCODE_TAB] = 0;
3919 							cursorflash = ticks;
3920 							editproperty++;
3921 							if ( editproperty == numProperties )
3922 							{
3923 								editproperty = 0;
3924 							}
3925 
3926 							inputstr = spriteProperties[editproperty];
3927 						}
3928 
3929 						// select a textbox
3930 						if ( mousestatus[SDL_BUTTON_LEFT] )
3931 						{
3932 							for ( int i = 0; i < numProperties; i++ )
3933 							{
3934 								if ( omousex >= pad_x1 - 4 && omousey >= suby1 + 40 + i * spacing && omousex < pad_x1 - 4 + pad_x2 && omousey < suby1 + 56 + i * spacing )
3935 								{
3936 									inputstr = spriteProperties[i];
3937 									editproperty = i;
3938 									cursorflash = ticks;
3939 								}
3940 								pad_x1 = subx1 + 8;
3941 							}
3942 						}
3943 						if ( editproperty < numProperties )   // edit
3944 						{
3945 							if ( !SDL_IsTextInputActive() )
3946 							{
3947 								SDL_StartTextInput();
3948 								inputstr = spriteProperties[0];
3949 							}
3950 							if ( editproperty == 2 )
3951 							{
3952 								inputlen = 3;
3953 							}
3954 							else
3955 							{
3956 								inputlen = 1;
3957 							}
3958 							if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
3959 							{
3960 								printText(font8x8_bmp, subx1 + 8 + strlen(spriteProperties[editproperty]) * 8, suby1 + 44 + editproperty * spacing, "\26");
3961 							}
3962 						}
3963 					}
3964 				}
3965 				else if ( newwindow == 4 || newwindow == 5 )
3966 				{
3967 					if ( selectedEntity != NULL )
3968 					{
3969 						int numProperties;
3970 
3971 						if ( newwindow == 4 )
3972 						{
3973 							numProperties = sizeof(itemPropertyNames) / sizeof(itemPropertyNames[0]); //find number of entries in property list
3974 						}
3975 						else if ( newwindow == 5 )
3976 						{
3977 							numProperties = sizeof(monsterItemPropertyNames) / sizeof(monsterItemPropertyNames[0]); //find number of entries in property list
3978 						}
3979 						const int lenProperties = 32;
3980 
3981 						int spacing = 36; // 36 px between each item in the list.
3982 						int verticalOffset = 20;
3983 						int pad_x1 = subx1 + 8 + 96 + 80; // 104 px spacing from subwindow start. handles right side item list
3984 						int pad_y1 = suby1 + 20 + verticalOffset; // 20 px spacing from subwindow start. handles right side item list
3985 						int pad_x2 = 64; // handles right side item list
3986 
3987 						int pad_y2 = (suby2 - 52 - 36) + verticalOffset - 4; //handles right side item list
3988 						int pad_x3 = subx1 + 8; //handles left side menu
3989 						int pad_y3 = suby1 + 28; // 28 px spacing from subwindow start, handles left side menu
3990 						int pad_x4 = 64; //handles left side menu-end
3991 						int pad_y4; //handles left side menu-end
3992 						int totalNumItems = (sizeof(itemNameStrings) / sizeof(itemNameStrings[0]));
3993 						int editorNumItems = totalNumItems /* - 1*/;
3994 						switch ( itemSlotSelected )
3995 						{
3996 							case -1:
3997 								break;
3998 							default:
3999 								if ( itemSlotSelected < 10 )
4000 								{
4001 									editorNumItems = 0;
4002 									for ( int i = 0; i < (sizeof(itemStringsByType[itemSlotSelected]) / sizeof(itemStringsByType[itemSlotSelected][0])); i++ )
4003 									{
4004 										if ( strcmp(itemStringsByType[itemSlotSelected][i], "") == 0) //look for the end of the array
4005 										{
4006 											i = totalNumItems;
4007 										}
4008 										editorNumItems++;
4009 									}
4010 								}
4011 								break;
4012 						}
4013 						int propertyInt = 0;
4014 						char tmpPropertyName[lenProperties] = "";
4015 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
4016 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
4017 						for ( int i = 0; i < numProperties; i++ )
4018 						{
4019 							if ( newwindow == 4 )
4020 							{
4021 								strcpy(tmpPropertyName, itemPropertyNames[i]);
4022 
4023 							}
4024 							else if ( newwindow == 5 )
4025 							{
4026 								strcpy(tmpPropertyName, monsterItemPropertyNames[i]);
4027 							}
4028 							pad_y3 = suby1 + 40 + spacing + i * spacing;
4029 							pad_y4 = suby1 + 44 + 12 + spacing + i * spacing;
4030 							// box outlines then text
4031 							drawDepressed(pad_x3 - 4, pad_y3, pad_x3 - 4 + pad_x2, pad_y4);
4032 							// print values on top of boxes
4033 							printText(font8x8_bmp, pad_x3, pad_y3 - 12, tmpPropertyName);
4034 							printText(font8x8_bmp, pad_x3, pad_y3 + 4, spriteProperties[i]);
4035 
4036 							propertyInt = atoi(spriteProperties[i]);
4037 
4038 							if ( errorArr[i] != 1 )
4039 							{
4040 								if ( i == 0 )
4041 								{
4042 									if ( newwindow == 4 )
4043 									{
4044 										if ( propertyInt > totalNumItems - 2 || propertyInt < 0 )
4045 										{
4046 											errorMessage = 60;
4047 											errorArr[i] = 1;
4048 											if ( propertyInt < 1 )
4049 											{
4050 												snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 1);
4051 											}
4052 											else
4053 											{
4054 												snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", editorNumItems - 2);
4055 											}
4056 										}
4057 										else if ( propertyInt == 0 )
4058 										{
4059 											errorMessage = 60;
4060 											errorArr[i] = 1;
4061 										}
4062 									}
4063 									else if ( newwindow == 5 )
4064 									{
4065 										if ( propertyInt > totalNumItems - 2 || propertyInt < 0 )
4066 										{
4067 											errorMessage = 60;
4068 											errorArr[i] = 1;
4069 											if ( propertyInt < 0 )
4070 											{
4071 												snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 0);
4072 											}
4073 											else
4074 											{
4075 												snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", editorNumItems - 2);
4076 											}
4077 										}
4078 									}
4079 								}
4080 								else if ( i == 1 )
4081 								{
4082 									if ( propertyInt == 2 )
4083 									{
4084 										color = SDL_MapRGB(mainsurface->format, 200, 128, 0);
4085 										printTextFormattedColor(font8x8_bmp, pad_x3 + pad_x4 + 8, pad_y3 + 4, color, "Decrepit");
4086 									}
4087 									else if ( propertyInt == 3 )
4088 									{
4089 										color = SDL_MapRGB(mainsurface->format, 255, 255, 0);
4090 										printTextFormattedColor(font8x8_bmp, pad_x3 + pad_x4 + 8, pad_y3 + 4, color, "Worn");
4091 									}
4092 									else if ( propertyInt == 4 )
4093 									{
4094 										color = SDL_MapRGB(mainsurface->format, 128, 200, 0);
4095 										printTextFormattedColor(font8x8_bmp, pad_x3 + pad_x4 + 8, pad_y3 + 4, color, "Servicable");
4096 									}
4097 									else if ( propertyInt == 5 )
4098 									{
4099 										color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
4100 										printTextFormattedColor(font8x8_bmp, pad_x3 + pad_x4 + 8, pad_y3 + 4, color, "Excellent");
4101 									}
4102 									else if ( propertyInt == 1 )
4103 									{
4104 										color = SDL_MapRGB(mainsurface->format, 255, 0, 0);
4105 										printTextFormattedColor(font8x8_bmp, pad_x3 + pad_x4 + 8, pad_y3 + 4, color, "Broken");
4106 									}
4107 									else if ( propertyInt == 0 )
4108 									{
4109 										printTextFormattedColor(font8x8_bmp, pad_x3 + pad_x4 + 8, pad_y3 + 4, colorRandom, "Random");
4110 									}
4111 									else if ( propertyInt < 0 || propertyInt > 5 )
4112 									{
4113 										errorMessage = 60;
4114 										errorArr[i] = 1;
4115 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 0); //reset
4116 									}
4117 								}
4118 								else if ( i == 2 )
4119 								{
4120 									if ( strcmp(spriteProperties[i], "00") == 0 )
4121 									{
4122 										printTextFormattedColor(font8x8_bmp, pad_x3 + pad_x4 + 8, pad_y3 + 4, colorRandom, "Random");
4123 									}
4124 									else if ( propertyInt > 9 || propertyInt < -9 )
4125 									{
4126 										errorMessage = 60;
4127 										errorArr[i] = 1;
4128 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 0); //reset
4129 									}
4130 								}
4131 								else if ( i == 3 )
4132 								{
4133 									if ( propertyInt > 99 || propertyInt < 0 )
4134 									{
4135 										errorMessage = 60;
4136 										errorArr[i] = 1;
4137 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 1); //reset
4138 									}
4139 									else if ( propertyInt == 0 )
4140 									{
4141 										color = SDL_MapRGB(mainsurface->format, 255, 0, 0);
4142 										printTextFormattedColor(font8x8_bmp, pad_x3 + pad_x4 + 8, pad_y3 + 4, color, "Invalid ID!");
4143 									}
4144 								}
4145 								else if ( i == 4 )
4146 								{
4147 									if ( propertyInt == 1 )
4148 									{
4149 										color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
4150 										printTextFormattedColor(font8x8_bmp, pad_x3 + pad_x4 + 8, pad_y3 + 4, color, "Identified");
4151 									}
4152 									else if ( propertyInt == 0 )
4153 									{
4154 										color = SDL_MapRGB(mainsurface->format, 255, 255, 0);
4155 										printTextFormattedColor(font8x8_bmp, pad_x3 + pad_x4 + 8, pad_y3 + 4, color, "Unidentified");
4156 									}
4157 									else if ( propertyInt == 2 )
4158 									{
4159 										printTextFormattedColor(font8x8_bmp, pad_x3 + pad_x4 + 8, pad_y3 + 4, colorRandom, "Random");
4160 									}
4161 									else
4162 									{
4163 										errorMessage = 60;
4164 										errorArr[i] = 1;
4165 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 0);
4166 									}
4167 								}
4168 								else if ( i == 5 && newwindow == 5)
4169 								{
4170 									if ( propertyInt > 100 || propertyInt < 0 )
4171 									{
4172 										errorMessage = 60;
4173 										errorArr[i] = 1;
4174 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 100); //reset
4175 									}
4176 									else if ( propertyInt == 0 )
4177 									{
4178 										color = SDL_MapRGB(mainsurface->format, 255, 0, 0);
4179 										printTextFormattedColor(font8x8_bmp, pad_x3 + pad_x4 + 8, pad_y3 + 4, color, "Invalid ID!");
4180 									}
4181 									else
4182 									{
4183 										color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
4184 										char tmpStr[32] = "";
4185 										strcpy(tmpStr, spriteProperties[i]); //reset
4186 										strcat(tmpStr, " %%");
4187 										printTextFormattedColor(font8x8_bmp, pad_x3 + pad_x4 + 8, pad_y3 + 4, color, tmpStr);
4188 									}
4189 								}
4190 								else if ( (i == 5 && newwindow == 4) || (i == 6 && newwindow == 5) )
4191 								{
4192 									if ( propertyInt > 16 || propertyInt < 0 )
4193 									{
4194 										errorMessage = 60;
4195 										errorArr[i] = 1;
4196 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 0); //reset
4197 									}
4198 									else if ( propertyInt >= 0 && propertyInt <= (static_cast<int>(sizeof(itemCategoryNames[propertyInt])) / static_cast<int>(sizeof(itemCategoryNames[propertyInt][0]))) )
4199 									{
4200 										if ( propertyInt == 0 )
4201 										{
4202 											color = colorRandom;
4203 										}
4204 										else
4205 										{
4206 											color = SDL_MapRGB(mainsurface->format, 200, 64, 220);
4207 										}
4208 
4209 										printTextFormattedColor(font8x8_bmp, pad_x3 + pad_x4 + 8, pad_y3 + 4, color, itemCategoryNames[propertyInt]);
4210 									}
4211 								}
4212 							}
4213 
4214 							if ( errorMessage )
4215 							{
4216 								color = SDL_MapRGB(mainsurface->format, 255, 0, 0);
4217 								if ( errorArr[i] == 1 )
4218 								{
4219 									printTextFormattedColor(font8x8_bmp, pad_x3 + pad_x4 + 8, pad_y3 + 4, color, "Invalid ID!");
4220 								}
4221 							}
4222 
4223 						}
4224 
4225 
4226 
4227 						drawDepressed(pad_x1, pad_y1, subx2 - 20, pad_y2);
4228 						drawDepressed(subx2 - 20, pad_y1, subx2 - 4, pad_y2);
4229 						slidersize = std::min<int>(((pad_y2 - 1) - (pad_y1 + 1)), ((pad_y2 - 1) - (pad_y1 + 1)) / ((real_t)(editorNumItems + 1) / 20)); //TODO: Why are int and real_t being compared?
4230 						slidery = std::min(std::max(pad_y1, slidery), pad_y2 - 1 - slidersize);
4231 						drawWindowFancy(subx2 - 19, slidery, subx2 - 5, slidery + slidersize);
4232 
4233 						// directory list offset from slider
4234 						y2 = ((real_t)(slidery - (pad_y1)) / (pad_y2 - (pad_y1))) * editorNumItems;
4235 						if ( scroll )
4236 						{
4237 							slidery -= 8 * scroll;
4238 							slidery = std::min(std::max(pad_y1, slidery), pad_y2 - 1 - slidersize);
4239 							y2 = ((real_t)(slidery - (pad_y1)) / ((pad_y2) - (pad_y1))) * editorNumItems;
4240 							itemSelect = std::min<long unsigned int>(std::max(y2, itemSelect), std::min<long unsigned int>(editorNumItems - 1, y2 + 19)); //TODO: Why are long unsigned int and int being compared? TWICE. On the same line.
4241 							scroll = 0;
4242 						}
4243 						if ( mousestatus[SDL_BUTTON_LEFT] && omousex >= subx2 - 20 && omousex < subx2 - 4 && omousey >= (pad_y1) && omousey < pad_y2 )
4244 						{
4245 							slidery = oslidery + mousey - omousey;
4246 							slidery = std::min(std::max(pad_y1, slidery), pad_y2 - 1 - slidersize);
4247 							y2 = ((real_t)(slidery - (pad_y1)) / ((pad_y2) - (pad_y1))) * editorNumItems;
4248 							mclick = 1;
4249 							itemSelect = std::min<long unsigned int>(std::max(y2, itemSelect), std::min<long unsigned int>(editorNumItems - 1, y2 + 19)); //TODO: Why are long unsigned int and int being compared? TWICE. On the same line.
4250 						}
4251 						else
4252 						{
4253 							oslidery = slidery;
4254 						}
4255 
4256 						pos.x = pad_x1 ;
4257 						pos.y = pad_y1 + 4 + (itemSelect - y2) * 8;
4258 						pos.w = subx2 - pad_x1 - 24;
4259 						pos.h = 8;
4260 						drawRect(&pos, SDL_MapRGB(mainsurface->format, 64, 64, 64), 255);
4261 
4262 						// print all the items
4263 						x = pad_x1;
4264 						y = pad_y1 + 4;
4265 						if ( newwindow == 4 )
4266 						{
4267 							c = std::min<long unsigned int>(editorNumItems, 20 + y2); //TODO: Why are long unsigned int and int being compared?
4268 						}
4269 						else
4270 						{
4271 							c = std::min<long unsigned int>(editorNumItems, 24 + y2); //TODO: Why are long unsigned int and int being compared?
4272 						}
4273 						for ( z = y2; z < c; z++ )
4274 						{
4275 							if ( newwindow == 5 && z == 1 )
4276 							{
4277 								printText(font8x8_bmp, x, y, "default_random");
4278 							}
4279 							else
4280 							{
4281 								switch ( itemSlotSelected )
4282 								{
4283 									case -1:
4284 										printText(font8x8_bmp, x, y, itemNameStrings[z]);
4285 										break;
4286 									default:
4287 										if ( itemSlotSelected < 10 )
4288 										{
4289 											printText(font8x8_bmp, x, y, itemStringsByType[itemSlotSelected][z]);
4290 										}
4291 										else
4292 										{
4293 											printText(font8x8_bmp, x, y, itemNameStrings[z]);
4294 										}
4295 										break;
4296 								}
4297 
4298 							}
4299 							y += 8;
4300 						}
4301 
4302 						// item selection box
4303 						pad_y3 = suby1 + 40;
4304 						pad_y4 = suby1 + 44 + 12;
4305 						// box outlines then text
4306 						drawDepressed(pad_x3 - 4, pad_y3, pad_x3 - 4 + pad_x2 + 112, pad_y4);
4307 						// print values on top of boxes
4308 						printText(font8x8_bmp, pad_x3, pad_y3 - 12, "Item Name");
4309 						printText(font8x8_bmp, pad_x1, pad_y3 - 12, "Click to select item");
4310 						printText(font8x8_bmp, pad_x3, pad_y3 + 4, itemName);
4311 						//drawDepressed(pad_x1, suby2 - 48, subx2 - 4, suby2 - 32);
4312 						//printText(font8x8_bmp, pad_x1, suby2 - 44, itemName);
4313 
4314 						// select a file
4315 						if ( mousestatus[SDL_BUTTON_LEFT] )
4316 						{
4317 							if ( omousex >= pad_x1 && omousex < subx2 - 24 && omousey >= pad_y1 + 4 && omousey < pad_y2 - 4 )
4318 							{
4319 								itemSelect = y2 + ((omousey - (pad_y1 + 4)) >> 3);
4320 								if ( newwindow == 4 )
4321 								{
4322 									itemSelect = std::min<long unsigned int>(std::max(y2, itemSelect), std::min<long unsigned int>(editorNumItems - 2, y2 + 19)); //TODO: Why are long unsigned int and int being compared? TWICE. On the same line.
4323 								}
4324 								else
4325 								{
4326 									itemSelect = std::min<long unsigned int>(std::max(y2, itemSelect), std::min<long unsigned int>(editorNumItems - 2, y2 + 23)); //TODO: Why are long unsigned int and int being compared? TWICE. On the same line.
4327 								}
4328 								switch ( itemSlotSelected )
4329 								{
4330 									case -1:
4331 										strcpy(itemName, itemNameStrings[itemSelect]);
4332 										break;
4333 									default:
4334 										if ( itemSlotSelected < 10 )
4335 										{
4336 											strcpy(itemName, itemStringsByType[itemSlotSelected][itemSelect]);
4337 										}
4338 										else
4339 										{
4340 											strcpy(itemName, itemNameStrings[itemSelect]);
4341 										}
4342 										break;
4343 								}
4344 								//inputstr = itemName;
4345 								editorNumItems = (sizeof(itemNameStrings) / sizeof(itemNameStrings[0]));
4346 								for ( z = 0; z < editorNumItems; z++ )
4347 								{
4348 									if ( strcmp(itemName, itemNameStrings[z]) == 0 )
4349 									{
4350 										char tmpStr[5];
4351 										snprintf(tmpStr, sizeof(tmpStr), "%d", z);
4352 										strcpy(spriteProperties[0], tmpStr);
4353 
4354 										z = editorNumItems;
4355 									}
4356 								}
4357 							}
4358 
4359 							for ( int i = 0; i < numProperties; i++ )
4360 							{
4361 								if ( omousex >= pad_x3 - 4 && omousey >= suby1 + 40 + spacing + i * spacing && omousex < pad_x3 - 4 + pad_x4 && omousey < suby1 + 56 + spacing + i * spacing )
4362 								{
4363 									inputstr = spriteProperties[i];
4364 									editproperty = i;
4365 									cursorflash = ticks;
4366 								}
4367 							}
4368 						}
4369 
4370 						// Cycle properties with TAB.
4371 						if ( keystatus[SDL_SCANCODE_TAB] )
4372 						{
4373 							keystatus[SDL_SCANCODE_TAB] = 0;
4374 							cursorflash = ticks;
4375 							editproperty++;
4376 							if ( editproperty == numProperties )
4377 							{
4378 								editproperty = 0;
4379 							}
4380 
4381 							inputstr = spriteProperties[editproperty];
4382 						}
4383 
4384 						if ( editproperty < numProperties )   // edit
4385 						{
4386 							if ( !SDL_IsTextInputActive() )
4387 							{
4388 								SDL_StartTextInput();
4389 								inputstr = spriteProperties[0];
4390 							}
4391 
4392 							if ( editproperty == 0 )
4393 							{
4394 								inputlen = 3;
4395 								//update the item name when the ID changes.
4396 								if ( newwindow == 5 && atoi(spriteProperties[0]) == 1 )
4397 								{
4398 									strcpy(itemName, "default_random");
4399 								}
4400 								else
4401 								{
4402 									strcpy(itemName, itemNameStrings[atoi(spriteProperties[0])]);
4403 								}
4404 							}
4405 							else if( editproperty == 2 || editproperty == 3 )
4406 							{
4407 								inputlen = 2;
4408 							}
4409 							else if ( editproperty == 5 )
4410 							{
4411 								inputlen = 3;
4412 							}
4413 							else if ( editproperty == 6 && newwindow == 5 )
4414 							{
4415 								inputlen = 3;
4416 							}
4417 							else
4418 							{
4419 								inputlen = 1;
4420 							}
4421 
4422 							if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
4423 							{
4424 								printText(font8x8_bmp, pad_x3 + strlen(spriteProperties[editproperty]) * 8, suby1 + 44 + spacing + editproperty * spacing, "\26");
4425 							}
4426 						}
4427 
4428 					}
4429 				}
4430 				else if ( newwindow == 6 )
4431 				{
4432 					if ( selectedEntity != NULL )
4433 					{
4434 						int numProperties = sizeof(summonTrapPropertyNames) / sizeof(summonTrapPropertyNames[0]); //find number of entries in property list
4435 						const int lenProperties = sizeof(summonTrapPropertyNames[0]) / sizeof(char); //find length of entry in property list
4436 						int spacing = 36; // 36 px between each item in the list.
4437 						int pad_y1 = suby1 + 28; // 28 px spacing from subwindow start.
4438 						int pad_x1 = subx1 + 8; // 8px spacing from subwindow start.
4439 						int pad_x2 = 64;
4440 						int pad_x3 = pad_x1 + pad_x2 + 8;
4441 						int pad_y2 = 0;
4442 						char tmpPropertyName[lenProperties] = "";
4443 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
4444 						Uint32 color2 = SDL_MapRGB(mainsurface->format, 255, 255, 0);
4445 						Uint32 colorBad = SDL_MapRGB(mainsurface->format, 255, 0, 0);
4446 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
4447 
4448 						for ( int i = 0; i < numProperties; i++ )
4449 						{
4450 							int propertyInt = atoi(spriteProperties[i]);
4451 
4452 							strcpy(tmpPropertyName, summonTrapPropertyNames[i]);
4453 							pad_y1 = suby1 + 28 + i * spacing;
4454 							pad_y2 = suby1 + 44 + i * spacing;
4455 							// box outlines then text
4456 							drawDepressed(pad_x1 - 4, suby1 + 40 + i * spacing, pad_x1 - 4 + pad_x2, suby1 + 56 + i * spacing);
4457 							// print values on top of boxes
4458 							printText(font8x8_bmp, pad_x1, suby1 + 44 + i * spacing, spriteProperties[i]);
4459 							printText(font8x8_bmp, pad_x1, pad_y1, tmpPropertyName);
4460 
4461 							if ( errorArr[i] != 1 )
4462 							{
4463 								if ( i == 0 ) //check input for valid entries, correct or notify the user if out of bounds.
4464 								{
4465 									if ( propertyInt > 32 || propertyInt < -1 )
4466 									{
4467 										errorMessage = 60;
4468 										errorArr[i] = 1;
4469 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 0); //reset
4470 									}
4471 									else if ( propertyInt == 0 )
4472 									{
4473 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, colorRandom, "Random monster to match level curve");
4474 									}
4475 									else if ( propertyInt == -1 )
4476 									{
4477 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, colorRandom, "Completely random monster");
4478 									}
4479 									else if ( propertyInt == 6 || propertyInt == 12 || propertyInt == 16 )
4480 									{
4481 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, colorBad, "Error: Unused monster ID, will reset to 0");
4482 									}
4483 									else
4484 									{
4485 										color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
4486 										char tmpStr[32] = "";
4487 										strcpy(tmpStr, monsterEditorNameStrings[atoi(spriteProperties[i])]);
4488 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, color, tmpStr);
4489 									}
4490 								}
4491 								else if ( i == 1 )
4492 								{
4493 									if ( propertyInt > 9 || propertyInt < 0 )
4494 									{
4495 										errorMessage = 60;
4496 										errorArr[i] = 1;
4497 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 1); //reset
4498 									}
4499 									else if ( propertyInt == 0 )
4500 									{
4501 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, colorBad, "Error: Must be > 0");
4502 									}
4503 								}
4504 								else if ( i == 2 )
4505 								{
4506 									if ( propertyInt > 999 || propertyInt < 0 )
4507 									{
4508 										errorMessage = 60;
4509 										errorArr[i] = 1;
4510 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 1); //reset
4511 									}
4512 									else if ( propertyInt == 0 )
4513 									{
4514 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, colorBad, "Error: Must be > 0");
4515 									}
4516 									else
4517 									{
4518 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, color, "%d seconds", atoi(spriteProperties[i]));
4519 									}
4520 								}
4521 								else if ( i == 3 )
4522 								{
4523 									if ( propertyInt > 99 || propertyInt < 0 )
4524 									{
4525 										errorMessage = 60;
4526 										errorArr[i] = 1;
4527 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 1); //reset
4528 									}
4529 									else if ( propertyInt == 0 )
4530 									{
4531 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, colorBad, "Error: Must be > 0");
4532 									}
4533 									else
4534 									{
4535 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, color, "%d instances", atoi(spriteProperties[i]));
4536 									}
4537 								}
4538 								else if ( i == 4 )
4539 								{
4540 									if ( propertyInt > 1 || propertyInt < 0 )
4541 									{
4542 										errorMessage = 60;
4543 										errorArr[i] = 1;
4544 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 0); //reset
4545 									}
4546 									else if ( propertyInt == 0 )
4547 									{
4548 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, color2, "No - power to enable");
4549 									}
4550 									else if ( propertyInt == 1 )
4551 									{
4552 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, color, "Yes - power to disable");
4553 									}
4554 								}
4555 								else if ( i == 5 )
4556 								{
4557 									if ( propertyInt > 100 || propertyInt < 0 )
4558 									{
4559 										errorMessage = 60;
4560 										errorArr[i] = 1;
4561 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 0); //reset
4562 									}
4563 									else
4564 									{
4565 										color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
4566 										char tmpStr[32] = "";
4567 										strcpy(tmpStr, spriteProperties[i]); //reset
4568 										strcat(tmpStr, " %%");
4569 										printTextFormatted(font8x8_bmp, pad_x3, pad_y2, tmpStr);
4570 									}
4571 								}
4572 							}
4573 
4574 							if ( errorMessage )
4575 							{
4576 								color = SDL_MapRGB(mainsurface->format, 255, 0, 0);
4577 								if ( errorArr[i] == 1 )
4578 								{
4579 									printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, color, "Invalid ID!");
4580 								}
4581 							}
4582 
4583 							pad_x1 = subx1 + 8;
4584 						}
4585 						// Cycle properties with TAB.
4586 						if ( keystatus[SDL_SCANCODE_TAB] )
4587 						{
4588 							keystatus[SDL_SCANCODE_TAB] = 0;
4589 							cursorflash = ticks;
4590 							editproperty++;
4591 							if ( editproperty == numProperties )
4592 							{
4593 								editproperty = 0;
4594 							}
4595 
4596 							inputstr = spriteProperties[editproperty];
4597 						}
4598 
4599 						// select a textbox
4600 						if ( mousestatus[SDL_BUTTON_LEFT] )
4601 						{
4602 							for ( int i = 0; i < numProperties; i++ )
4603 							{
4604 								if ( omousex >= pad_x1 - 4 && omousey >= suby1 + 40 + i * spacing && omousex < pad_x1 - 4 + pad_x2 && omousey < suby1 + 56 + i * spacing )
4605 								{
4606 									inputstr = spriteProperties[i];
4607 									editproperty = i;
4608 									cursorflash = ticks;
4609 								}
4610 								pad_x1 = subx1 + 8;
4611 							}
4612 						}
4613 						if ( editproperty < numProperties )   // edit
4614 						{
4615 							if ( !SDL_IsTextInputActive() )
4616 							{
4617 								SDL_StartTextInput();
4618 								inputstr = spriteProperties[0];
4619 							}
4620 							if ( editproperty == 0 || editproperty == 3) //length of text field allowed to enter
4621 							{
4622 								inputlen = 2;
4623 							}
4624 							else if ( editproperty == 2 || editproperty == 5 )
4625 							{
4626 								inputlen = 3;
4627 							}
4628 							else
4629 							{
4630 								inputlen = 1;
4631 							}
4632 							if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
4633 							{
4634 								printText(font8x8_bmp, subx1 + 8 + strlen(spriteProperties[editproperty]) * 8, suby1 + 44 + editproperty * spacing, "\26");
4635 							}
4636 						}
4637 					}
4638 				}
4639 				else if ( newwindow == 7 )
4640 				{
4641 					if ( selectedEntity != NULL )
4642 					{
4643 						int numProperties = sizeof(powerCrystalPropertyNames) / sizeof(powerCrystalPropertyNames[0]); //find number of entries in property list
4644 						const int lenProperties = sizeof(powerCrystalPropertyNames[0]) / sizeof(char); //find length of entry in property list
4645 						int spacing = 36; // 36 px between each item in the list.
4646 						int pad_y1 = suby1 + 28; // 28 px spacing from subwindow start.
4647 						int pad_x1 = subx1 + 8; // 8px spacing from subwindow start.
4648 						int pad_x2 = 64;
4649 						int pad_x3 = pad_x1 + pad_x2 + 8;
4650 						int pad_y2 = 0;
4651 						char tmpPropertyName[lenProperties] = "";
4652 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
4653 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
4654 
4655 						for ( int i = 0; i < numProperties; i++ )
4656 						{
4657 							int propertyInt = atoi(spriteProperties[i]);
4658 
4659 							strcpy(tmpPropertyName, powerCrystalPropertyNames[i]);
4660 							pad_y1 = suby1 + 28 + i * spacing;
4661 							pad_y2 = suby1 + 44 + i * spacing;
4662 							// box outlines then text
4663 							drawDepressed(pad_x1 - 4, suby1 + 40 + i * spacing, pad_x1 - 4 + pad_x2, suby1 + 56 + i * spacing);
4664 							// print values on top of boxes
4665 							printText(font8x8_bmp, pad_x1, suby1 + 44 + i * spacing, spriteProperties[i]);
4666 							printText(font8x8_bmp, pad_x1, pad_y1, tmpPropertyName);
4667 
4668 							if ( errorArr[i] != 1 )
4669 							{
4670 								if ( i == 0 )
4671 								{
4672 									if ( propertyInt > 3 || propertyInt < 0 )
4673 									{
4674 										errorMessage = 60;
4675 										errorArr[i] = 1;
4676 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 0); //reset
4677 									}
4678 									else
4679 									{
4680 										color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
4681 										char tmpStr[32] = "";
4682 										if ( propertyInt == 0 )
4683 										{
4684 											strcpy(tmpStr, "EAST");
4685 										}
4686 										else if ( propertyInt == 1 )
4687 										{
4688 											strcpy(tmpStr, "SOUTH");
4689 										}
4690 										else if ( propertyInt == 2 )
4691 										{
4692 											strcpy(tmpStr, "WEST");
4693 										}
4694 										else if ( propertyInt == 3 )
4695 										{
4696 											strcpy(tmpStr, "NORTH");
4697 										}
4698 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, color, tmpStr);
4699 									}
4700 								}
4701 								else if ( i == 1 )
4702 								{
4703 									if ( propertyInt > 99 || propertyInt < 0 )
4704 									{
4705 										errorMessage = 60;
4706 										errorArr[i] = 1;
4707 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 1); //reset
4708 									}
4709 									else
4710 									{
4711 										color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
4712 										// 32 is WAY TOO SMALL for this, wtf?
4713 										// spriteProperties is a string table, each entry 128 bytes long
4714 										// " Tiles to power in facing direction" = 35 bytes
4715 										// do not forget the null terminator
4716 										char tmpStr[128 + 35 + 1] = "";
4717 										strcpy(tmpStr, spriteProperties[i]); //reset
4718 										strcat(tmpStr, " Tiles to power in facing direction");
4719 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, color, tmpStr);
4720 									}
4721 								}
4722 								else if ( i == 2 )
4723 								{
4724 									if ( propertyInt > 1 || propertyInt < 0 )
4725 									{
4726 										errorMessage = 60;
4727 										errorArr[i] = 1;
4728 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 0); //reset
4729 									}
4730 									else if ( propertyInt == 0 )
4731 									{
4732 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, colorRandom, "Clockwise");
4733 									}
4734 									else if ( propertyInt == 1 )
4735 									{
4736 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, color, "Counter-Clockwise");
4737 									}
4738 								}
4739 								else if ( i == 3 )
4740 								{
4741 									if ( propertyInt > 1 || propertyInt < 0 )
4742 									{
4743 										errorMessage = 60;
4744 										errorArr[i] = 1;
4745 										snprintf(spriteProperties[i], sizeof(spriteProperties[i]), "%d", 0); //reset
4746 									}
4747 									else if ( propertyInt == 0 )
4748 									{
4749 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, colorRandom, "Always on");
4750 									}
4751 									else if ( propertyInt == 1 )
4752 									{
4753 										printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, color, "Requires spell to activate");
4754 									}
4755 								}
4756 							}
4757 
4758 							if ( errorMessage )
4759 							{
4760 								color = SDL_MapRGB(mainsurface->format, 255, 0, 0);
4761 								if ( errorArr[i] == 1 )
4762 								{
4763 									printTextFormattedColor(font8x8_bmp, pad_x3, pad_y2, color, "Invalid ID!");
4764 								}
4765 							}
4766 
4767 							pad_x1 = subx1 + 8;
4768 						}
4769 
4770 						// print out directions
4771 						pad_x1 += 54;
4772 						spacing = 18;
4773 						pad_y1 = suby1 + 28 + 8 * spacing;
4774 						printText(font8x8_bmp, pad_x1 + 32, pad_y1, "NORTH(3)");
4775 						pad_y1 = suby1 + 28 + 9 * spacing;
4776 						printText(font8x8_bmp, pad_x1, pad_y1, "WEST(2)");
4777 						printText(font8x8_bmp, pad_x1 + 96 - 16, pad_y1, "EAST(0)");
4778 						pad_y1 = suby1 + 28 + 10 * spacing;
4779 						printText(font8x8_bmp, pad_x1 + 32, pad_y1, "SOUTH(1)");
4780 						spacing = 36;
4781 
4782 						// Cycle properties with TAB.
4783 						if ( keystatus[SDL_SCANCODE_TAB] )
4784 						{
4785 							keystatus[SDL_SCANCODE_TAB] = 0;
4786 							cursorflash = ticks;
4787 							editproperty++;
4788 							if ( editproperty == numProperties )
4789 							{
4790 								editproperty = 0;
4791 							}
4792 
4793 							inputstr = spriteProperties[editproperty];
4794 						}
4795 
4796 						// select a textbox
4797 						if ( mousestatus[SDL_BUTTON_LEFT] )
4798 						{
4799 							for ( int i = 0; i < numProperties; i++ )
4800 							{
4801 								pad_x1 = subx1 + 8;
4802 								if ( omousex >= pad_x1 - 4 && omousey >= suby1 + 40 + i * spacing && omousex < pad_x1 - 4 + pad_x2 && omousey < suby1 + 56 + i * spacing )
4803 								{
4804 									inputstr = spriteProperties[i];
4805 									editproperty = i;
4806 									cursorflash = ticks;
4807 								}
4808 							}
4809 						}
4810 						if ( editproperty < numProperties )   // edit
4811 						{
4812 							if ( !SDL_IsTextInputActive() )
4813 							{
4814 								SDL_StartTextInput();
4815 								inputstr = spriteProperties[0];
4816 							}
4817 							if ( editproperty == 1 )
4818 							{
4819 								inputlen = 2;
4820 							}
4821 							else
4822 							{
4823 								inputlen = 1;
4824 							}
4825 							if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
4826 							{
4827 								printText(font8x8_bmp, subx1 + 8 + strlen(spriteProperties[editproperty]) * 8, suby1 + 44 + editproperty * spacing, "\26");
4828 							}
4829 						}
4830 					}
4831 				}
4832 				else if ( newwindow == 8 )
4833 				{
4834 					if ( selectedEntity != NULL )
4835 					{
4836 						int numProperties = sizeof(leverTimerPropertyNames) / sizeof(leverTimerPropertyNames[0]); //find number of entries in property list
4837 						const int lenProperties = sizeof(leverTimerPropertyNames[0]) / sizeof(char); //find length of entry in property list
4838 						int spacing = 36; // 36 px between each item in the list.
4839 						int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
4840 						int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
4841 						int inputField_y = inputFieldHeader_y + 16;
4842 						int inputFieldWidth = 64; // width of the text field
4843 						int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
4844 						char tmpPropertyName[lenProperties] = "";
4845 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
4846 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
4847 						Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
4848 
4849 						for ( int i = 0; i < numProperties; i++ )
4850 						{
4851 							int propertyInt = atoi(spriteProperties[i]);
4852 
4853 							strcpy(tmpPropertyName, leverTimerPropertyNames[i]);
4854 							inputFieldHeader_y = suby1 + 28 + i * spacing;
4855 							inputField_y = inputFieldHeader_y + 16;
4856 							// box outlines then text
4857 							drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
4858 							// print values on top of boxes
4859 							printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing, spriteProperties[i]);
4860 							printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
4861 
4862 							if ( errorArr[i] != 1 )
4863 							{
4864 								if ( i == 0 )
4865 								{
4866 									if ( propertyInt > 999 || propertyInt < 0 )
4867 									{
4868 										propertyPageError(i, 5); // reset to default 5 seconds.
4869 									}
4870 									else
4871 									{
4872 										char tmpStr[32] = "";
4873 										if ( propertyInt == 0 )
4874 										{
4875 											strcpy(tmpStr, "Value must be > 0!");
4876 											printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, tmpStr);
4877 										}
4878 										else
4879 										{
4880 											if ( propertyInt == 1 )
4881 											{
4882 												strcpy(tmpStr, "second");
4883 											}
4884 											else
4885 											{
4886 												strcpy(tmpStr, "seconds");
4887 											}
4888 											printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
4889 										}
4890 									}
4891 								}
4892 								else
4893 								{
4894 									// enter other row entries here
4895 								}
4896 							}
4897 
4898 							if ( errorMessage )
4899 							{
4900 								if ( errorArr[i] == 1 )
4901 								{
4902 									printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
4903 								}
4904 							}
4905 						}
4906 
4907 						propertyPageTextAndInput(numProperties, inputFieldWidth);
4908 
4909 						if ( editproperty < numProperties )   // edit
4910 						{
4911 							if ( !SDL_IsTextInputActive() )
4912 							{
4913 								SDL_StartTextInput();
4914 								inputstr = spriteProperties[0];
4915 							}
4916 
4917 							// set the maximum length allowed for user input
4918 							if ( editproperty == 0 )
4919 							{
4920 								inputlen = 4;
4921 							}
4922 							else
4923 							{
4924 								inputlen = 4;
4925 							}
4926 							propertyPageCursorFlash(spacing);
4927 						}
4928 					}
4929 				}
4930 				else if ( newwindow == 9 )
4931 				{
4932 					if ( selectedEntity != NULL )
4933 					{
4934 						int numProperties = sizeof(boulderTrapPropertyNames) / sizeof(boulderTrapPropertyNames[0]); //find number of entries in property list
4935 						const int lenProperties = sizeof(boulderTrapPropertyNames[0]) / sizeof(char); //find length of entry in property list
4936 						int spacing = 36; // 36 px between each item in the list.
4937 						int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
4938 						int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
4939 						int inputField_y = inputFieldHeader_y + 16;
4940 						int inputFieldWidth = 64; // width of the text field
4941 						int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
4942 						char tmpPropertyName[lenProperties] = "";
4943 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
4944 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
4945 						Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
4946 
4947 						for ( int i = 0; i < numProperties; i++ )
4948 						{
4949 							int propertyInt = atoi(spriteProperties[i]);
4950 
4951 							strcpy(tmpPropertyName, boulderTrapPropertyNames[i]);
4952 							inputFieldHeader_y = suby1 + 28 + i * spacing;
4953 							inputField_y = inputFieldHeader_y + 16;
4954 							// box outlines then text
4955 							drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
4956 							// print values on top of boxes
4957 							printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing, spriteProperties[i]);
4958 							printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
4959 
4960 							if ( errorArr[i] != 1 )
4961 							{
4962 								if ( i == 0 )
4963 								{
4964 									if ( propertyInt > 99 || propertyInt < -1 )
4965 									{
4966 										propertyPageError(i, 0); // reset to default 0 re-fire.
4967 									}
4968 									else
4969 									{
4970 										char tmpStr[32] = "";
4971 										if ( propertyInt == 1 )
4972 										{
4973 											strcpy(tmpStr, "time");
4974 										}
4975 										else if ( propertyInt == -1 )
4976 										{
4977 											strcpy(tmpStr, "infinite reload");
4978 										}
4979 										else
4980 										{
4981 											strcpy(tmpStr, "times");
4982 										}
4983 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
4984 									}
4985 								}
4986 								else if ( i == 1 )
4987 								{
4988 									if ( propertyInt > 999 || propertyInt < 0 )
4989 									{
4990 										propertyPageError(i, 1); // reset to default 1 seconds.
4991 									}
4992 									else
4993 									{
4994 										char tmpStr[32] = "";
4995 										if ( propertyInt < 2 )
4996 										{
4997 											strcpy(tmpStr, "Value must be > 1!");
4998 											printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, tmpStr);
4999 										}
5000 										else
5001 										{
5002 											if ( propertyInt == 1 )
5003 											{
5004 												strcpy(tmpStr, "second");
5005 											}
5006 											else
5007 											{
5008 												strcpy(tmpStr, "seconds");
5009 											}
5010 											printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
5011 										}
5012 									}
5013 								}
5014 								else if ( i == 2 )
5015 								{
5016 									if ( propertyInt > 999 || propertyInt < 0 )
5017 									{
5018 										propertyPageError(i, 0); // reset to default 1 seconds.
5019 									}
5020 									else
5021 									{
5022 										char tmpStr[32] = "";
5023 										if ( propertyInt == 1 )
5024 										{
5025 											strcpy(tmpStr, "second");
5026 										}
5027 										else
5028 										{
5029 											strcpy(tmpStr, "seconds");
5030 										}
5031 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
5032 									}
5033 								}
5034 								else
5035 								{
5036 									// enter other row entries here
5037 								}
5038 							}
5039 
5040 							if ( errorMessage )
5041 							{
5042 								if ( errorArr[i] == 1 )
5043 								{
5044 									printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
5045 								}
5046 							}
5047 						}
5048 
5049 						propertyPageTextAndInput(numProperties, inputFieldWidth);
5050 
5051 						if ( editproperty < numProperties )   // edit
5052 						{
5053 							if ( !SDL_IsTextInputActive() )
5054 							{
5055 								SDL_StartTextInput();
5056 								inputstr = spriteProperties[0];
5057 							}
5058 
5059 							// set the maximum length allowed for user input
5060 							if ( editproperty == 0 )
5061 							{
5062 								inputlen = 4;
5063 							}
5064 							else
5065 							{
5066 								inputlen = 4;
5067 							}
5068 							propertyPageCursorFlash(spacing);
5069 						}
5070 					}
5071 				}
5072 				else if ( newwindow == 10 )
5073 				{
5074 					if ( selectedEntity != NULL )
5075 					{
5076 						int numProperties = sizeof(pedestalPropertyNames) / sizeof(pedestalPropertyNames[0]); //find number of entries in property list
5077 						const int lenProperties = sizeof(pedestalPropertyNames[0]) / sizeof(char); //find length of entry in property list
5078 						int spacing = 36; // 36 px between each item in the list.
5079 						int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
5080 						int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
5081 						int inputField_y = inputFieldHeader_y + 16;
5082 						int inputFieldWidth = 64; // width of the text field
5083 						int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
5084 						char tmpPropertyName[lenProperties] = "";
5085 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
5086 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
5087 						Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
5088 
5089 						for ( int i = 0; i < numProperties; i++ )
5090 						{
5091 							int propertyInt = atoi(spriteProperties[i]);
5092 
5093 							strcpy(tmpPropertyName, pedestalPropertyNames[i]);
5094 							inputFieldHeader_y = suby1 + 28 + i * spacing;
5095 							inputField_y = inputFieldHeader_y + 16;
5096 							// box outlines then text
5097 							drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
5098 							// print values on top of boxes
5099 							printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing, spriteProperties[i]);
5100 							printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
5101 
5102 							if ( errorArr[i] != 1 )
5103 							{
5104 								if ( i == 0 )
5105 								{
5106 									if ( propertyInt > 3 || propertyInt < 0 )
5107 									{
5108 										propertyPageError(i, 0); // reset to default 0 blue.
5109 									}
5110 									else
5111 									{
5112 										char tmpStr[32] = "";
5113 										if ( propertyInt == 0 )
5114 										{
5115 											strcpy(tmpStr, "blue");
5116 										}
5117 										else if ( propertyInt == 1 )
5118 										{
5119 											strcpy(tmpStr, "red");
5120 										}
5121 										else if ( propertyInt == 2 )
5122 										{
5123 											strcpy(tmpStr, "purple");
5124 										}
5125 										else if ( propertyInt == 3 )
5126 										{
5127 											strcpy(tmpStr, "green");
5128 										}
5129 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
5130 									}
5131 								}
5132 								else if ( i == 1 )
5133 								{
5134 									if ( propertyInt > 1 || propertyInt < 0 )
5135 									{
5136 										propertyPageError(i, 0); // reset to default 0 (no orb)
5137 									}
5138 									else
5139 									{
5140 										char tmpStr[32] = "";
5141 										if ( propertyInt == 1 )
5142 										{
5143 											strcpy(tmpStr, "pre-load with orb");
5144 										}
5145 										else
5146 										{
5147 											strcpy(tmpStr, "no orb pre-loaded");
5148 										}
5149 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
5150 									}
5151 								}
5152 								else if ( i == 2 )
5153 								{
5154 									if ( propertyInt > 1 || propertyInt < 0 )
5155 									{
5156 										propertyPageError(i, 0); // reset to default 0 non-inverted.
5157 									}
5158 									else
5159 									{
5160 										char tmpStr[32] = "";
5161 										if ( propertyInt == 1 )
5162 										{
5163 											strcpy(tmpStr, "inverted (orb to de-power)");
5164 										}
5165 										else
5166 										{
5167 											strcpy(tmpStr, "non-inverted (orb to power)");
5168 										}
5169 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
5170 									}
5171 								}
5172 								else if ( i == 3 )
5173 								{
5174 									if ( propertyInt > 1 || propertyInt < 0 )
5175 									{
5176 										propertyPageError(i, 0); // reset to default 0 normal height.
5177 									}
5178 									else
5179 									{
5180 										char tmpStr[32] = "";
5181 										if ( propertyInt == 1 )
5182 										{
5183 											strcpy(tmpStr, "true");
5184 										}
5185 										else
5186 										{
5187 											strcpy(tmpStr, "false");
5188 										}
5189 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
5190 									}
5191 								}
5192 								else if ( i == 4 )
5193 								{
5194 									if ( propertyInt > 1 || propertyInt < 0 )
5195 									{
5196 										propertyPageError(i, 0); // reset to default 0 no lock
5197 									}
5198 									else
5199 									{
5200 										char tmpStr[32] = "";
5201 										if ( propertyInt == 0 )
5202 										{
5203 											strcpy(tmpStr, "able to retreive");
5204 										}
5205 										else
5206 										{
5207 											strcpy(tmpStr, "locked when placed");
5208 										}
5209 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
5210 									}
5211 								}
5212 								else
5213 								{
5214 									// enter other row entries here
5215 								}
5216 							}
5217 
5218 							if ( errorMessage )
5219 							{
5220 								if ( errorArr[i] == 1 )
5221 								{
5222 									printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
5223 								}
5224 							}
5225 						}
5226 
5227 						propertyPageTextAndInput(numProperties, inputFieldWidth);
5228 
5229 						if ( editproperty < numProperties )   // edit
5230 						{
5231 							if ( !SDL_IsTextInputActive() )
5232 							{
5233 								SDL_StartTextInput();
5234 								inputstr = spriteProperties[0];
5235 							}
5236 
5237 							// set the maximum length allowed for user input
5238 							inputlen = 2;
5239 							propertyPageCursorFlash(spacing);
5240 						}
5241 					}
5242 				}
5243 				else if ( newwindow == 11 )
5244 				{
5245 					if ( selectedEntity != NULL )
5246 					{
5247 						int numProperties = sizeof(teleporterPropertyNames) / sizeof(teleporterPropertyNames[0]); //find number of entries in property list
5248 						const int lenProperties = sizeof(teleporterPropertyNames[0]) / sizeof(char); //find length of entry in property list
5249 						int spacing = 36; // 36 px between each item in the list.
5250 						int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
5251 						int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
5252 						int inputField_y = inputFieldHeader_y + 16;
5253 						int inputFieldWidth = 64; // width of the text field
5254 						int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
5255 						char tmpPropertyName[lenProperties] = "";
5256 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
5257 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
5258 						Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
5259 
5260 						for ( int i = 0; i < numProperties; i++ )
5261 						{
5262 							int propertyInt = atoi(spriteProperties[i]);
5263 
5264 							strcpy(tmpPropertyName, teleporterPropertyNames[i]);
5265 							inputFieldHeader_y = suby1 + 28 + i * spacing;
5266 							inputField_y = inputFieldHeader_y + 16;
5267 							// box outlines then text
5268 							drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
5269 							// print values on top of boxes
5270 							printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing, spriteProperties[i]);
5271 							printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
5272 
5273 							if ( errorArr[i] != 1 )
5274 							{
5275 								if ( i == 0 )
5276 								{
5277 									if ( propertyInt > 999 || propertyInt < 0 )
5278 									{
5279 										propertyPageError(i, 1); // reset to default 1.
5280 									}
5281 								}
5282 								else if ( i == 1 )
5283 								{
5284 									if ( propertyInt > 999 || propertyInt < 0 )
5285 									{
5286 										propertyPageError(i, 1); // reset to default 1.
5287 									}
5288 								}
5289 								else if ( i == 2 )
5290 								{
5291 									if ( propertyInt > 2 || propertyInt < 0 )
5292 									{
5293 										propertyPageError(i, 0); // reset to default 0 up.
5294 									}
5295 									else
5296 									{
5297 										char tmpStr[32] = "";
5298 										if ( propertyInt == 2 )
5299 										{
5300 											strcpy(tmpStr, "portal");
5301 										}
5302 										else if ( propertyInt == 1 )
5303 										{
5304 											strcpy(tmpStr, "ladder down");
5305 										}
5306 										else
5307 										{
5308 											strcpy(tmpStr, "ladder up");
5309 										}
5310 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
5311 									}
5312 								}
5313 								else
5314 								{
5315 									// enter other row entries here
5316 								}
5317 							}
5318 
5319 							if ( errorMessage )
5320 							{
5321 								if ( errorArr[i] == 1 )
5322 								{
5323 									printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
5324 								}
5325 							}
5326 						}
5327 
5328 						propertyPageTextAndInput(numProperties, inputFieldWidth);
5329 
5330 						if ( editproperty < numProperties )   // edit
5331 						{
5332 							if ( !SDL_IsTextInputActive() )
5333 							{
5334 								SDL_StartTextInput();
5335 								inputstr = spriteProperties[0];
5336 							}
5337 
5338 							// set the maximum length allowed for user input
5339 							if ( editproperty == 2 )
5340 							{
5341 								inputlen = 2;
5342 							}
5343 							else
5344 							{
5345 								inputlen = 4;
5346 							}
5347 							propertyPageCursorFlash(spacing);
5348 						}
5349 					}
5350 				}
5351 				else if ( newwindow == 12 )
5352 				{
5353 					if ( selectedEntity != nullptr )
5354 					{
5355 						int numProperties = sizeof(ceilingTilePropertyNames) / sizeof(ceilingTilePropertyNames[0]); //find number of entries in property list
5356 						const int lenProperties = sizeof(ceilingTilePropertyNames[0]) / sizeof(char); //find length of entry in property list
5357 						int spacing = 36; // 36 px between each item in the list.
5358 						int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
5359 						int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
5360 						int inputField_y = inputFieldHeader_y + 16;
5361 						int inputFieldWidth = 64; // width of the text field
5362 						int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
5363 						char tmpPropertyName[lenProperties] = "";
5364 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
5365 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
5366 						Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
5367 
5368 						for ( int i = 0; i < numProperties; i++ )
5369 						{
5370 							int propertyInt = atoi(spriteProperties[i]);
5371 
5372 							strcpy(tmpPropertyName, ceilingTilePropertyNames[i]);
5373 							inputFieldHeader_y = suby1 + 28 + i * spacing;
5374 							inputField_y = inputFieldHeader_y + 16;
5375 							// box outlines then text
5376 							drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
5377 							// print values on top of boxes
5378 							printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing, spriteProperties[i]);
5379 							printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
5380 
5381 							if ( errorArr[i] != 1 )
5382 							{
5383 								if ( i == 0 )
5384 								{
5385 									if ( propertyInt > 9999 || propertyInt < 0 )
5386 									{
5387 										propertyPageError(i, 0); // reset to default 0.
5388 									}
5389 								}
5390 								else
5391 								{
5392 									// enter other row entries here
5393 								}
5394 							}
5395 
5396 							if ( errorMessage )
5397 							{
5398 								if ( errorArr[i] == 1 )
5399 								{
5400 									printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
5401 								}
5402 							}
5403 						}
5404 
5405 						propertyPageTextAndInput(numProperties, inputFieldWidth);
5406 
5407 						if ( editproperty < numProperties )   // edit
5408 						{
5409 							if ( !SDL_IsTextInputActive() )
5410 							{
5411 								SDL_StartTextInput();
5412 								inputstr = spriteProperties[0];
5413 							}
5414 
5415 							// set the maximum length allowed for user input
5416 							if ( editproperty == 0 )
5417 							{
5418 								inputlen = 4;
5419 							}
5420 							else
5421 							{
5422 								inputlen = 3;
5423 							}
5424 							propertyPageCursorFlash(spacing);
5425 						}
5426 					}
5427 				}
5428 				else if ( newwindow == 13 )
5429 				{
5430 					if ( selectedEntity != nullptr )
5431 					{
5432 						int numProperties = sizeof(spellTrapPropertyNames) / sizeof(spellTrapPropertyNames[0]); //find number of entries in property list
5433 						const int lenProperties = sizeof(spellTrapPropertyNames[0]) / sizeof(char); //find length of entry in property list
5434 						int spacing = 36; // 36 px between each item in the list.
5435 						int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
5436 						int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
5437 						int inputField_y = inputFieldHeader_y + 16;
5438 						int inputFieldWidth = 64; // width of the text field
5439 						int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
5440 						char tmpPropertyName[lenProperties] = "";
5441 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
5442 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
5443 						Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
5444 
5445 						for ( int i = 0; i < numProperties; i++ )
5446 						{
5447 							int propertyInt = atoi(spriteProperties[i]);
5448 
5449 							strcpy(tmpPropertyName, spellTrapPropertyNames[i]);
5450 							inputFieldHeader_y = suby1 + 28 + i * spacing;
5451 							inputField_y = inputFieldHeader_y + 16;
5452 							// box outlines then text
5453 							drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
5454 							// print values on top of boxes
5455 							printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing, spriteProperties[i]);
5456 							printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
5457 
5458 							if ( errorArr[i] != 1 )
5459 							{
5460 								if ( i == 0 )
5461 								{
5462 									if ( propertyInt > 99 || propertyInt < -1 )
5463 									{
5464 										propertyPageError(i, -1); // reset to default -1.
5465 									}
5466 								}
5467 								else if ( i == 1 )
5468 								{
5469 									if ( propertyInt > 99 || propertyInt < -1 )
5470 									{
5471 										propertyPageError(i, -1); // reset to default -1.
5472 									}
5473 								}
5474 								else if ( i == 2 )
5475 								{
5476 									if ( propertyInt > 1 || propertyInt < 0 )
5477 									{
5478 										propertyPageError(i, 0); // reset to default 0 continuous.
5479 									}
5480 									else
5481 									{
5482 										char tmpStr[32] = "";
5483 										if ( propertyInt == 0 )
5484 										{
5485 											strcpy(tmpStr, "must re-trigger power to fire");
5486 										}
5487 										else if ( propertyInt == 1 )
5488 										{
5489 											strcpy(tmpStr, "continous fire first power up");
5490 										}
5491 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
5492 									}
5493 								}
5494 								else if ( i == 3 )
5495 								{
5496 									if ( propertyInt > 9999 || propertyInt < 0 )
5497 									{
5498 										propertyPageError(i, 1); // reset to default 1.
5499 									}
5500 								}
5501 								else if ( i == 4 )
5502 								{
5503 									if ( propertyInt > 999 || propertyInt < 0 )
5504 									{
5505 										propertyPageError(i, 1); // reset to default 1.
5506 									}
5507 									else
5508 									{
5509 										char tmpStr[32] = "";
5510 										if ( propertyInt == 1 )
5511 										{
5512 											strcpy(tmpStr, "second");
5513 										}
5514 										else if ( propertyInt > 1 )
5515 										{
5516 											strcpy(tmpStr, "seconds");
5517 										}
5518 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
5519 									}
5520 								}
5521 								else
5522 								{
5523 									// enter other row entries here
5524 								}
5525 							}
5526 
5527 							if ( errorMessage )
5528 							{
5529 								if ( errorArr[i] == 1 )
5530 								{
5531 									printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
5532 								}
5533 							}
5534 						}
5535 
5536 						propertyPageTextAndInput(numProperties, inputFieldWidth);
5537 
5538 						if ( editproperty < numProperties )   // edit
5539 						{
5540 							if ( !SDL_IsTextInputActive() )
5541 							{
5542 								SDL_StartTextInput();
5543 								inputstr = spriteProperties[0];
5544 							}
5545 
5546 							// set the maximum length allowed for user input
5547 							if ( editproperty == 0 || editproperty == 1 )
5548 							{
5549 								inputlen = 3;
5550 							}
5551 							else if ( editproperty == 2 )
5552 							{
5553 								inputlen = 2;
5554 							}
5555 							else
5556 							{
5557 								inputlen = 4;
5558 							}
5559 							propertyPageCursorFlash(spacing);
5560 						}
5561 					}
5562 				}
5563 				else if ( newwindow == 14 )
5564 				{
5565 					if ( selectedEntity != nullptr )
5566 					{
5567 						int numProperties = sizeof(furniturePropertyNames) / sizeof(furniturePropertyNames[0]); //find number of entries in property list
5568 						const int lenProperties = sizeof(furniturePropertyNames[0]) / sizeof(char); //find length of entry in property list
5569 						int spacing = 36; // 36 px between each item in the list.
5570 						int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
5571 						int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
5572 						int inputField_y = inputFieldHeader_y + 16;
5573 						int inputFieldWidth = 64; // width of the text field
5574 						int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
5575 						char tmpPropertyName[lenProperties] = "";
5576 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
5577 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
5578 						Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
5579 
5580 						for ( int i = 0; i < numProperties; i++ )
5581 						{
5582 							int propertyInt = atoi(spriteProperties[i]);
5583 
5584 							strcpy(tmpPropertyName, furniturePropertyNames[i]);
5585 							inputFieldHeader_y = suby1 + 28 + i * spacing;
5586 							inputField_y = inputFieldHeader_y + 16;
5587 							// box outlines then text
5588 							drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
5589 							// print values on top of boxes
5590 							printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing, spriteProperties[i]);
5591 							printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
5592 
5593 							if ( errorArr[i] != 1 )
5594 							{
5595 								if ( i == 0 )
5596 								{
5597 									if ( propertyInt > 9 || propertyInt < -1 )
5598 									{
5599 										propertyPageError(i, -1); // reset to default -1.
5600 									}
5601 									else
5602 									{
5603 										char tmpStr[32] = "";
5604 										switch ( propertyInt )
5605 										{
5606 											case -1:
5607 												strcpy(tmpStr, "random");
5608 												break;
5609 											case 0:
5610 												strcpy(tmpStr, "East");
5611 												break;
5612 											case 1:
5613 												strcpy(tmpStr, "Southeast");
5614 												break;
5615 											case 2:
5616 												strcpy(tmpStr, "South");
5617 												break;
5618 											case 3:
5619 												strcpy(tmpStr, "Southwest");
5620 												break;
5621 											case 4:
5622 												strcpy(tmpStr, "West");
5623 												break;
5624 											case 5:
5625 												strcpy(tmpStr, "Northwest");
5626 												break;
5627 											case 6:
5628 												strcpy(tmpStr, "North");
5629 												break;
5630 											case 7:
5631 												strcpy(tmpStr, "Northeast");
5632 												break;
5633 											default:
5634 												break;
5635 										}
5636 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
5637 									}
5638 								}
5639 								else
5640 								{
5641 									// enter other row entries here
5642 								}
5643 							}
5644 
5645 							if ( errorMessage )
5646 							{
5647 								if ( errorArr[i] == 1 )
5648 								{
5649 									printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
5650 								}
5651 							}
5652 						}
5653 
5654 						propertyPageTextAndInput(numProperties, inputFieldWidth);
5655 
5656 						if ( editproperty < numProperties )   // edit
5657 						{
5658 							if ( !SDL_IsTextInputActive() )
5659 							{
5660 								SDL_StartTextInput();
5661 								inputstr = spriteProperties[0];
5662 							}
5663 
5664 							// set the maximum length allowed for user input
5665 							inputlen = 2;
5666 							propertyPageCursorFlash(spacing);
5667 						}
5668 					}
5669 				}
5670 				else if ( newwindow == 15 )
5671 				{
5672 					if ( selectedEntity != nullptr )
5673 					{
5674 						int numProperties = sizeof(floorDecorationPropertyNames) / sizeof(floorDecorationPropertyNames[0]); //find number of entries in property list
5675 						const int lenProperties = sizeof(floorDecorationPropertyNames[0]) / sizeof(char); //find length of entry in property list
5676 						int spacing = 36; // 36 px between each item in the list.
5677 						int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
5678 						int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
5679 						int inputField_y = inputFieldHeader_y + 16;
5680 						int inputFieldWidth = 64; // width of the text field
5681 						int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
5682 						char tmpPropertyName[lenProperties] = "";
5683 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
5684 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
5685 						Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
5686 
5687 						for ( int i = 0; i < numProperties; i++ )
5688 						{
5689 							int propertyInt = atoi(spriteProperties[i]);
5690 
5691 							if ( i >= 5 && i <= 8 )
5692 							{
5693 								inputFieldWidth = subx2 - inputField_x; // width of the text field
5694 								if ( i > 5 )
5695 								{
5696 									spacing = 18;
5697 								}
5698 								else
5699 								{
5700 									spacing = 36;
5701 								}
5702 							}
5703 							else
5704 							{
5705 								inputFieldWidth = 64; // width of the text field
5706 								spacing = 36;
5707 							}
5708 
5709 							inputFieldHeader_y = suby1 + 28 + i * spacing;
5710 							inputField_y = inputFieldHeader_y + 16;
5711 
5712 							if ( i > 5 && i <= 8 )
5713 							{
5714 								int offsetBoxes = 2.5 * 36;
5715 								inputFieldHeader_y = suby1 + 28 + i * spacing + offsetBoxes;
5716 								inputField_y = inputFieldHeader_y + 16;
5717 								// box outlines then text
5718 								drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
5719 								// print values on top of boxes
5720 								printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing + offsetBoxes, spriteProperties[i]);
5721 							}
5722 							else
5723 							{
5724 								// box outlines then text
5725 								drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
5726 								// print values on top of boxes
5727 								printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing, spriteProperties[i]);
5728 								strcpy(tmpPropertyName, floorDecorationPropertyNames[i]);
5729 								printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
5730 							}
5731 
5732 							if ( errorArr[i] != 1 )
5733 							{
5734 								if ( i == 0 )
5735 								{
5736 									if ( propertyInt > 9999 || propertyInt < 0 )
5737 									{
5738 										propertyPageError(i, 0); // reset to default 0.
5739 									}
5740 								}
5741 								else if ( i == 1 )
5742 								{
5743 									if ( propertyInt > 7 || propertyInt < -1 )
5744 									{
5745 										propertyPageError(i, 0); // reset to default 0.
5746 									}
5747 									else
5748 									{
5749 										char tmpStr[32] = "";
5750 										switch ( propertyInt )
5751 										{
5752 											case -1:
5753 												strcpy(tmpStr, "random");
5754 												break;
5755 											case 0:
5756 												strcpy(tmpStr, "East");
5757 												break;
5758 											case 1:
5759 												strcpy(tmpStr, "Southeast");
5760 												break;
5761 											case 2:
5762 												strcpy(tmpStr, "South");
5763 												break;
5764 											case 3:
5765 												strcpy(tmpStr, "Southwest");
5766 												break;
5767 											case 4:
5768 												strcpy(tmpStr, "West");
5769 												break;
5770 											case 5:
5771 												strcpy(tmpStr, "Northwest");
5772 												break;
5773 											case 6:
5774 												strcpy(tmpStr, "North");
5775 												break;
5776 											case 7:
5777 												strcpy(tmpStr, "Northeast");
5778 												break;
5779 											default:
5780 												break;
5781 										}
5782 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
5783 									}
5784 								}
5785 								else if ( i == 2 || i == 3 || i == 4 )
5786 								{
5787 									if ( propertyInt > 999 || propertyInt < -999 )
5788 									{
5789 										propertyPageError(i, 0); // reset to default 0.
5790 									}
5791 								}
5792 								else
5793 								{
5794 									// enter other row entries here
5795 								}
5796 							}
5797 
5798 							if ( errorMessage )
5799 							{
5800 								if ( errorArr[i] == 1 )
5801 								{
5802 									printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
5803 								}
5804 							}
5805 						}
5806 
5807 						spacing = 36;
5808 
5809 						// Cycle properties with TAB.
5810 						if ( keystatus[SDL_SCANCODE_TAB] )
5811 						{
5812 							keystatus[SDL_SCANCODE_TAB] = 0;
5813 							cursorflash = ticks;
5814 							editproperty++;
5815 							if ( editproperty == numProperties )
5816 							{
5817 								editproperty = 0;
5818 							}
5819 
5820 							inputstr = spriteProperties[editproperty];
5821 						}
5822 
5823 						// select a textbox
5824 						if ( mousestatus[SDL_BUTTON_LEFT] )
5825 						{
5826 							for ( int i = 0; i < numProperties; i++ )
5827 							{
5828 								inputField_x = subx1 + 8;
5829 								if ( i > 5 && i <= 8 )
5830 								{
5831 									spacing = 18;
5832 									int offsetBoxes = 2.5 * 36;
5833 									inputFieldWidth = subx2 - inputField_x; // width of the text field
5834 									if ( mouseInBounds(inputField_x - 4, inputField_x - 4 + inputFieldWidth,
5835 										suby1 + 40 + i * spacing + offsetBoxes, suby1 + 56 + i * spacing + offsetBoxes) )
5836 									{
5837 										inputstr = spriteProperties[i];
5838 										editproperty = i;
5839 										cursorflash = ticks;
5840 									}
5841 								}
5842 								else
5843 								{
5844 									if ( i == 5 )
5845 									{
5846 										inputFieldWidth = subx2 - inputField_x; // width of the text field
5847 									}
5848 									else
5849 									{
5850 										inputFieldWidth = 64; // width of the text field
5851 									}
5852 									spacing = 36;
5853 
5854 									if ( mouseInBounds(inputField_x - 4, inputField_x - 4 + inputFieldWidth,
5855 										suby1 + 40 + i * spacing, suby1 + 56 + i * spacing) )
5856 									{
5857 										inputstr = spriteProperties[i];
5858 										editproperty = i;
5859 										cursorflash = ticks;
5860 									}
5861 								}
5862 							}
5863 						}
5864 
5865 						if ( editproperty < numProperties )   // edit
5866 						{
5867 							if ( !SDL_IsTextInputActive() )
5868 							{
5869 								SDL_StartTextInput();
5870 								inputstr = spriteProperties[0];
5871 							}
5872 
5873 							// set the maximum length allowed for user input
5874 							if ( editproperty >= 5 && editproperty <= 8 )
5875 							{
5876 								inputlen = 48;
5877 							}
5878 							else
5879 							{
5880 								inputlen = 4;
5881 							}
5882 							if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
5883 							{
5884 								if ( editproperty > 5 && editproperty <= 8 )
5885 								{
5886 									spacing = 18;
5887 									int offsetBoxes = 2.5 * 36;
5888 									if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
5889 									{
5890 										printText(font8x8_bmp, subx1 + 8 + strlen(spriteProperties[editproperty]) * 8, suby1 + 44 + editproperty * spacing + offsetBoxes, "\26");
5891 									}
5892 								}
5893 								else
5894 								{
5895 									spacing = 36;
5896 									propertyPageCursorFlash(spacing);
5897 								}
5898 							}
5899 						}
5900 					}
5901 				}
5902 				else if ( newwindow == 18 )
5903 				{
5904 					if ( selectedEntity != nullptr )
5905 					{
5906 						int numProperties = sizeof(soundSourcePropertyNames) / sizeof(soundSourcePropertyNames[0]); //find number of entries in property list
5907 						const int lenProperties = sizeof(soundSourcePropertyNames[0]) / sizeof(char); //find length of entry in property list
5908 						int spacing = 36; // 36 px between each item in the list.
5909 						int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
5910 						int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
5911 						int inputField_y = inputFieldHeader_y + 16;
5912 						int inputFieldWidth = 64; // width of the text field
5913 						int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
5914 						char tmpPropertyName[lenProperties] = "";
5915 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
5916 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
5917 						Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
5918 
5919 						for ( int i = 0; i < numProperties; i++ )
5920 						{
5921 							int propertyInt = atoi(spriteProperties[i]);
5922 
5923 							strcpy(tmpPropertyName, soundSourcePropertyNames[i]);
5924 							inputFieldHeader_y = suby1 + 28 + i * spacing;
5925 							inputField_y = inputFieldHeader_y + 16;
5926 							// box outlines then text
5927 							drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
5928 							// print values on top of boxes
5929 							printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing, spriteProperties[i]);
5930 							printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
5931 
5932 							if ( errorArr[i] != 1 )
5933 							{
5934 								if ( i == 4 )
5935 								{
5936 									if ( propertyInt > 1 || propertyInt < 0 )
5937 									{
5938 										propertyPageError(i, 0); // reset to default 0.
5939 									}
5940 									else if ( propertyInt == 0 )
5941 									{
5942 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "Play sound on this entity");
5943 									}
5944 									else
5945 									{
5946 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "Play sound global");
5947 									}
5948 								}
5949 								else if ( i == 3 )
5950 								{
5951 									if ( propertyInt > 9999 || propertyInt < 0 )
5952 									{
5953 										propertyPageError(i, 0); // reset to default 0.
5954 									}
5955 								}
5956 								if ( i == 2 )
5957 								{
5958 									if ( propertyInt > 1 || propertyInt < 0 )
5959 									{
5960 										propertyPageError(i, 0); // reset to default 0.
5961 									}
5962 								}
5963 								else if ( i == 1 )
5964 								{
5965 									if ( propertyInt > 255 || propertyInt < -1 )
5966 									{
5967 										propertyPageError(i, 0); // reset to default 0.
5968 									}
5969 								}
5970 								else if ( i == 0 )
5971 								{
5972 									if ( propertyInt > 999 || propertyInt < 0 )
5973 									{
5974 										propertyPageError(i, 0); // reset to default 0.
5975 									}
5976 								}
5977 								else
5978 								{
5979 									// enter other row entries here
5980 								}
5981 							}
5982 
5983 							if ( errorMessage )
5984 							{
5985 								if ( errorArr[i] == 1 )
5986 								{
5987 									printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
5988 								}
5989 							}
5990 						}
5991 
5992 						propertyPageTextAndInput(numProperties, inputFieldWidth);
5993 
5994 						if ( editproperty < numProperties )   // edit
5995 						{
5996 							if ( !SDL_IsTextInputActive() )
5997 							{
5998 								SDL_StartTextInput();
5999 								inputstr = spriteProperties[0];
6000 							}
6001 
6002 							// set the maximum length allowed for user input
6003 							if ( editproperty <= 1 )
6004 							{
6005 								inputlen = 3;
6006 							}
6007 							else if ( editproperty == 2 )
6008 							{
6009 								inputlen = 1;
6010 							}
6011 							else
6012 							{
6013 								inputlen = 4;
6014 							}
6015 							propertyPageCursorFlash(spacing);
6016 						}
6017 					}
6018 				}
6019 				else if ( newwindow == 19 )
6020 				{
6021 					if ( selectedEntity != nullptr )
6022 					{
6023 						int numProperties = sizeof(lightSourcePropertyNames) / sizeof(lightSourcePropertyNames[0]); //find number of entries in property list
6024 						const int lenProperties = sizeof(lightSourcePropertyNames[0]) / sizeof(char); //find length of entry in property list
6025 						int spacing = 36; // 36 px between each item in the list.
6026 						int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
6027 						int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
6028 						int inputField_y = inputFieldHeader_y + 16;
6029 						int inputFieldWidth = 64; // width of the text field
6030 						int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
6031 						char tmpPropertyName[lenProperties] = "";
6032 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
6033 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
6034 						Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
6035 
6036 						for ( int i = 0; i < numProperties; i++ )
6037 						{
6038 							int propertyInt = atoi(spriteProperties[i]);
6039 
6040 							strcpy(tmpPropertyName, lightSourcePropertyNames[i]);
6041 							inputFieldHeader_y = suby1 + 28 + i * spacing;
6042 							inputField_y = inputFieldHeader_y + 16;
6043 							// box outlines then text
6044 							drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
6045 							// print values on top of boxes
6046 							printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing, spriteProperties[i]);
6047 							printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
6048 
6049 							if ( errorArr[i] != 1 )
6050 							{
6051 								if ( i == 0 || i == 2 || i == 3 || i == 5 )
6052 								{
6053 									if ( propertyInt > 2 || propertyInt < 0 )
6054 									{
6055 										propertyPageError(i, 0); // reset to default 0.
6056 									}
6057 								}
6058 								else if ( i == 4 )
6059 								{
6060 									if ( propertyInt > 64 || propertyInt < -1 )
6061 									{
6062 										propertyPageError(i, 0); // reset to default 0.
6063 									}
6064 								}
6065 								else if ( i == 6 )
6066 								{
6067 									if ( propertyInt > 9999 || propertyInt < 0 )
6068 									{
6069 										propertyPageError(i, 0); // reset to default 0.
6070 									}
6071 								}
6072 								else if ( i == 1 )
6073 								{
6074 									if ( propertyInt > 255 || propertyInt < -1 )
6075 									{
6076 										propertyPageError(i, 0); // reset to default 0.
6077 									}
6078 								}
6079 								else
6080 								{
6081 									// enter other row entries here
6082 								}
6083 							}
6084 
6085 							if ( errorMessage )
6086 							{
6087 								if ( errorArr[i] == 1 )
6088 								{
6089 									printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
6090 								}
6091 							}
6092 						}
6093 
6094 						propertyPageTextAndInput(numProperties, inputFieldWidth);
6095 
6096 						if ( editproperty < numProperties )   // edit
6097 						{
6098 							if ( !SDL_IsTextInputActive() )
6099 							{
6100 								SDL_StartTextInput();
6101 								inputstr = spriteProperties[0];
6102 							}
6103 
6104 							// set the maximum length allowed for user input
6105 							if ( editproperty == 1 )
6106 							{
6107 								inputlen = 3;
6108 							}
6109 							else if ( editproperty == 0 || editproperty == 2 || editproperty == 3 || editproperty == 5 )
6110 							{
6111 								inputlen = 1;
6112 							}
6113 							else if ( editproperty == 4 )
6114 							{
6115 								inputlen = 2;
6116 							}
6117 							else
6118 							{
6119 								inputlen = 4;
6120 							}
6121 							propertyPageCursorFlash(spacing);
6122 						}
6123 					}
6124 				}
6125 				else if ( newwindow == 20 )
6126 				{
6127 					if ( selectedEntity != nullptr )
6128 					{
6129 						int numProperties = sizeof(textSourcePropertyNames) / sizeof(textSourcePropertyNames[0]); //find number of entries in property list
6130 						const int lenProperties = sizeof(textSourcePropertyNames[0]) / sizeof(char); //find length of entry in property list
6131 						int spacing = 36; // 36 px between each item in the list.
6132 						int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
6133 						int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
6134 						int inputField_y = inputFieldHeader_y + 16;
6135 						int inputFieldWidth = 64; // width of the text field
6136 						int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
6137 						char tmpPropertyName[lenProperties] = "";
6138 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
6139 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
6140 						Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
6141 						bool showTextSourceTooltip = false;
6142 
6143 						for ( int i = 0; i < numProperties; i++ )
6144 						{
6145 							inputField_x = subx1 + 8;
6146 							int propertyInt = atoi(spriteProperties[i]);
6147 							if ( i >= 3 && i < 8 )
6148 							{
6149 								inputFieldWidth = subx2 - inputField_x; // width of the text field
6150 								inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
6151 								if ( i > 3 )
6152 								{
6153 									spacing = 18;
6154 								}
6155 								else
6156 								{
6157 									spacing = 36;
6158 								}
6159 							}
6160 							else
6161 							{
6162 								inputFieldWidth = 64; // width of the text field
6163 								inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
6164 								spacing = 36;
6165 							}
6166 
6167 							if ( i <= 2 )
6168 							{
6169 								inputFieldFeedback_x = inputField_x + (inputFieldWidth + 8) * 4 - 4;
6170 							}
6171 							if ( i == 1 || i == 2 )
6172 							{
6173 								inputFieldHeader_y = suby1 + 28;
6174 								inputField_y = inputFieldHeader_y + 16;
6175 								inputField_x = subx1 + 8 + (inputFieldWidth + 8) * i;
6176 								if ( i == 2 )
6177 								{
6178 									Uint32 colorPreview = SDL_MapRGB(mainsurface->format, (Uint32)atoi(spriteProperties[0]),
6179 										(Uint32)atoi(spriteProperties[1]), (Uint32)atoi(spriteProperties[2]));
6180 									SDL_Rect src;
6181 									src.x = subx1 + 8 + (inputFieldWidth + 8) * 3;
6182 									src.h = 16;
6183 									src.w = 32;
6184 									src.y = inputField_y - 4;
6185 									drawRect(&src, colorPreview, 255);
6186 
6187 									printText(font8x8_bmp, inputField_x + (inputFieldWidth + 8), inputFieldHeader_y, "Hover for help");
6188 									if ( mouseInBounds(inputField_x + (inputFieldWidth + 8), inputField_x + (inputFieldWidth + 8) + strlen("Hover for help") * 8,
6189 										inputFieldHeader_y, inputFieldHeader_y + 16) )
6190 									{
6191 										showTextSourceTooltip = true;
6192 									}
6193 								}
6194 							}
6195 							else if ( i > 3 && i < 8 )
6196 							{
6197 								inputFieldHeader_y = suby1 + 28 + (i - 1) * spacing;
6198 								inputField_y = inputFieldHeader_y + 16;
6199 							}
6200 							else
6201 							{
6202 								// header print
6203 								if ( i == 3 )
6204 								{
6205 									inputFieldHeader_y = suby1 + 28 + (i - 2) * spacing;
6206 								}
6207 								else if ( i >= 8 )
6208 								{
6209 									inputFieldHeader_y = suby1 + 28 + (i - 4) * spacing;
6210 								}
6211 								else
6212 								{
6213 									inputFieldHeader_y = suby1 + 28;
6214 								}
6215 								inputField_y = inputFieldHeader_y + 16;
6216 								strcpy(tmpPropertyName, textSourcePropertyNames[i]);
6217 								printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
6218 							}
6219 							// box outlines then text
6220 							// print values on top of boxes
6221 							if ( i == 1 || i == 2 )
6222 							{
6223 								drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
6224 								printText(font8x8_bmp, inputField_x, inputField_y, spriteProperties[i]);
6225 							}
6226 							else
6227 							{
6228 								drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
6229 								printText(font8x8_bmp, inputField_x, inputField_y, spriteProperties[i]);
6230 							}
6231 
6232 							if ( errorArr[i] != 1 )
6233 							{
6234 								if ( i >= 0 && i <= 2 )
6235 								{
6236 									if ( propertyInt > 255 || propertyInt < 0 )
6237 									{
6238 										propertyPageError(i, 0); // reset to default 0.
6239 									}
6240 								}
6241 								else if ( i == 8 )
6242 								{
6243 									if ( propertyInt > 9999 || propertyInt < 0 )
6244 									{
6245 										propertyPageError(i, 0); // reset to default 0.
6246 									}
6247 								}
6248 								else if ( i == 9 )
6249 								{
6250 									if ( propertyInt > 1 || propertyInt < 0 )
6251 									{
6252 										propertyPageError(i, 0); // reset to default 0.
6253 									}
6254 								}
6255 								else
6256 								{
6257 									// enter other row entries here
6258 								}
6259 							}
6260 
6261 							if ( errorMessage )
6262 							{
6263 								if ( errorArr[i] == 1 )
6264 								{
6265 									printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
6266 								}
6267 							}
6268 						}
6269 
6270 						spacing = 36;
6271 
6272 						// Cycle properties with TAB.
6273 						if ( keystatus[SDL_SCANCODE_TAB] )
6274 						{
6275 							keystatus[SDL_SCANCODE_TAB] = 0;
6276 							cursorflash = ticks;
6277 							editproperty++;
6278 							if ( editproperty == numProperties )
6279 							{
6280 								editproperty = 0;
6281 							}
6282 
6283 							inputstr = spriteProperties[editproperty];
6284 						}
6285 
6286 						// select a textbox
6287 						if ( mousestatus[SDL_BUTTON_LEFT] )
6288 						{
6289 							for ( int i = 0; i < numProperties; i++ )
6290 							{
6291 								inputField_x = subx1 + 8;
6292 								if ( i > 3 && i < 8 )
6293 								{
6294 									spacing = 18;
6295 									inputFieldWidth = subx2 - inputField_x; // width of the text field
6296 									if ( mouseInBounds(inputField_x - 4, inputField_x - 4 + inputFieldWidth,
6297 										suby1 + 40 + (i - 1) * spacing, suby1 + 56 + (i - 1) * spacing) )
6298 									{
6299 										inputstr = spriteProperties[i];
6300 										editproperty = i;
6301 										cursorflash = ticks;
6302 									}
6303 								}
6304 								else
6305 								{
6306 									if ( i == 3 )
6307 									{
6308 										inputFieldWidth = subx2 - inputField_x; // width of the text field
6309 									}
6310 									else
6311 									{
6312 										inputFieldWidth = 64; // width of the text field
6313 									}
6314 									spacing = 36;
6315 									if ( i == 1 || i == 2 )
6316 									{
6317 										inputField_x = subx1 + 8 + (inputFieldWidth + 8) * i;
6318 										spacing = 0;
6319 									}
6320 									else if ( i == 3 )
6321 									{
6322 										spacing = 12;
6323 									}
6324 
6325 									if ( i >= 8 )
6326 									{
6327 										if ( mouseInBounds(inputField_x - 4, inputField_x - 4 + inputFieldWidth,
6328 											suby1 + 40 + (i - 4) * spacing, suby1 + 56 + (i - 4) * spacing) )
6329 										{
6330 											inputstr = spriteProperties[i];
6331 											editproperty = i;
6332 											cursorflash = ticks;
6333 										}
6334 									}
6335 									else
6336 									{
6337 										if ( mouseInBounds(inputField_x - 4, inputField_x - 4 + inputFieldWidth,
6338 											suby1 + 40 + i * spacing, suby1 + 56 + i * spacing) )
6339 										{
6340 											inputstr = spriteProperties[i];
6341 											editproperty = i;
6342 											cursorflash = ticks;
6343 										}
6344 									}
6345 								}
6346 							}
6347 						}
6348 
6349 						if ( editproperty < numProperties )   // edit
6350 						{
6351 							if ( !SDL_IsTextInputActive() )
6352 							{
6353 								SDL_StartTextInput();
6354 								inputstr = spriteProperties[0];
6355 							}
6356 							if ( SDL_IsTextInputActive() )
6357 							{
6358 								if ( textInsertCaratPosition >= 0 )
6359 								{
6360 									textInsertCaratPosition = std::min(textInsertCaratPosition, (int)strlen(inputstr));
6361 									if ( editproperty < 3 || editproperty > 8 )
6362 									{
6363 										textInsertCaratPosition = -1;
6364 									}
6365 								}
6366 								if ( keystatus[SDL_SCANCODE_LEFT] )
6367 								{
6368 									keystatus[SDL_SCANCODE_LEFT] = 0;
6369 									if ( textInsertCaratPosition > 0 )
6370 									{
6371 										--textInsertCaratPosition;
6372 									}
6373 									else if ( textInsertCaratPosition == 0 )
6374 									{
6375 										// do nothing
6376 									}
6377 									else
6378 									{
6379 										textInsertCaratPosition = strlen(inputstr);
6380 									}
6381 									cursorflash = ticks;
6382 								}
6383 								else if ( keystatus[SDL_SCANCODE_RIGHT] )
6384 								{
6385 									keystatus[SDL_SCANCODE_RIGHT] = 0;
6386 									if ( textInsertCaratPosition == -1 )
6387 									{
6388 										textInsertCaratPosition = strlen(inputstr);
6389 									}
6390 									else
6391 									{
6392 										++textInsertCaratPosition;
6393 										textInsertCaratPosition = std::min((int)strlen(inputstr), textInsertCaratPosition);
6394 									}
6395 									cursorflash = ticks;
6396 								}
6397 								if ( keystatus[SDL_SCANCODE_RETURN] )
6398 								{
6399 									if ( textInsertCaratPosition >= 0 )
6400 									{
6401 										textInsertCaratPosition = -1;
6402 									}
6403 									else
6404 									{
6405 										textInsertCaratPosition = strlen(inputstr);
6406 									}
6407 									keystatus[SDL_SCANCODE_RETURN] = 0;
6408 								}
6409 							}
6410 
6411 							// set the maximum length allowed for user input
6412 							if ( editproperty >= 3 && editproperty < 8 )
6413 							{
6414 								if ( editproperty == 7 )
6415 								{
6416 									inputlen = 32;
6417 								}
6418 								else
6419 								{
6420 									inputlen = 48;
6421 								}
6422 							}
6423 							else
6424 							{
6425 								if ( editproperty == 9 )
6426 								{
6427 									inputlen = 1;
6428 								}
6429 								else
6430 								{
6431 									inputlen = 4;
6432 								}
6433 							}
6434 							if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
6435 							{
6436 								if ( editproperty > 3 && editproperty < 8 )
6437 								{
6438 									spacing = 18;
6439 									if ( textInsertCaratPosition >= 0 )
6440 									{
6441 										printTextFormattedColor(font8x8_bmp, subx1 + 8 + textInsertCaratPosition * 8, suby1 + 44 + (editproperty - 1) * spacing, color, "\26");
6442 									}
6443 									else
6444 									{
6445 										printText(font8x8_bmp, subx1 + 8 + strlen(spriteProperties[editproperty]) * 8, suby1 + 44 + (editproperty - 1) * spacing, "\26");
6446 									}
6447 								}
6448 								else
6449 								{
6450 									spacing = 36;
6451 									if ( editproperty == 1 || editproperty == 2 )
6452 									{
6453 										spacing = 0;
6454 										inputFieldWidth = 64;
6455 										printText(font8x8_bmp, subx1 + 8 + (inputFieldWidth + 8) * editproperty + strlen(spriteProperties[editproperty]) * 8, suby1 + 44, "\26");
6456 									}
6457 									else if ( editproperty == 3 )
6458 									{
6459 										if ( textInsertCaratPosition >= 0 )
6460 										{
6461 											printTextFormattedColor(font8x8_bmp, subx1 + 8 + textInsertCaratPosition * 8, suby1 + 44 + spacing, color, "\26");
6462 										}
6463 										else
6464 										{
6465 											printText(font8x8_bmp, subx1 + 8 + strlen(spriteProperties[editproperty]) * 8, suby1 + 44 + spacing, "\26");
6466 										}
6467 									}
6468 									else
6469 									{
6470 										if ( editproperty >= 8 )
6471 										{
6472 											printText(font8x8_bmp, subx1 + 8 + strlen(spriteProperties[editproperty]) * 8, suby1 + 44 + (editproperty - 4) * spacing, "\26");
6473 										}
6474 										else
6475 										{
6476 											printText(font8x8_bmp, subx1 + 8 + strlen(spriteProperties[editproperty]) * 8, suby1 + 44 + editproperty * spacing, "\26");
6477 										}
6478 									}
6479 								}
6480 							}
6481 						}
6482 
6483 						if ( showTextSourceTooltip )
6484 						{
6485 							SDL_Rect src;
6486 							src.w = 74 * 8 + 4;
6487 							src.h = 240;
6488 							src.x = omousex - src.w / 2;
6489 							src.y = omousey + 16 - src.h / 2;
6490 							drawTooltip(&src);
6491 							printText(font8x8_bmp, src.x + 4, src.y + 4, "This sprite sends a message to all players in the specified color.");
6492 							printText(font8x8_bmp, src.x + 4, src.y + 16, "Text will appear as one line unless a new line symbol is entered.");
6493 							printText(font8x8_bmp, src.x + 4, src.y + 28, "To insert text onto a new line, enter \\n in the text field.");
6494 							printText(font8x8_bmp, src.x + 4, src.y + 40, "To address the player's name in the text, enter @p in the text field.");
6495 							printText(font8x8_bmp, src.x + 4, src.y + 52, "E.g \"Hello, \\n@p\"");
6496 							printText(font8x8_bmp, src.x + 4, src.y + 64, "Adding @script to the text allows some basic scripting instead of text.");
6497 							printText(font8x8_bmp, src.x + 4, src.y + 76, "Separate all tags with a space. Some tags allow a range of values.");
6498 							printText(font8x8_bmp, src.x + 4, src.y + 88, "@clrplayer clears player data. @class=1 sets class to warrior");
6499 							printText(font8x8_bmp, src.x + 4, src.y + 100, "@clrstats resets stats and HP/MP. @hunger=250 sets player hungry.");
6500 							printText(font8x8_bmp, src.x + 4, src.y + 112, "@nextlevel=2 triggers a 2 level change.");
6501 							printText(font8x8_bmp, src.x + 4, src.y + 124, "@copyNPC=2 player stats set to monster named \"scriptNPC\" that is NPC: 2");
6502 							printText(font8x8_bmp, src.x + 4, src.y + 136, "");
6503 							printText(font8x8_bmp, src.x + 4, src.y + 148, "Tags that take a map reference or range: (i.e tag=1-3,4-6 tag=8,10)");
6504 							printText(font8x8_bmp, src.x + 4, src.y + 160, "@power=11,15 powers tile x=11,y=15");
6505 							printText(font8x8_bmp, src.x + 4, src.y + 172, "@power=11-13,15-17 powers 3x3 grid from x=11,y=15 to x=13,y=17.");
6506 							printText(font8x8_bmp, src.x + 4, src.y + 184, "@unpower= unpower tile(s). @freezemonsters= freeze monster on tile(s)");
6507 							printText(font8x8_bmp, src.x + 4, src.y + 196, "@unfreezemonsters= unfreeze on tile(s). @killall= kill npcs on tile(s)");
6508 							printText(font8x8_bmp, src.x + 4, src.y + 208, "@killenemies= kill non- ally npcs on tile(s).");
6509 							printText(font8x8_bmp, src.x + 4, src.y + 220, "@nodropitems= npc will be marked to not drop items on death within tile(s)");
6510 						}
6511 					}
6512 				}
6513 				else if ( newwindow == 21 )
6514 				{
6515 					if ( selectedEntity != nullptr )
6516 					{
6517 						int numProperties = sizeof(signalTimerPropertyNames) / sizeof(signalTimerPropertyNames[0]); //find number of entries in property list
6518 						const int lenProperties = sizeof(signalTimerPropertyNames[0]) / sizeof(char); //find length of entry in property list
6519 						int spacing = 36; // 36 px between each item in the list.
6520 						int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
6521 						int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
6522 						int inputField_y = inputFieldHeader_y + 16;
6523 						int inputFieldWidth = 64; // width of the text field
6524 						int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
6525 						char tmpPropertyName[lenProperties] = "";
6526 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
6527 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
6528 						Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
6529 
6530 						for ( int i = 0; i < numProperties; i++ )
6531 						{
6532 							int propertyInt = atoi(spriteProperties[i]);
6533 
6534 							strcpy(tmpPropertyName, signalTimerPropertyNames[i]);
6535 							inputFieldHeader_y = suby1 + 28 + i * spacing;
6536 							inputField_y = inputFieldHeader_y + 16;
6537 							// box outlines then text
6538 							drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
6539 							// print values on top of boxes
6540 							printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing, spriteProperties[i]);
6541 							printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
6542 
6543 							if ( errorArr[i] != 1 )
6544 							{
6545 								if ( i == 0 )
6546 								{
6547 									if ( propertyInt > 3 || propertyInt < 0 )
6548 									{
6549 										propertyPageError(i, 0); // reset to default 0.
6550 									}
6551 									else
6552 									{
6553 										char tmpStr[8] = "";
6554 										switch ( propertyInt )
6555 										{
6556 											case 0:
6557 												strcpy(tmpStr, "West");
6558 												break;
6559 											case 1:
6560 												strcpy(tmpStr, "South");
6561 												break;
6562 											case 2:
6563 												strcpy(tmpStr, "East");
6564 												break;
6565 											case 3:
6566 												strcpy(tmpStr, "North");
6567 												break;
6568 											default:
6569 												break;
6570 										}
6571 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
6572 									}
6573 								}
6574 								else if ( i == 1 )
6575 								{
6576 									if ( propertyInt > 9999 || propertyInt < 0 )
6577 									{
6578 										propertyPageError(i, 0); // reset to default 0.
6579 									}
6580 								}
6581 								else if ( i == 2 )
6582 								{
6583 									if ( propertyInt > 9999 || propertyInt < 0 )
6584 									{
6585 										propertyPageError(i, 0); // reset to default 0.
6586 									}
6587 									else
6588 									{
6589 										if ( propertyInt == 0 )
6590 										{
6591 											printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "output without on/off toggling");
6592 										}
6593 									}
6594 								}
6595 								else if ( i == 3 )
6596 								{
6597 									if ( propertyInt > 9999 || propertyInt < 0 )
6598 									{
6599 										propertyPageError(i, 0); // reset to default 0.
6600 									}
6601 									else
6602 									{
6603 										if ( propertyInt == 0 )
6604 										{
6605 											printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "repeat infinite");
6606 										}
6607 									}
6608 								}
6609 								else if ( i == 4 )
6610 								{
6611 									if ( propertyInt > 1 || propertyInt < 0 )
6612 									{
6613 										propertyPageError(i, 0); // reset to default 0.
6614 									}
6615 									else
6616 									{
6617 										if ( propertyInt == 0 )
6618 										{
6619 											printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "turn off without input signal");
6620 										}
6621 										else if ( propertyInt == 1 )
6622 										{
6623 											printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "stay on without input signal");
6624 										}
6625 									}
6626 								}
6627 								else
6628 								{
6629 									// enter other row entries here
6630 								}
6631 							}
6632 
6633 							if ( errorMessage )
6634 							{
6635 								if ( errorArr[i] == 1 )
6636 								{
6637 									printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
6638 								}
6639 							}
6640 						}
6641 
6642 						propertyPageTextAndInput(numProperties, inputFieldWidth);
6643 
6644 						if ( editproperty < numProperties )   // edit
6645 						{
6646 							if ( !SDL_IsTextInputActive() )
6647 							{
6648 								SDL_StartTextInput();
6649 								inputstr = spriteProperties[0];
6650 							}
6651 
6652 							// set the maximum length allowed for user input
6653 							inputlen = 4;
6654 							propertyPageCursorFlash(spacing);
6655 						}
6656 					}
6657 				}
6658 				else if ( newwindow == 22 )
6659 				{
6660 					if ( selectedEntity != nullptr )
6661 					{
6662 						int numProperties = sizeof(customPortalPropertyNames) / sizeof(customPortalPropertyNames[0]); //find number of entries in property list
6663 						const int lenProperties = sizeof(customPortalPropertyNames[0]) / sizeof(char); //find length of entry in property list
6664 						int spacing = 36; // 36 px between each item in the list.
6665 						int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
6666 						int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
6667 						int inputField_y = inputFieldHeader_y + 16;
6668 						int inputFieldWidth = 64; // width of the text field
6669 						int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
6670 						char tmpPropertyName[lenProperties] = "";
6671 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
6672 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
6673 						Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
6674 
6675 						for ( int i = 0; i < numProperties; i++ )
6676 						{
6677 							int propertyInt = atoi(spriteProperties[i]);
6678 
6679 							strcpy(tmpPropertyName, customPortalPropertyNames[i]);
6680 							inputFieldHeader_y = suby1 + 28 + i * spacing;
6681 							inputField_y = inputFieldHeader_y + 16;
6682 							// box outlines then text
6683 							if ( i == 4 )
6684 							{
6685 								inputFieldWidth = 280; // width of the text field
6686 							}
6687 							else
6688 							{
6689 								inputFieldWidth = 64; // width of the text field
6690 							}
6691 							drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
6692 							// print values on top of boxes
6693 							printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing, spriteProperties[i]);
6694 							printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
6695 
6696 							if ( errorArr[i] != 1 )
6697 							{
6698 								if ( i == 0 )
6699 								{
6700 									if ( propertyInt > 9999 || propertyInt < 0 )
6701 									{
6702 										propertyPageError(i, 0); // reset to default 0.
6703 									}
6704 								}
6705 								else if ( i == 1 )
6706 								{
6707 									if ( propertyInt > 9 || propertyInt < 0 )
6708 									{
6709 										propertyPageError(i, 0); // reset to default 0.
6710 									}
6711 									else
6712 									{
6713 										if ( propertyInt != 0 )
6714 										{
6715 											printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color,
6716 												"using model textures %d-%d for animation",
6717 												atoi(spriteProperties[0]), atoi(spriteProperties[0]) + propertyInt - 1);
6718 										}
6719 									}
6720 								}
6721 								else if ( i == 2 )
6722 								{
6723 									if ( propertyInt > 999 || propertyInt < -999 )
6724 									{
6725 										propertyPageError(i, 0); // reset to default 0.
6726 									}
6727 								}
6728 								else if ( i == 3 )
6729 								{
6730 									if ( propertyInt > 99 || propertyInt < -99 )
6731 									{
6732 										propertyPageError(i, 0); // reset to default 0.
6733 									}
6734 									else
6735 									{
6736 										if ( spriteProperties[4][0] != 0 && propertyInt != 0 )
6737 										{
6738 											char shortName[16] = "";
6739 											strncpy(shortName, spriteProperties[4], 11);
6740 											if ( strlen(spriteProperties[4]) > 9 )
6741 											{
6742 												strcat(shortName, "..");
6743 											}
6744 											printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "move to instance %d of map name %s", propertyInt, shortName);
6745 										}
6746 										else if ( spriteProperties[4][0] != 0 && propertyInt == 0 )
6747 										{
6748 											char shortName[16] = "";
6749 											strncpy(shortName, spriteProperties[4], 11);
6750 											if ( strlen(spriteProperties[4]) > 9 )
6751 											{
6752 												strcat(shortName, "..");
6753 											}
6754 											printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "move to first instance of map name %s", propertyInt, shortName);
6755 										}
6756 										else
6757 										{
6758 											printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "jump %d levels", propertyInt);
6759 										}
6760 									}
6761 								}
6762 								else if ( i == 4 )
6763 								{
6764 
6765 								}
6766 								else if ( i == 5 )
6767 								{
6768 									if ( propertyInt > 1 || propertyInt < 0 )
6769 									{
6770 										propertyPageError(i, 0); // reset to default 0.
6771 									}
6772 									else
6773 									{
6774 										if ( propertyInt == 0 )
6775 										{
6776 											printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "always visible");
6777 										}
6778 										else if ( propertyInt == 1 )
6779 										{
6780 											printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "requires power to be visible");
6781 										}
6782 									}
6783 								}
6784 								else if ( i == 6 )
6785 								{
6786 									if ( propertyInt > 1 || propertyInt < 0 )
6787 									{
6788 										propertyPageError(i, 0); // reset to default 0.
6789 									}
6790 									else
6791 									{
6792 										if ( propertyInt == 0 )
6793 										{
6794 											if ( spriteProperties[4][0] != 0 )
6795 											{
6796 												printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "searching for map in normal levels");
6797 											}
6798 											else
6799 											{
6800 												printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "no toggle");
6801 											}
6802 										}
6803 										else if ( propertyInt == 1 )
6804 										{
6805 											if ( spriteProperties[4][0] != 0 )
6806 											{
6807 												printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "searching for map in secret levels");
6808 											}
6809 											else
6810 											{
6811 												printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "will toggle secret levels file");
6812 											}
6813 										}
6814 									}
6815 								}
6816 								else
6817 								{
6818 									// enter other row entries here
6819 								}
6820 							}
6821 
6822 							if ( errorMessage )
6823 							{
6824 								if ( errorArr[i] == 1 )
6825 								{
6826 									printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
6827 								}
6828 							}
6829 						}
6830 
6831 						propertyPageTextAndInput(numProperties, inputFieldWidth);
6832 
6833 						if ( editproperty < numProperties )   // edit
6834 						{
6835 							if ( !SDL_IsTextInputActive() )
6836 							{
6837 								SDL_StartTextInput();
6838 								inputstr = spriteProperties[0];
6839 							}
6840 
6841 							// set the maximum length allowed for user input
6842 
6843 							if ( editproperty == 4 )
6844 							{
6845 								inputlen = 32;
6846 							}
6847 							else
6848 							{
6849 								inputlen = 4;
6850 							}
6851 							propertyPageCursorFlash(spacing);
6852 						}
6853 					}
6854 				}
6855 				else if ( newwindow == 23 )
6856 				{
6857 					if ( selectedEntity != nullptr )
6858 					{
6859 						int numProperties = sizeof(tablePropertyNames) / sizeof(tablePropertyNames[0]); //find number of entries in property list
6860 						const int lenProperties = sizeof(tablePropertyNames[0]) / sizeof(char); //find length of entry in property list
6861 						int spacing = 36; // 36 px between each item in the list.
6862 						int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
6863 						int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
6864 						int inputField_y = inputFieldHeader_y + 16;
6865 						int inputFieldWidth = 64; // width of the text field
6866 						int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
6867 						char tmpPropertyName[lenProperties] = "";
6868 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
6869 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
6870 						Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
6871 
6872 						for ( int i = 0; i < numProperties; i++ )
6873 						{
6874 							int propertyInt = atoi(spriteProperties[i]);
6875 
6876 							strcpy(tmpPropertyName, tablePropertyNames[i]);
6877 							inputFieldHeader_y = suby1 + 28 + i * spacing;
6878 							inputField_y = inputFieldHeader_y + 16;
6879 							// box outlines then text
6880 							drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
6881 							// print values on top of boxes
6882 							printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing, spriteProperties[i]);
6883 							printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
6884 
6885 							if ( errorArr[i] != 1 )
6886 							{
6887 								if ( i == 0 )
6888 								{
6889 									if ( propertyInt > 7 || propertyInt < -1 )
6890 									{
6891 										propertyPageError(i, -1); // reset to default -1.
6892 									}
6893 									else
6894 									{
6895 										char tmpStr[32] = "";
6896 										switch ( propertyInt )
6897 										{
6898 											case -1:
6899 												strcpy(tmpStr, "default");
6900 												break;
6901 											case 0:
6902 												strcpy(tmpStr, "East");
6903 												break;
6904 											case 1:
6905 												strcpy(tmpStr, "Southeast");
6906 												break;
6907 											case 2:
6908 												strcpy(tmpStr, "South");
6909 												break;
6910 											case 3:
6911 												strcpy(tmpStr, "Southwest");
6912 												break;
6913 											case 4:
6914 												strcpy(tmpStr, "West");
6915 												break;
6916 											case 5:
6917 												strcpy(tmpStr, "Northwest");
6918 												break;
6919 											case 6:
6920 												strcpy(tmpStr, "North");
6921 												break;
6922 											case 7:
6923 												strcpy(tmpStr, "Northeast");
6924 												break;
6925 											default:
6926 												break;
6927 										}
6928 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
6929 									}
6930 								}
6931 								else if ( i == 1 )
6932 								{
6933 									if ( propertyInt > 4 || propertyInt < -1 )
6934 									{
6935 										propertyPageError(i, -1); // reset to default -1.
6936 									}
6937 									else
6938 									{
6939 										if ( propertyInt == -1 )
6940 										{
6941 											printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "random chairs", propertyInt);
6942 										}
6943 										else
6944 										{
6945 											printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "%d chairs", propertyInt);
6946 										}
6947 									}
6948 								}
6949 								else if ( i == 2 )
6950 								{
6951 									if ( propertyInt > 100 || propertyInt < -1 )
6952 									{
6953 										propertyPageError(i, -1); // reset to default -1.
6954 									}
6955 									else
6956 									{
6957 										if ( propertyInt == -1 )
6958 										{
6959 											printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "default random item chance");
6960 										}
6961 										else
6962 										{
6963 											printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "%d%% chance", propertyInt);
6964 										}
6965 									}
6966 								}
6967 								else
6968 								{
6969 									// enter other row entries here
6970 								}
6971 							}
6972 
6973 							if ( errorMessage )
6974 							{
6975 								if ( errorArr[i] == 1 )
6976 								{
6977 									printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
6978 								}
6979 							}
6980 						}
6981 
6982 						propertyPageTextAndInput(numProperties, inputFieldWidth);
6983 
6984 						if ( editproperty < numProperties )   // edit
6985 						{
6986 							if ( !SDL_IsTextInputActive() )
6987 							{
6988 								SDL_StartTextInput();
6989 								inputstr = spriteProperties[0];
6990 							}
6991 
6992 							// set the maximum length allowed for user input
6993 							if ( editproperty == 2 )
6994 							{
6995 								inputlen = 4;
6996 							}
6997 							else
6998 							{
6999 								inputlen = 3;
7000 							}
7001 							propertyPageCursorFlash(spacing);
7002 						}
7003 					}
7004 				}
7005 				else if ( newwindow == 24 )
7006 				{
7007 						if ( selectedEntity != nullptr )
7008 					{
7009 						int numProperties = sizeof(readableBookPropertyNames) / sizeof(readableBookPropertyNames[0]); //find number of entries in property list
7010 						const int lenProperties = sizeof(readableBookPropertyNames[0]) / sizeof(char); //find length of entry in property list
7011 						int spacing = 36; // 36 px between each item in the list.
7012 						int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
7013 						int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
7014 						int inputField_y = inputFieldHeader_y + 16;
7015 						int inputFieldWidth = 64; // width of the text field
7016 						int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
7017 						char tmpPropertyName[lenProperties] = "";
7018 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
7019 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
7020 						Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
7021 
7022 						for ( int i = 0; i < numProperties; i++ )
7023 						{
7024 							int propertyInt = atoi(spriteProperties[i]);
7025 
7026 							strcpy(tmpPropertyName, readableBookPropertyNames[i]);
7027 							inputFieldHeader_y = suby1 + 28 + i * spacing;
7028 							inputField_y = inputFieldHeader_y + 16;
7029 							// box outlines then text
7030 							if ( i == 3 )
7031 							{
7032 								inputFieldWidth = subx2 - inputField_x; // width of the text field
7033 							}
7034 							else
7035 							{
7036 								inputFieldWidth = 64; // width of the text field
7037 							}
7038 							drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
7039 							// print values on top of boxes
7040 							printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing, spriteProperties[i]);
7041 							printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
7042 
7043 							if ( errorArr[i] != 1 )
7044 							{
7045 								if ( i == 0 )
7046 								{
7047 									if ( propertyInt == 2 )
7048 									{
7049 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, SDL_MapRGB(mainsurface->format, 200, 128, 0), "Decrepit");
7050 									}
7051 									else if ( propertyInt == 3 )
7052 									{
7053 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, SDL_MapRGB(mainsurface->format, 255, 255, 0), "Worn");
7054 									}
7055 									else if ( propertyInt == 4 )
7056 									{
7057 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, SDL_MapRGB(mainsurface->format, 128, 200, 0), "Servicable");
7058 									}
7059 									else if ( propertyInt == 5 )
7060 									{
7061 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, SDL_MapRGB(mainsurface->format, 0, 255, 0), "Excellent");
7062 									}
7063 									else if ( propertyInt == 1 )
7064 									{
7065 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, SDL_MapRGB(mainsurface->format, 255, 0, 0), "Broken");
7066 									}
7067 									else if ( propertyInt == 0 )
7068 									{
7069 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorRandom, "Random");
7070 									}
7071 									else if ( propertyInt < 0 || propertyInt > 5 )
7072 									{
7073 										propertyPageError(i, 0); // reset to default 0.
7074 									}
7075 								}
7076 								else if ( i == 1 )
7077 								{
7078 									if ( strcmp(spriteProperties[i], "00") == 0 )
7079 									{
7080 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorRandom, "Random");
7081 									}
7082 									else if ( propertyInt > 9 || propertyInt < -9 )
7083 									{
7084 										propertyPageError(i, 0); // reset to default 0.
7085 									}
7086 								}
7087 								else if ( i == 2 )
7088 								{
7089 									if ( propertyInt == 1 )
7090 									{
7091 										color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
7092 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "Identified");
7093 									}
7094 									else if ( propertyInt == 0 )
7095 									{
7096 										color = SDL_MapRGB(mainsurface->format, 255, 255, 0);
7097 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "Unidentified");
7098 									}
7099 									else if ( propertyInt == 2 )
7100 									{
7101 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorRandom, "Random");
7102 									}
7103 									else
7104 									{
7105 										propertyPageError(i, 0); // reset to default 0.
7106 									}
7107 								}
7108 								else
7109 								{
7110 									// enter other row entries here
7111 								}
7112 							}
7113 
7114 							if ( errorMessage )
7115 							{
7116 								if ( errorArr[i] == 1 )
7117 								{
7118 									printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
7119 								}
7120 							}
7121 						}
7122 
7123 						propertyPageTextAndInput(numProperties, inputFieldWidth);
7124 
7125 						if ( editproperty < numProperties )   // edit
7126 						{
7127 							if ( !SDL_IsTextInputActive() )
7128 							{
7129 								SDL_StartTextInput();
7130 								inputstr = spriteProperties[0];
7131 							}
7132 
7133 							// set the maximum length allowed for user input
7134 
7135 							if ( editproperty == 3 )
7136 							{
7137 								inputlen = 48;
7138 							}
7139 							else
7140 							{
7141 								inputlen = 4;
7142 							}
7143 							propertyPageCursorFlash(spacing);
7144 						}
7145 					}
7146 				}
7147 				else if ( newwindow == 26 )
7148 				{
7149 					if ( selectedEntity != NULL )
7150 					{
7151 						int numProperties = sizeof(doorPropertyNames) / sizeof(doorPropertyNames[0]); //find number of entries in property list
7152 						const int lenProperties = sizeof(doorPropertyNames[0]) / sizeof(char); //find length of entry in property list
7153 						int spacing = 36; // 36 px between each item in the list.
7154 						int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
7155 						int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
7156 						int inputField_y = inputFieldHeader_y + 16;
7157 						int inputFieldWidth = 64; // width of the text field
7158 						int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
7159 						char tmpPropertyName[lenProperties] = "";
7160 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
7161 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
7162 						Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
7163 
7164 						for ( int i = 0; i < numProperties; i++ )
7165 						{
7166 							int propertyInt = atoi(spriteProperties[i]);
7167 
7168 							strcpy(tmpPropertyName, doorPropertyNames[i]);
7169 							inputFieldHeader_y = suby1 + 28 + i * spacing;
7170 							inputField_y = inputFieldHeader_y + 16;
7171 							// box outlines then text
7172 							drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
7173 							// print values on top of boxes
7174 							printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing, spriteProperties[i]);
7175 							printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
7176 
7177 							if ( errorArr[i] != 1 )
7178 							{
7179 								if ( i == 0 )
7180 								{
7181 									if ( propertyInt > 2 || propertyInt < 0 )
7182 									{
7183 										propertyPageError(i, 0); // reset to default 0 random.
7184 									}
7185 									else
7186 									{
7187 										char tmpStr[32] = "";
7188 										if ( propertyInt == 1 )
7189 										{
7190 											strcpy(tmpStr, "force locked");
7191 										}
7192 										else if ( propertyInt == 2 )
7193 										{
7194 											strcpy(tmpStr, "force unlocked");
7195 										}
7196 										else
7197 										{
7198 											strcpy(tmpStr, "default random");
7199 										}
7200 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
7201 									}
7202 								}
7203 								else if ( i == 1 || i == 2 )
7204 								{
7205 									if ( propertyInt > 1 || propertyInt < 0 )
7206 									{
7207 										propertyPageError(i, 0); // reset to default no disable
7208 									}
7209 									else
7210 									{
7211 										char tmpStr[32] = "";
7212 										if ( propertyInt == 1 )
7213 										{
7214 											strcpy(tmpStr, "disabled");
7215 										}
7216 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
7217 									}
7218 								}
7219 								else
7220 								{
7221 									// enter other row entries here
7222 								}
7223 							}
7224 
7225 							if ( errorMessage )
7226 							{
7227 								if ( errorArr[i] == 1 )
7228 								{
7229 									printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
7230 								}
7231 							}
7232 						}
7233 
7234 						propertyPageTextAndInput(numProperties, inputFieldWidth);
7235 
7236 						if ( editproperty < numProperties )   // edit
7237 						{
7238 							if ( !SDL_IsTextInputActive() )
7239 							{
7240 								SDL_StartTextInput();
7241 								inputstr = spriteProperties[0];
7242 							}
7243 
7244 							// set the maximum length allowed for user input
7245 							inputlen = 2;
7246 							propertyPageCursorFlash(spacing);
7247 						}
7248 					}
7249 				}
7250 				else if ( newwindow == 27 )
7251 				{
7252 					if ( selectedEntity != NULL )
7253 					{
7254 						int numProperties = sizeof(gatePropertyNames) / sizeof(gatePropertyNames[0]); //find number of entries in property list
7255 						const int lenProperties = sizeof(gatePropertyNames[0]) / sizeof(char); //find length of entry in property list
7256 						int spacing = 36; // 36 px between each item in the list.
7257 						int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
7258 						int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
7259 						int inputField_y = inputFieldHeader_y + 16;
7260 						int inputFieldWidth = 64; // width of the text field
7261 						int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
7262 						char tmpPropertyName[lenProperties] = "";
7263 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
7264 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
7265 						Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
7266 
7267 						for ( int i = 0; i < numProperties; i++ )
7268 						{
7269 							int propertyInt = atoi(spriteProperties[i]);
7270 
7271 							strcpy(tmpPropertyName, gatePropertyNames[i]);
7272 							inputFieldHeader_y = suby1 + 28 + i * spacing;
7273 							inputField_y = inputFieldHeader_y + 16;
7274 							// box outlines then text
7275 							drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
7276 							// print values on top of boxes
7277 							printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing, spriteProperties[i]);
7278 							printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
7279 
7280 							if ( errorArr[i] != 1 )
7281 							{
7282 								if ( i == 0 )
7283 								{
7284 									if ( propertyInt > 1 || propertyInt < 0 )
7285 									{
7286 										propertyPageError(i, 0); // reset to default no disable
7287 									}
7288 									else
7289 									{
7290 										char tmpStr[32] = "";
7291 										if ( propertyInt == 1 )
7292 										{
7293 											strcpy(tmpStr, "disabled");
7294 										}
7295 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
7296 									}
7297 								}
7298 								else
7299 								{
7300 									// enter other row entries here
7301 								}
7302 							}
7303 
7304 							if ( errorMessage )
7305 							{
7306 								if ( errorArr[i] == 1 )
7307 								{
7308 									printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
7309 								}
7310 							}
7311 						}
7312 
7313 						propertyPageTextAndInput(numProperties, inputFieldWidth);
7314 
7315 						if ( editproperty < numProperties )   // edit
7316 						{
7317 							if ( !SDL_IsTextInputActive() )
7318 							{
7319 								SDL_StartTextInput();
7320 								inputstr = spriteProperties[0];
7321 							}
7322 
7323 							// set the maximum length allowed for user input
7324 							inputlen = 2;
7325 							propertyPageCursorFlash(spacing);
7326 						}
7327 					}
7328 				}
7329 				else if ( newwindow == 28 )
7330 				{
7331 					if ( selectedEntity != nullptr )
7332 					{
7333 						int numProperties = sizeof(playerSpawnPropertyNames) / sizeof(playerSpawnPropertyNames[0]); //find number of entries in property list
7334 						const int lenProperties = sizeof(playerSpawnPropertyNames[0]) / sizeof(char); //find length of entry in property list
7335 						int spacing = 36; // 36 px between each item in the list.
7336 						int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
7337 						int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
7338 						int inputField_y = inputFieldHeader_y + 16;
7339 						int inputFieldWidth = 64; // width of the text field
7340 						int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
7341 						char tmpPropertyName[lenProperties] = "";
7342 						Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
7343 						Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
7344 						Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
7345 
7346 						for ( int i = 0; i < numProperties; i++ )
7347 						{
7348 							int propertyInt = atoi(spriteProperties[i]);
7349 
7350 							strcpy(tmpPropertyName, playerSpawnPropertyNames[i]);
7351 							inputFieldHeader_y = suby1 + 28 + i * spacing;
7352 							inputField_y = inputFieldHeader_y + 16;
7353 							// box outlines then text
7354 							drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
7355 							// print values on top of boxes
7356 							printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing, spriteProperties[i]);
7357 							printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
7358 
7359 							if ( errorArr[i] != 1 )
7360 							{
7361 								if ( i == 0 )
7362 								{
7363 									if ( propertyInt > 7 || propertyInt < -1 )
7364 									{
7365 										propertyPageError(i, 0); // reset to default 0.
7366 									}
7367 									else
7368 									{
7369 										char tmpStr[32] = "";
7370 										switch ( propertyInt )
7371 										{
7372 											case -1:
7373 												strcpy(tmpStr, "random");
7374 												break;
7375 											case 0:
7376 												strcpy(tmpStr, "East");
7377 												break;
7378 											case 1:
7379 												strcpy(tmpStr, "Southeast");
7380 												break;
7381 											case 2:
7382 												strcpy(tmpStr, "South");
7383 												break;
7384 											case 3:
7385 												strcpy(tmpStr, "Southwest");
7386 												break;
7387 											case 4:
7388 												strcpy(tmpStr, "West");
7389 												break;
7390 											case 5:
7391 												strcpy(tmpStr, "Northwest");
7392 												break;
7393 											case 6:
7394 												strcpy(tmpStr, "North");
7395 												break;
7396 											case 7:
7397 												strcpy(tmpStr, "Northeast");
7398 												break;
7399 											default:
7400 												break;
7401 										}
7402 										printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, tmpStr);
7403 									}
7404 								}
7405 								else
7406 								{
7407 									// enter other row entries here
7408 								}
7409 							}
7410 
7411 							if ( errorMessage )
7412 							{
7413 								if ( errorArr[i] == 1 )
7414 								{
7415 									printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
7416 								}
7417 							}
7418 						}
7419 
7420 						propertyPageTextAndInput(numProperties, inputFieldWidth);
7421 
7422 						if ( editproperty < numProperties )   // edit
7423 						{
7424 							if ( !SDL_IsTextInputActive() )
7425 							{
7426 								SDL_StartTextInput();
7427 								inputstr = spriteProperties[0];
7428 							}
7429 
7430 							// set the maximum length allowed for user input
7431 							inputlen = 2;
7432 							propertyPageCursorFlash(spacing);
7433 						}
7434 					}
7435 				}
7436 				else if ( newwindow == 25 )
7437 				{
7438 					//if ( selectedEntity != nullptr )
7439 					//{
7440 					//	int numProperties = sizeof(playerClassSetterPropertyNames) / sizeof(playerClassSetterPropertyNames[0]); //find number of entries in property list
7441 					//	const int lenProperties = sizeof(playerClassSetterPropertyNames[0]) / sizeof(char); //find length of entry in property list
7442 					//	int spacing = 36; // 36 px between each item in the list.
7443 					//	int inputFieldHeader_y = suby1 + 28; // 28 px spacing from subwindow start.
7444 					//	int inputField_x = subx1 + 8; // 8px spacing from subwindow start.
7445 					//	int inputField_y = inputFieldHeader_y + 16;
7446 					//	int inputFieldWidth = 64; // width of the text field
7447 					//	int inputFieldFeedback_x = inputField_x + inputFieldWidth + 8;
7448 					//	char tmpPropertyName[lenProperties] = "";
7449 					//	Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 0);
7450 					//	Uint32 colorRandom = SDL_MapRGB(mainsurface->format, 0, 168, 255);
7451 					//	Uint32 colorError = SDL_MapRGB(mainsurface->format, 255, 0, 0);
7452 
7453 					//	for ( int i = 0; i < numProperties; i++ )
7454 					//	{
7455 					//		int propertyInt = atoi(spriteProperties[i]);
7456 
7457 					//		strcpy(tmpPropertyName, playerClassSetterPropertyNames[i]);
7458 					//		inputFieldHeader_y = suby1 + 28 + i * spacing;
7459 					//		inputField_y = inputFieldHeader_y + 16;
7460 					//		// box outlines then text
7461 					//		inputFieldWidth = 64; // width of the text field
7462 					//		drawDepressed(inputField_x - 4, inputField_y - 4, inputField_x - 4 + inputFieldWidth, inputField_y + 16 - 4);
7463 					//		// print values on top of boxes
7464 					//		printText(font8x8_bmp, inputField_x, suby1 + 44 + i * spacing, spriteProperties[i]);
7465 					//		printText(font8x8_bmp, inputField_x, inputFieldHeader_y, tmpPropertyName);
7466 
7467 					//		if ( errorArr[i] != 1 )
7468 					//		{
7469 					//			if ( i == 0 )
7470 					//			{
7471 					//				if ( propertyInt < 0 || propertyInt > NUMCLASSES - 1 )
7472 					//				{
7473 					//					propertyPageError(i, 0); // reset to default 0.
7474 					//				}
7475 					//				else
7476 					//				{
7477 					//					printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, playerClassLangEntry(propertyInt, 0));
7478 					//				}
7479 					//			}
7480 					//			else if ( i == 1 )
7481 					//			{
7482 					//				if ( propertyInt > 1 || propertyInt < 0 )
7483 					//				{
7484 					//					propertyPageError(i, 0); // reset to default 0.
7485 					//				}
7486 					//				else if ( propertyInt == 1 )
7487 					//				{
7488 					//					printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "Trigger once only");
7489 					//				}
7490 					//				else if ( propertyInt == 0 )
7491 					//				{
7492 					//					printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, color, "Can re-trigger");
7493 					//				}
7494 					//			}
7495 					//			else
7496 					//			{
7497 					//				// enter other row entries here
7498 					//			}
7499 					//		}
7500 
7501 					//		if ( errorMessage )
7502 					//		{
7503 					//			if ( errorArr[i] == 1 )
7504 					//			{
7505 					//				printTextFormattedColor(font8x8_bmp, inputFieldFeedback_x, inputField_y, colorError, "Invalid ID!");
7506 					//			}
7507 					//		}
7508 					//	}
7509 
7510 					//	propertyPageTextAndInput(numProperties, inputFieldWidth);
7511 
7512 					//	if ( editproperty < numProperties )   // edit
7513 					//	{
7514 					//		if ( !SDL_IsTextInputActive() )
7515 					//		{
7516 					//			SDL_StartTextInput();
7517 					//			inputstr = spriteProperties[0];
7518 					//		}
7519 
7520 					//		// set the maximum length allowed for user input
7521 					//		inputlen = 3;
7522 					//		propertyPageCursorFlash(spacing);
7523 					//	}
7524 					//}
7525 				}
7526 				else if ( newwindow == 16 || newwindow == 17 )
7527 				{
7528 					int textColumnLeft = subx1 + 16;
7529 					int textColumnRight = (subx2 - subx1) / 2 + 300;
7530 					int pady = suby1 + 16;
7531 					int spacing = 0;
7532 					Uint32 colorHeader = SDL_MapRGB(mainsurface->format, 0, 255, 0);
7533 					char helptext[128];
7534 
7535 					if ( newwindow == 16 )
7536 					{
7537 						printTextFormattedColor(font8x8_bmp, textColumnLeft, pady + spacing, colorHeader, "Editor File Shortcuts:");
7538 						spacing += 12;
7539 						strcpy(helptext, "New Map:                            CTRL + N");
7540 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7541 						spacing += 12;
7542 						strcpy(helptext, "Open:                               CTRL + O");
7543 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7544 						spacing += 12;
7545 						strcpy(helptext, "Save:                               CTRL + S");
7546 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7547 						spacing += 12;
7548 						strcpy(helptext, "Change Load/Save Directory:         CTRL + D");
7549 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7550 						spacing += 12;
7551 						strcpy(helptext, "Close Window/Dialogue:              CTRL + M");
7552 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7553 						spacing += 12;
7554 						strcpy(helptext, "Delete Text:                        Backspace or Grave (`)");
7555 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7556 
7557 						spacing += 16;
7558 
7559 						printTextFormattedColor(font8x8_bmp, textColumnLeft, pady + spacing, colorHeader, "Editor Functions:");
7560 						spacing += 12;
7561 						strcpy(helptext, "Open Sprite Window:                 S");
7562 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7563 						spacing += 12;
7564 						strcpy(helptext, "Open Tile Window:                   T");
7565 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7566 						spacing += 12;
7567 						strcpy(helptext, "Sprite Properties:                  F2");
7568 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7569 						spacing += 12;
7570 						strcpy(helptext, "Map Properties:                     CTRL + M");
7571 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7572 						spacing += 12;
7573 						strcpy(helptext, "Delete Selected Sprite:             DEL");
7574 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7575 						spacing += 12;
7576 						strcpy(helptext, "Cycle Stacked Sprites:              C");
7577 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7578 
7579 						spacing += 16;
7580 
7581 						printTextFormattedColor(font8x8_bmp, textColumnLeft, pady + spacing, colorHeader, "Navigation:");
7582 						spacing += 12;
7583 						strcpy(helptext, "Move Camera/View:                   Arrow Keys");
7584 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7585 						spacing += 12;
7586 						strcpy(helptext, "Change Current Wall Layer:          SHIFT + Scrollwheel");
7587 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7588 						spacing += 12;
7589 						strcpy(helptext, "Change Current Wall Layer:          CTRL + U, CTRL + P");
7590 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7591 						spacing += 12;
7592 						strcpy(helptext, "Toggle First Person Camera:         F");
7593 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7594 
7595 						spacing += 16;
7596 
7597 						printTextFormattedColor(font8x8_bmp, textColumnLeft, pady + spacing, colorHeader, "Tile Palette (Last Used Tiles):");
7598 						spacing += 12;
7599 						strcpy(helptext, "Cycle Through Current Tile Palette: Scrollwheel");
7600 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7601 						spacing += 12;
7602 						strcpy(helptext, "Cycle Through All Palettes:         CTRL + Scrollwheel");
7603 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7604 						spacing += 12;
7605 						strcpy(helptext, "Choose Specific Tile In Palette:    Numpad 0-9");
7606 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7607 						spacing += 12;
7608 						strcpy(helptext, "Choose Specific Tile In Palette:    Left Click Tile");
7609 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7610 						spacing += 12;
7611 						strcpy(helptext, "Lock Changes to Current Palette:    Numpad *");
7612 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7613 						spacing += 12;
7614 						strcpy(helptext, "Go To Next Palette:                 Numpad +");
7615 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7616 						spacing += 12;
7617 						strcpy(helptext, "Go To Previous Palette:             Numpad -");
7618 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7619 						spacing += 12;
7620 						strcpy(helptext, "Clear Tile in Palette:              Right Click Tile");
7621 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7622 					}
7623 					else if ( newwindow == 17 )
7624 					{
7625 						printTextFormattedColor(font8x8_bmp, textColumnLeft, pady + spacing, colorHeader, "Editing Tools:");
7626 						spacing += 20;
7627 
7628 						printTextFormattedColor(font8x8_bmp, textColumnLeft, pady + spacing, colorHeader, "Pencil:");
7629 						strcpy(helptext, "        Draws currently selected tile on current wall layer.");
7630 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7631 						spacing += 12;
7632 						strcpy(helptext, "   Does not select sprites. Right click sets the selected tile");
7633 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7634 						spacing += 12;
7635 						strcpy(helptext, "   under the cursor to selected.");
7636 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7637 						spacing += 20;
7638 						printTextFormattedColor(font8x8_bmp, textColumnLeft, pady + spacing, colorHeader, "Point:");
7639 						strcpy(helptext, "       Selects sprites only. Sprites can be moved or deleted once");
7640 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7641 						spacing += 12;
7642 						strcpy(helptext, "   placed and selected with this tool. Left click selects, right");
7643 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7644 						spacing += 12;
7645 						strcpy(helptext, "   clicking duplicates a sprite and places it the cursor.");
7646 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7647 						spacing += 20;
7648 						strcpy(helptext, "   When sprites are stacked, only the lowest listed sprite is");
7649 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7650 						spacing += 12;
7651 						strcpy(helptext, "   selected. Hovering over multiple sprites and cycling with C");
7652 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7653 						spacing += 12;
7654 						strcpy(helptext, "   allows you to change the order that sprites are drawn in");
7655 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7656 						spacing += 12;
7657 						strcpy(helptext, "   the editor.");
7658 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7659 						spacing += 20;
7660 						strcpy(helptext, "   Certain sprites like monsters, chests, boulder traps, and most");
7661 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7662 						spacing += 12;
7663 						strcpy(helptext, "   Blessed Addition sprites (sprite 75 and onwards) have extra");
7664 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7665 						spacing += 12;
7666 						strcpy(helptext, "   customisable properties when F2 is pressed while the sprite");
7667 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7668 						spacing += 12;
7669 						strcpy(helptext, "   is selected using this tool. If no sprite is selected, F2");
7670 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7671 						spacing += 12;
7672 						strcpy(helptext, "   will show properties of the last sprite selected.");
7673 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7674 
7675 						spacing += 20;
7676 						printTextFormattedColor(font8x8_bmp, textColumnLeft, pady + spacing, colorHeader, "Brush:");
7677 						strcpy(helptext, "       Same as pencil, but draws a larger area at once.");
7678 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7679 
7680 						spacing += 20;
7681 						printTextFormattedColor(font8x8_bmp, textColumnLeft, pady + spacing, colorHeader, "Select:");
7682 						strcpy(helptext, "        Selects area of tiles or sprites. Tiles can be copied/");
7683 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7684 						spacing += 12;
7685 						strcpy(helptext, "   pasted/deleted in groups. Sprites can be moved in groups");
7686 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7687 						spacing += 12;
7688 						strcpy(helptext, "   with ALT + Arrow Keys. Selection can be moved with CTRL + ");
7689 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7690 						spacing += 12;
7691 						strcpy(helptext, "   Arrow Keys, and resized with SHIFT + Arrow Keys.\n");
7692 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7693 
7694 						spacing += 20;
7695 						printTextFormattedColor(font8x8_bmp, textColumnLeft, pady + spacing, colorHeader, "Fill:");
7696 						strcpy(helptext, "      Fills in left-clicked area with currently selected tile.");
7697 						printTextFormatted(font8x8_bmp, textColumnLeft, pady + spacing, helptext);
7698 						spacing += 12;
7699 					}
7700 				}
7701 
7702 				if ( keystatus[SDL_SCANCODE_ESCAPE] )
7703 				{
7704 					keystatus[SDL_SCANCODE_ESCAPE] = 0;
7705 					if ( newwindow > 1 )
7706 					{
7707 						//buttonCloseSpriteSubwindow(NULL);
7708 					}
7709 					else if ( openwindow > 0 || savewindow == 1 )
7710 					{
7711 						buttonCloseSubwindow(NULL);
7712 					}
7713 					if ( newwindow == 16 || newwindow == 17 )
7714 					{
7715 						buttonCloseSubwindow(NULL);
7716 					}
7717 				}
7718 				if ( keystatus[SDL_SCANCODE_RETURN] )
7719 				{
7720 					keystatus[SDL_SCANCODE_RETURN] = 0;
7721 					if ( newwindow > 1 )
7722 					{
7723 						//buttonSpritePropertiesConfirm(NULL);
7724 					}
7725 					else if ( openwindow == 1 )
7726 					{
7727 						buttonOpenConfirm(NULL);
7728 					}
7729 					else if ( savewindow == 1 )
7730 					{
7731 						//buttonSaveConfirm(NULL);
7732 					}
7733 					if ( newwindow == 16 )
7734 					{
7735 						buttonEditorToolsHelp(nullptr);
7736 					}
7737 					else if ( newwindow == 17 )
7738 					{
7739 						buttonCloseSubwindow(nullptr);
7740 					}
7741 				}
7742 			}
7743 			else
7744 			{
7745 				if ( SDL_IsTextInputActive() )
7746 				{
7747 					SDL_StopTextInput();
7748 				}
7749 
7750 				// handle hotkeys
7751 				if ( keystatus[SDL_SCANCODE_LCTRL] || keystatus[SDL_SCANCODE_RCTRL] )
7752 				{
7753 					if ( keystatus[SDL_SCANCODE_N] && !keystatus[SDL_SCANCODE_LSHIFT] && !keystatus[SDL_SCANCODE_RSHIFT] )
7754 					{
7755 						keystatus[SDL_SCANCODE_N] = 0;
7756 						buttonNew(NULL);
7757 						groupedEntities.clear();
7758 					}
7759 					if ( keystatus[SDL_SCANCODE_S] )
7760 					{
7761 						keystatus[SDL_SCANCODE_S] = 0;
7762 						buttonSave(NULL);
7763 					}
7764 					if ( keystatus[SDL_SCANCODE_O] )
7765 					{
7766 						keystatus[SDL_SCANCODE_O] = 0;
7767 						buttonOpen(NULL);
7768 						groupedEntities.clear();
7769 					}
7770 					if ( keystatus[SDL_SCANCODE_X] )
7771 					{
7772 						keystatus[SDL_SCANCODE_X] = 0;
7773 						buttonCut(NULL);
7774 					}
7775 					if ( keystatus[SDL_SCANCODE_C] )
7776 					{
7777 						keystatus[SDL_SCANCODE_C] = 0;
7778 						buttonCopy(NULL);
7779 						groupedEntities.clear();
7780 					}
7781 					if ( keystatus[SDL_SCANCODE_V] )
7782 					{
7783 						keystatus[SDL_SCANCODE_V] = 0;
7784 						buttonPaste(NULL);
7785 						groupedEntities.clear();
7786 					}
7787 					if ( keystatus[SDL_SCANCODE_A] )
7788 					{
7789 						keystatus[SDL_SCANCODE_A] = 0;
7790 						buttonSelectAll(NULL);
7791 						reselectEntityGroup();
7792 					}
7793 					if ( keystatus[SDL_SCANCODE_Z] )
7794 					{
7795 						keystatus[SDL_SCANCODE_Z] = 0;
7796 						buttonUndo(NULL);
7797 						groupedEntities.clear();
7798 					}
7799 					if ( keystatus[SDL_SCANCODE_Y] )
7800 					{
7801 						keystatus[SDL_SCANCODE_Y] = 0;
7802 						buttonRedo(NULL);
7803 						groupedEntities.clear();
7804 					}
7805 					if ( keystatus[SDL_SCANCODE_G] )
7806 					{
7807 						keystatus[SDL_SCANCODE_G] = 0;
7808 						buttonGrid(NULL);
7809 					}
7810 					if ( keystatus[SDL_SCANCODE_D] )
7811 					{
7812 						keystatus[SDL_SCANCODE_D] = 0;
7813 						buttonOpenDirectory(NULL);
7814 					}
7815 					if ( keystatus[SDL_SCANCODE_T] )
7816 					{
7817 						keystatus[SDL_SCANCODE_T] = 0;
7818 						buttonToolbox(NULL);
7819 					}
7820 					if ( keystatus[SDL_SCANCODE_E] )
7821 					{
7822 						keystatus[SDL_SCANCODE_E] = 0;
7823 						buttonViewSprites(NULL);
7824 					}
7825 					if ( keystatus[SDL_SCANCODE_L] )
7826 					{
7827 						keystatus[SDL_SCANCODE_L] = 0;
7828 						buttonAllLayers(NULL);
7829 					}
7830 					if ( keystatus[SDL_SCANCODE_H] )
7831 					{
7832 						keystatus[SDL_SCANCODE_H] = 0;
7833 						buttonHoverText(NULL);
7834 					}
7835 					if ( keystatus[SDL_SCANCODE_I] )
7836 					{
7837 						keystatus[SDL_SCANCODE_I] = 0;
7838 						buttonStatusBar(NULL);
7839 					}
7840 					if ( keystatus[SDL_SCANCODE_M] )
7841 					{
7842 						keystatus[SDL_SCANCODE_M] = 0;
7843 						buttonAttributes(NULL);
7844 					}
7845 					//Cycle layer up.
7846 					if ( keystatus[SDL_SCANCODE_U] )
7847 					{
7848 						keystatus[SDL_SCANCODE_U] = 0;
7849 						drawlayer = std::min(drawlayer + 1, MAPLAYERS - 1);
7850 					}
7851 					//Cycle layer down.
7852 					if ( keystatus[SDL_SCANCODE_P] )
7853 					{
7854 						keystatus[SDL_SCANCODE_P] = 0;
7855 						drawlayer = std::max(drawlayer - 1, 0);
7856 					}
7857 					if ( keystatus[SDL_SCANCODE_LSHIFT] || keystatus[SDL_SCANCODE_RSHIFT] )
7858 					{
7859 						if ( keystatus[SDL_SCANCODE_N] )
7860 						{
7861 							keystatus[SDL_SCANCODE_N] = 0;
7862 							buttonClearMap(NULL);
7863 							groupedEntities.clear();
7864 						}
7865 					}
7866 					if ( keystatus[SDL_SCANCODE_DOWN] )
7867 					{
7868 						keystatus[SDL_SCANCODE_DOWN] = 0;
7869 						// move selection
7870 						if ( selectedarea_y2 < map.height - 1 )
7871 						{
7872 							selectedarea_y2 += 1;
7873 							if ( selectedarea_y1 < map.height - 1 )
7874 							{
7875 								selectedarea_y1 += 1;
7876 							}
7877 							reselectEntityGroup();
7878 						}
7879 					}
7880 					else if ( keystatus[SDL_SCANCODE_UP] )
7881 					{
7882 						keystatus[SDL_SCANCODE_UP] = 0;
7883 						// move selection
7884 						if ( selectedarea_y1 > 0 )
7885 						{
7886 							selectedarea_y1 -= 1;
7887 							if ( selectedarea_y2 > 0 )
7888 							{
7889 								selectedarea_y2 -= 1;
7890 							}
7891 							reselectEntityGroup();
7892 						}
7893 					}
7894 					else if ( keystatus[SDL_SCANCODE_LEFT] )
7895 					{
7896 						keystatus[SDL_SCANCODE_LEFT] = 0;
7897 						// move selection
7898 						if ( selectedarea_x1 > 0 )
7899 						{
7900 							selectedarea_x1 -= 1;
7901 							if ( selectedarea_x2 > 0 )
7902 							{
7903 								selectedarea_x2 -= 1;
7904 							}
7905 							reselectEntityGroup();
7906 						}
7907 					}
7908 					else if ( keystatus[SDL_SCANCODE_RIGHT] )
7909 					{
7910 						keystatus[SDL_SCANCODE_RIGHT] = 0;
7911 						// move selection
7912 						if ( selectedarea_x2 < map.width - 1 )
7913 						{
7914 							selectedarea_x2 += 1;
7915 							if ( selectedarea_x1 < map.width - 1 )
7916 							{
7917 								selectedarea_x1 += 1;
7918 							}
7919 							reselectEntityGroup();
7920 						}
7921 					}
7922 				}
7923 				else
7924 				{
7925 					if ( keystatus[SDL_SCANCODE_LSHIFT] || keystatus[SDL_SCANCODE_RSHIFT] )
7926 					{
7927 						if ( keystatus[SDL_SCANCODE_DOWN] )
7928 						{
7929 							keystatus[SDL_SCANCODE_DOWN] = 0;
7930 							// resize selection
7931 							if ( selectedarea_y2 < map.height - 1 && !moveSelectionNegativeY )
7932 							{
7933 								selectedarea_y2 += 1;
7934 								reselectEntityGroup();
7935 							}
7936 							else if ( selectedarea_y1 < selectedarea_y2
7937 								&& selectedarea_y1 < map.height - 1 && moveSelectionNegativeY )
7938 							{
7939 								selectedarea_y1 += 1;
7940 								reselectEntityGroup();
7941 							}
7942 							else if ( selectedarea_y1 == selectedarea_y2 )
7943 							{
7944 								moveSelectionNegativeY = false;
7945 								if ( selectedarea_y2 < map.height - 1 )
7946 								{
7947 									selectedarea_y2 += 1;
7948 									reselectEntityGroup();
7949 								}
7950 							}
7951 						}
7952 						else if ( keystatus[SDL_SCANCODE_UP] )
7953 						{
7954 							keystatus[SDL_SCANCODE_UP] = 0;
7955 							// resize selection
7956 							if ( selectedarea_y2 > selectedarea_y1 && !moveSelectionNegativeY )
7957 							{
7958 								selectedarea_y2 -= 1;
7959 								reselectEntityGroup();
7960 							}
7961 							else if ( selectedarea_y1 < selectedarea_y2
7962 								&& selectedarea_y1 > 0 && moveSelectionNegativeY )
7963 							{
7964 								selectedarea_y1 -= 1;
7965 								reselectEntityGroup();
7966 							}
7967 							else if ( selectedarea_y1 == selectedarea_y2 )
7968 							{
7969 								moveSelectionNegativeY = true;
7970 								if ( selectedarea_y1 > 0 )
7971 								{
7972 									selectedarea_y1 -= 1;
7973 									reselectEntityGroup();
7974 								}
7975 							}
7976 						}
7977 						else if ( keystatus[SDL_SCANCODE_LEFT] )
7978 						{
7979 							keystatus[SDL_SCANCODE_LEFT] = 0;
7980 							// resize selection
7981 							if ( selectedarea_x2 > selectedarea_x1 && !moveSelectionNegativeX )
7982 							{
7983 								selectedarea_x2 -= 1;
7984 								reselectEntityGroup();
7985 							}
7986 							else if ( selectedarea_x1 < selectedarea_x2
7987 								&& selectedarea_x1 > 0 && moveSelectionNegativeX )
7988 							{
7989 								selectedarea_x1 -= 1;
7990 								reselectEntityGroup();
7991 							}
7992 							else if ( selectedarea_x1 == selectedarea_x2 )
7993 							{
7994 								moveSelectionNegativeX = true;
7995 								if ( selectedarea_x1 > 0 )
7996 								{
7997 									selectedarea_x1 -= 1;
7998 									reselectEntityGroup();
7999 								}
8000 							}
8001 						}
8002 						else if ( keystatus[SDL_SCANCODE_RIGHT] )
8003 						{
8004 							keystatus[SDL_SCANCODE_RIGHT] = 0;
8005 							// resize selection
8006 							if ( selectedarea_x2 < map.width - 1 && !moveSelectionNegativeX)
8007 							{
8008 								selectedarea_x2 += 1;
8009 								reselectEntityGroup();
8010 							}
8011 							else if ( selectedarea_x1 < selectedarea_x2
8012 								&& selectedarea_x1 < map.width - 1 && moveSelectionNegativeX )
8013 							{
8014 								selectedarea_x1 += 1;
8015 								reselectEntityGroup();
8016 							}
8017 							else if ( selectedarea_x1 == selectedarea_x2 )
8018 							{
8019 								moveSelectionNegativeX = false;
8020 								if ( selectedarea_x2 < map.width - 1 )
8021 								{
8022 									selectedarea_x2 += 1;
8023 									reselectEntityGroup();
8024 								}
8025 							}
8026 						}
8027 					}
8028 					if ( keystatus[SDL_SCANCODE_S] )
8029 					{
8030 						keystatus[SDL_SCANCODE_S] = 0;
8031 						spritepalette = 1;
8032 					}
8033 					if ( keystatus[SDL_SCANCODE_T] )
8034 					{
8035 						keystatus[SDL_SCANCODE_T] = 0;
8036 						tilepalette = 1;
8037 					}
8038 					if ( keystatus[SDL_SCANCODE_F] )
8039 					{
8040 						keystatus[SDL_SCANCODE_F] = 0;
8041 						button3DMode(NULL);
8042 					}
8043 				}
8044 				if ( keystatus[SDL_SCANCODE_LALT] || keystatus[SDL_SCANCODE_RALT] )
8045 				{
8046 					if ( keystatus[SDL_SCANCODE_F] )
8047 					{
8048 						keystatus[SDL_SCANCODE_F] = 0;
8049 						menuVisible = 1;
8050 					}
8051 					if ( keystatus[SDL_SCANCODE_E] )
8052 					{
8053 						keystatus[SDL_SCANCODE_E] = 0;
8054 						menuVisible = 2;
8055 					}
8056 					if ( keystatus[SDL_SCANCODE_V] )
8057 					{
8058 						keystatus[SDL_SCANCODE_V] = 0;
8059 						menuVisible = 3;
8060 					}
8061 					if ( keystatus[SDL_SCANCODE_M] )
8062 					{
8063 						keystatus[SDL_SCANCODE_M] = 0;
8064 						menuVisible = 4;
8065 					}
8066 					if ( keystatus[SDL_SCANCODE_H] )
8067 					{
8068 						keystatus[SDL_SCANCODE_H] = 0;
8069 						menuVisible = 5;
8070 					}
8071 					if ( keystatus[SDL_SCANCODE_F4] )
8072 					{
8073 						keystatus[SDL_SCANCODE_F4] = 0;
8074 						buttonExit(NULL);
8075 					}
8076 					if ( keystatus[SDL_SCANCODE_DOWN] )
8077 					{
8078 						keystatus[SDL_SCANCODE_DOWN] = 0;
8079 						// move entities
8080 						makeUndo();
8081 						if ( selectedarea_y2 < map.height - 1 )
8082 						{
8083 							for ( std::vector<Entity*>::iterator it = groupedEntities.begin(); it != groupedEntities.end(); ++it )
8084 							{
8085 								Entity* tmpEntity = *it;
8086 								tmpEntity->y += 16;
8087 							}
8088 							selectedarea_y2 += 1;
8089 							if ( selectedarea_y1 < map.height - 1 )
8090 							{
8091 								selectedarea_y1 += 1;
8092 							}
8093 						}
8094 					}
8095 					else if ( keystatus[SDL_SCANCODE_UP] )
8096 					{
8097 						keystatus[SDL_SCANCODE_UP] = 0;
8098 						// move entities
8099 						makeUndo();
8100 						if ( selectedarea_y1 > 0 )
8101 						{
8102 							for ( std::vector<Entity*>::iterator it = groupedEntities.begin(); it != groupedEntities.end(); ++it )
8103 							{
8104 								Entity* tmpEntity = *it;
8105 								tmpEntity->y -= 16;
8106 							}
8107 							selectedarea_y1 -= 1;
8108 							if ( selectedarea_y2 > 0 )
8109 							{
8110 								selectedarea_y2 -= 1;
8111 							}
8112 						}
8113 					}
8114 					else if ( keystatus[SDL_SCANCODE_LEFT] )
8115 					{
8116 						keystatus[SDL_SCANCODE_LEFT] = 0;
8117 						// move entities
8118 						makeUndo();
8119 						if ( selectedarea_x1 > 0 )
8120 						{
8121 							for ( std::vector<Entity*>::iterator it = groupedEntities.begin(); it != groupedEntities.end(); ++it )
8122 							{
8123 								Entity* tmpEntity = *it;
8124 								tmpEntity->x -= 16;
8125 							}
8126 							selectedarea_x1 -= 1;
8127 							if ( selectedarea_x2 > 0 )
8128 							{
8129 								selectedarea_x2 -= 1;
8130 							}
8131 						}
8132 					}
8133 					else if ( keystatus[SDL_SCANCODE_RIGHT] )
8134 					{
8135 						keystatus[SDL_SCANCODE_RIGHT] = 0;
8136 						// move entities
8137 						makeUndo();
8138 						if ( selectedarea_x2 < map.width - 1 )
8139 						{
8140 							for ( std::vector<Entity*>::iterator it = groupedEntities.begin(); it != groupedEntities.end(); ++it )
8141 							{
8142 								Entity* tmpEntity = *it;
8143 								tmpEntity->x += 16;
8144 							}
8145 							selectedarea_x2 += 1;
8146 							if ( selectedarea_x1 < map.width - 1 )
8147 							{
8148 								selectedarea_x1 += 1;
8149 							}
8150 						}
8151 					}
8152 				}
8153 				if ( keystatus[SDL_SCANCODE_DELETE] )
8154 				{
8155 					keystatus[SDL_SCANCODE_DELETE] = 0;
8156 					buttonDelete(NULL);
8157 					groupedEntities.clear();
8158 				}
8159 				if ( keystatus[SDL_SCANCODE_C] )
8160 				{
8161 					keystatus[SDL_SCANCODE_C] = 0;
8162 					buttonCycleSprites(NULL);
8163 				}
8164 				if ( keystatus[SDL_SCANCODE_F1] )
8165 				{
8166 					keystatus[SDL_SCANCODE_F1] = 0;
8167 					buttonAbout(NULL);
8168 				}
8169 				if ( keystatus[SDL_SCANCODE_H] )
8170 				{
8171 					keystatus[SDL_SCANCODE_H] = 0;
8172 					buttonEditorControls(NULL);
8173 				}
8174 				if ( keystatus[SDL_SCANCODE_1] ) // Switch to Pencil Tool
8175 				{
8176 					keystatus[SDL_SCANCODE_1] = 0;
8177 					selectedTool = 0;
8178 					selectedarea = false;
8179 				}
8180 				if ( keystatus[SDL_SCANCODE_2] ) // Switch to Point Tool
8181 				{
8182 					keystatus[SDL_SCANCODE_2] = 0;
8183 					selectedTool = 1;
8184 					selectedarea = false;
8185 				}
8186 				if ( keystatus[SDL_SCANCODE_3] ) // Switch to Brush Tool
8187 				{
8188 					keystatus[SDL_SCANCODE_3] = 0;
8189 					selectedTool = 2;
8190 					selectedarea = false;
8191 				}
8192 				if ( keystatus[SDL_SCANCODE_4] ) // Switch to Select Tool
8193 				{
8194 					keystatus[SDL_SCANCODE_4] = 0;
8195 					selectedTool = 3;
8196 					selectedarea = false;
8197 				}
8198 				if ( keystatus[SDL_SCANCODE_5] ) // Switch to Fill Tool
8199 				{
8200 					keystatus[SDL_SCANCODE_5] = 0;
8201 					selectedTool = 4;
8202 					selectedarea = false;
8203 				}
8204 				if ( keystatus[SDL_SCANCODE_F2] )
8205 				{
8206 					keystatus[SDL_SCANCODE_F2] = 0;
8207 					makeUndo();
8208 					buttonSpriteProperties(NULL);
8209 				}
8210 				if ( keystatus[SDL_SCANCODE_KP_7] )
8211 				{
8212 					keystatus[SDL_SCANCODE_KP_7] = 0;
8213 					selectedTile = recentUsedTiles[recentUsedTilePalette][0];
8214 				}
8215 				if ( keystatus[SDL_SCANCODE_KP_8] )
8216 				{
8217 					keystatus[SDL_SCANCODE_KP_8] = 0;
8218 					selectedTile = recentUsedTiles[recentUsedTilePalette][1];
8219 				}
8220 				if ( keystatus[SDL_SCANCODE_KP_9] )
8221 				{
8222 					keystatus[SDL_SCANCODE_KP_9] = 0;
8223 					selectedTile = recentUsedTiles[recentUsedTilePalette][2];
8224 				}
8225 				if ( keystatus[SDL_SCANCODE_KP_4] )
8226 				{
8227 					keystatus[SDL_SCANCODE_KP_4] = 0;
8228 					selectedTile = recentUsedTiles[recentUsedTilePalette][3];
8229 				}
8230 				if ( keystatus[SDL_SCANCODE_KP_5] )
8231 				{
8232 					keystatus[SDL_SCANCODE_KP_5] = 0;
8233 					selectedTile = recentUsedTiles[recentUsedTilePalette][4];
8234 				}
8235 				if ( keystatus[SDL_SCANCODE_KP_6] )
8236 				{
8237 					keystatus[SDL_SCANCODE_KP_6] = 0;
8238 					selectedTile = recentUsedTiles[recentUsedTilePalette][5];
8239 				}
8240 				if ( keystatus[SDL_SCANCODE_KP_1] )
8241 				{
8242 					keystatus[SDL_SCANCODE_KP_1] = 0;
8243 					selectedTile = recentUsedTiles[recentUsedTilePalette][6];
8244 				}
8245 				if ( keystatus[SDL_SCANCODE_KP_2] )
8246 				{
8247 					keystatus[SDL_SCANCODE_KP_2] = 0;
8248 					selectedTile = recentUsedTiles[recentUsedTilePalette][7];
8249 				}
8250 				if ( keystatus[SDL_SCANCODE_KP_3] )
8251 				{
8252 					keystatus[SDL_SCANCODE_KP_3] = 0;
8253 					selectedTile = recentUsedTiles[recentUsedTilePalette][8];
8254 				}
8255 				if ( keystatus[SDL_SCANCODE_KP_PLUS] )
8256 				{
8257 					keystatus[SDL_SCANCODE_KP_PLUS] = 0;
8258 					recentUsedTilePalette++; //scroll through palettes 1-9
8259 					if ( recentUsedTilePalette == 9 )
8260 					{
8261 						recentUsedTilePalette = 0;
8262 					}
8263 				}
8264 				if ( keystatus[SDL_SCANCODE_KP_MINUS] )
8265 				{
8266 					keystatus[SDL_SCANCODE_KP_MINUS] = 0;
8267 					recentUsedTilePalette--; //scroll through palettes 1-9
8268 					if ( recentUsedTilePalette == -1 )
8269 					{
8270 						recentUsedTilePalette = 8;
8271 					}
8272 				}
8273 				if ( keystatus[SDL_SCANCODE_KP_MULTIPLY] )
8274 				{
8275 					keystatus[SDL_SCANCODE_KP_MULTIPLY] = 0;
8276 					lockTilePalette[recentUsedTilePalette] = !lockTilePalette[recentUsedTilePalette]; // toggle lock/unlock
8277 				}
8278 			}
8279 			// process and draw buttons
8280 			handleButtons();
8281 		}
8282 
8283 		if ( spritepalette )
8284 		{
8285 			x = 0;
8286 			y = 0;
8287 			z = 0;
8288 			drawRect( NULL, SDL_MapRGB(mainsurface->format, 0, 0, 0), 255 ); // wipe screen
8289 			for ( c = 0; c < xres * yres; c++ )
8290 			{
8291 				palette[c] = -1;
8292 			}
8293 			for ( c = 0; c < numsprites; c++ )
8294 			{
8295 				if ( sprites[c] != NULL )
8296 				{
8297 					pos.x = x;
8298 					pos.y = y;
8299 					pos.w = sprites[c]->w;
8300 					pos.h = sprites[c]->h;
8301 					int scale = 1;
8302 					if ( pos.w < 16 && pos.h < 16 )
8303 					{
8304 						scale = 4;
8305 						pos.w *= scale;
8306 						pos.h *= scale;
8307 					}
8308 					else if ( pos.w < 32 && pos.h < 32 )
8309 					{
8310 						scale = 2;
8311 						pos.w *= scale;
8312 						pos.h *= scale;
8313 					}
8314 
8315 					drawImageScaled(sprites[c], NULL, &pos);
8316 					for ( x2 = x; x2 < x + sprites[c]->w * scale; x2++ )
8317 					{
8318 						for ( y2 = y; y2 < y + sprites[c]->h * scale; y2++ )
8319 						{
8320 							if ( x2 < xres && y2 < yres )
8321 							{
8322 								palette[y2 + x2 * yres] = c;
8323 							}
8324 						}
8325 					}
8326 					x += sprites[c]->w * scale;
8327 					z = std::max(z, sprites[c]->h * scale);
8328 					if ( c < numsprites - 1 )
8329 					{
8330 						if ( sprites[c + 1] != NULL )
8331 						{
8332 							if ( x + sprites[c + 1]->w * scale > xres )
8333 							{
8334 								x = 0;
8335 								y += z;
8336 							}
8337 						}
8338 						else
8339 						{
8340 							if ( x + sprites[0]->w * scale > xres )
8341 							{
8342 								x = 0;
8343 								y += z;
8344 							}
8345 						}
8346 					}
8347 				}
8348 				else
8349 				{
8350 					pos.x = x;
8351 					pos.y = y;
8352 					pos.w = TEXTURESIZE;
8353 					pos.h = TEXTURESIZE;
8354 					drawImageScaled(sprites[0], NULL, &pos);
8355 					x += sprites[0]->w;
8356 					z = std::max(z, sprites[0]->h);
8357 					if ( c < numsprites - 1 )
8358 					{
8359 						if ( sprites[c + 1] != NULL )
8360 						{
8361 							if ( x + sprites[c + 1]->w > xres )
8362 							{
8363 								x = 0;
8364 								y += z;
8365 							}
8366 						}
8367 						else
8368 						{
8369 							if ( x + sprites[0]->w > xres )
8370 							{
8371 								x = 0;
8372 								y += z;
8373 							}
8374 						}
8375 					}
8376 				}
8377 			}
8378 			if (mousestatus[SDL_BUTTON_LEFT])
8379 			{
8380 				mclick = 1;
8381 			}
8382 			if (!mousestatus[SDL_BUTTON_LEFT] && mclick)
8383 			{
8384 				// create a new object
8385 				if (palette[mousey + mousex * yres] >= 0)
8386 				{
8387 					entity = newEntity(palette[mousey + mousex * yres], 0, map.entities, nullptr);
8388 					selectedEntity = entity;
8389 					lastSelectedEntity = selectedEntity;
8390 					setSpriteAttributes(selectedEntity, nullptr, nullptr);
8391 				}
8392 
8393 				mclick = 0;
8394 				spritepalette = 0;
8395 			}
8396 			if (keystatus[SDL_SCANCODE_ESCAPE])
8397 			{
8398 				mclick = 0;
8399 				spritepalette = 0;
8400 			}
8401 			/*switch( palette[mousey+mousex*yres] ) {
8402 				case 1:	strcpy(action,"PLAYER"); break;
8403 				case 53:	strcpy(action,"PURPLEGEM"); break;
8404 				case 37:	strcpy(action,"REDGEM"); break;
8405 				case 74:
8406 				case 75:	strcpy(action,"TROLL"); break;
8407 				default:	strcpy(action,"STATIC"); break;
8408 			}*/
8409 
8410 			int numsprites = static_cast<int>(sizeof(spriteEditorNameStrings) / sizeof(spriteEditorNameStrings[0]));
8411 
8412 			if ( (mousex <= xres && mousey <= yres) && palette[mousey + mousex * yres] >= 0 && palette[mousey + mousex * yres] <= numsprites )
8413 			{
8414 				printTextFormatted(font8x8_bmp, 0, yres - 8, "Sprite index:%5d", palette[mousey + mousex * yres]);
8415 				printTextFormatted(font8x8_bmp, 0, yres - 16, "%s", spriteEditorNameStrings[palette[mousey + mousex * yres]]);
8416 
8417 				char hoverTextString[1024] = "";
8418 				snprintf(hoverTextString, 5, "%d: ", palette[mousey + mousex * yres]);
8419 				strcat(hoverTextString, spriteEditorNameStrings[palette[mousey + mousex * yres]]);
8420 				int hoverTextWidth = strlen(hoverTextString);
8421 
8422 				if ( mousey - 20 <= 0 )
8423 				{
8424 					if ( mousex + 16 + 8 * hoverTextWidth >= xres )
8425 					{
8426 						// stop text being drawn above y = 0 and past window width (xres)
8427 						drawWindowFancy(mousex - 16 - (8 + 8 * hoverTextWidth), 0, mousex - 16, 16);
8428 						printTextFormatted(font8x8_bmp, mousex - 16 - (4 + 8 * hoverTextWidth), 4, "%s", hoverTextString);
8429 					}
8430 					else
8431 					{
8432 						// stop text being drawn above y = 0
8433 						drawWindowFancy(mousex + 16, 0, 16 + 8 + mousex + 8 * hoverTextWidth, 16);
8434 						printTextFormatted(font8x8_bmp, mousex + 16 + 4, 4, "%s", hoverTextString);
8435 					}
8436 				}
8437 				else
8438 				{
8439 					if ( mousex + 16 + 8 * hoverTextWidth >= xres )
8440 					{
8441 						// stop text being drawn past window width (xres)
8442 						drawWindowFancy(xres - (8 + 8 * hoverTextWidth), mousey - 20, xres, mousey - 4);
8443 						printTextFormatted(font8x8_bmp, xres - (4 + 8 * hoverTextWidth), mousey - 16, "%s", hoverTextString);
8444 					}
8445 					else
8446 					{
8447 						drawWindowFancy(mousex + 16, mousey - 20, 16 + 8 + mousex + 8 * hoverTextWidth, mousey - 4);
8448 						printTextFormatted(font8x8_bmp, mousex + 16 + 4, mousey - 16, "%s", hoverTextString);
8449 					}
8450 				}
8451 			}
8452 			else
8453 			{
8454 				printText(font8x8_bmp, 0, yres - 8, "Click to cancel");
8455 			}
8456 		}
8457 		if ( tilepalette )
8458 		{
8459 			x = 0;
8460 			y = 0;
8461 			drawRect( NULL, SDL_MapRGB(mainsurface->format, 0, 0, 0), 255 ); // wipe screen
8462 			for ( c = 0; c < xres * yres; c++ )
8463 			{
8464 				palette[c] = -1;
8465 			}
8466 			for ( c = 0; c < numtiles; c++ )
8467 			{
8468 				pos.x = x;
8469 				pos.y = y;
8470 				pos.w = TEXTURESIZE;
8471 				pos.h = TEXTURESIZE;
8472 				if ( tiles[c] != NULL )
8473 				{
8474 					drawImageScaled(tiles[c], NULL, &pos);
8475 					for ( x2 = x; x2 < x + TEXTURESIZE; x2++ )
8476 						for ( y2 = y; y2 < y + TEXTURESIZE; y2++ )
8477 						{
8478 							if ( x2 < xres && y2 < yres )
8479 							{
8480 								palette[y2 + x2 * yres] = c;
8481 							}
8482 						}
8483 					x += TEXTURESIZE;
8484 					if ( c < numtiles - 1 )
8485 					{
8486 						if ( x + TEXTURESIZE > xres )
8487 						{
8488 							x = 0;
8489 							y += TEXTURESIZE;
8490 						}
8491 					}
8492 				}
8493 				else
8494 				{
8495 					drawImageScaled(sprites[0], NULL, &pos);
8496 					x += TEXTURESIZE;
8497 					if ( c < numtiles - 1 )
8498 					{
8499 						if ( x + TEXTURESIZE > xres )
8500 						{
8501 							x = 0;
8502 							y += TEXTURESIZE;
8503 						}
8504 					}
8505 				}
8506 			}
8507 			if (mousestatus[SDL_BUTTON_LEFT])
8508 			{
8509 				mclick = 1;
8510 			}
8511 			if (!mousestatus[SDL_BUTTON_LEFT] && mclick)
8512 			{
8513 				// select the tile under the mouse
8514 				if ( (mousex <= xres && mousey <= yres) && palette[mousey + mousex * yres] >= 0)
8515 				{
8516 					selectedTile = palette[mousey + mousex * yres];
8517 					updateRecentTileList(selectedTile);
8518 				}
8519 				mclick = 0;
8520 				tilepalette = 0;
8521 			}
8522 			if (keystatus[SDL_SCANCODE_ESCAPE])
8523 			{
8524 				mclick = 0;
8525 				tilepalette = 0;
8526 			}
8527 
8528 			int numtiles = static_cast<int>(sizeof(tileEditorNameStrings) / sizeof(tileEditorNameStrings[0]));
8529 
8530 			if ( (mousex <= xres && mousey <= yres) && palette[mousey + mousex * yres] >= 0 && palette[mousey + mousex * yres] <= numtiles)
8531 			{
8532 				printTextFormatted(font8x8_bmp, 0, yres - 8, "Tile index:%5d", palette[mousey + mousex * yres]);
8533 				printTextFormatted(font8x8_bmp, 0, yres - 16, "%s", tileEditorNameStrings[palette[mousey + mousex * yres]]);
8534 
8535 				char hoverTextString[1024] = "";
8536 				snprintf(hoverTextString, 5, "%d: ", palette[mousey + mousex * yres]);
8537 				strcat(hoverTextString, tileEditorNameStrings[palette[mousey + mousex * yres]]);
8538 				int hoverTextWidth = strlen(hoverTextString);
8539 
8540 				if ( mousey - 20 <= 0 )
8541 				{
8542 					if ( mousex + 16 + 8 * hoverTextWidth >= xres )
8543 					{
8544 						// stop text being drawn above y = 0 and past window width (xres)
8545 						drawWindowFancy(mousex - 16 - (8 + 8 * hoverTextWidth), 0, mousex - 16, 16);
8546 						printTextFormatted(font8x8_bmp, mousex - 16 - (4 + 8 * hoverTextWidth), 4, "%s", hoverTextString);
8547 					}
8548 					else
8549 					{
8550 						// stop text being drawn above y = 0
8551 						drawWindowFancy(mousex + 16, 0, 16 + 8 + mousex + 8 * hoverTextWidth, 16);
8552 						printTextFormatted(font8x8_bmp, mousex + 16 + 4, 4, "%s", hoverTextString);
8553 					}
8554 				}
8555 				else
8556 				{
8557 					if ( mousex + 16 + 8 * hoverTextWidth >= xres )
8558 					{
8559 						// stop text being drawn past window width (xres)
8560 						drawWindowFancy(xres - (8 + 8 * hoverTextWidth), mousey - 20, xres, mousey - 4);
8561 						printTextFormatted(font8x8_bmp, xres - (4 + 8 * hoverTextWidth), mousey - 16, "%s", hoverTextString);
8562 					}
8563 					else
8564 					{
8565 						drawWindowFancy(mousex + 16, mousey - 20, 16 + 8 + mousex + 8 * hoverTextWidth, mousey - 4);
8566 						printTextFormatted(font8x8_bmp, mousex + 16 + 4, mousey - 16, "%s", hoverTextString);
8567 					}
8568 				}
8569 			}
8570 			else
8571 			{
8572 				printText(font8x8_bmp, 0, yres - 8, "Click to cancel");
8573 			}
8574 		}
8575 
8576 		// flip screen
8577 		GO_SwapBuffers(screen);
8578 		cycles++;
8579 	}
8580 
8581 	// deinit
8582 	SDL_SetCursor(cursorArrow);
8583 	SDL_FreeCursor(cursorPencil);
8584 	SDL_FreeCursor(cursorPoint);
8585 	SDL_FreeCursor(cursorBrush);
8586 	SDL_FreeCursor(cursorFill);
8587 	if ( palette != NULL )
8588 	{
8589 		free(palette);
8590 	}
8591 	if ( copymap.tiles != NULL )
8592 	{
8593 		free(copymap.tiles);
8594 	}
8595 	list_FreeAll(&undolist);
8596 	saveTilePalettes();
8597 	return deinitApp();
8598 }
8599 
propertyPageTextAndInput(int numProperties,int width)8600 void propertyPageTextAndInput(int numProperties, int width)
8601 {
8602 	int pad_x1 = subx1 + 8;
8603 	int spacing = 36;
8604 	int pad_x2 = width;
8605 
8606 	// Cycle properties with TAB.
8607 	if ( keystatus[SDL_SCANCODE_TAB] )
8608 	{
8609 		keystatus[SDL_SCANCODE_TAB] = 0;
8610 		cursorflash = ticks;
8611 		editproperty++;
8612 		if ( editproperty == numProperties )
8613 		{
8614 			editproperty = 0;
8615 		}
8616 
8617 		inputstr = spriteProperties[editproperty];
8618 	}
8619 
8620 	// select a textbox
8621 	if ( mousestatus[SDL_BUTTON_LEFT] )
8622 	{
8623 		for ( int i = 0; i < numProperties; i++ )
8624 		{
8625 			if ( omousex >= pad_x1 - 4 && omousey >= suby1 + 40 + i * spacing && omousex < pad_x1 - 4 + pad_x2 && omousey < suby1 + 56 + i * spacing )
8626 			{
8627 				inputstr = spriteProperties[i];
8628 				editproperty = i;
8629 				cursorflash = ticks;
8630 			}
8631 		}
8632 	}
8633 }
8634 
propertyPageError(int rowIndex,int resetValue)8635 void propertyPageError(int rowIndex, int resetValue)
8636 {
8637 	errorMessage = 60;
8638 	errorArr[rowIndex] = 1;
8639 	snprintf(spriteProperties[rowIndex], sizeof(spriteProperties[rowIndex]), "%d", resetValue); //reset
8640 }
8641 
propertyPageCursorFlash(int rowSpacing)8642 void propertyPageCursorFlash(int rowSpacing)
8643 {
8644 	if ( (ticks - cursorflash) % TICKS_PER_SECOND < TICKS_PER_SECOND / 2 )
8645 	{
8646 		printText(font8x8_bmp, subx1 + 8 + strlen(spriteProperties[editproperty]) * 8, suby1 + 44 + editproperty * rowSpacing, "\26");
8647 	}
8648 }
8649 
reselectEntityGroup()8650 void reselectEntityGroup()
8651 {
8652 	groupedEntities.clear();
8653 	node_t* nextnode = nullptr;
8654 	Entity* entity = nullptr;
8655 	for ( node_t* node = map.entities->first; node != nullptr; node = nextnode )
8656 	{
8657 		nextnode = node->next;
8658 		entity = (Entity*)node->element;
8659 		if ( entity->x / 16 >= selectedarea_x1 && entity->x / 16 <= selectedarea_x2
8660 			&& entity->y / 16 >= selectedarea_y1 && entity->y / 16 <= selectedarea_y2 )
8661 		{
8662 			groupedEntities.push_back(entity);
8663 		}
8664 	}
8665 }
8666 
generateDungeon(char * levelset,Uint32 seed,std::tuple<int,int,int,int> mapParameters)8667 int generateDungeon(char* levelset, Uint32 seed, std::tuple<int, int, int, int> mapParameters)
8668 {
8669 	return 0; // dummy function
8670 }