1 /////////////////////////////////////////
2 //
3 //             OpenLieroX
4 //
5 // code under LGPL, based on JasonBs work,
6 // enhanced by Dark Charlie and Albert Zeyer
7 //
8 //
9 /////////////////////////////////////////
10 
11 
12 // Map editor
13 // Created 28/7/02
14 // Jason Boettcher
15 
16 
17 #include "LieroX.h"
18 #include "AuxLib.h"
19 #include "DeprecatedGUI/Graphics.h"
20 #include "DeprecatedGUI/Menu.h"
21 #include "GfxPrimitives.h"
22 #include "FindFile.h"
23 #include "StringUtils.h"
24 #include "DeprecatedGUI/CButton.h"
25 #include "DeprecatedGUI/CTextbox.h"
26 #include "Sounds.h"
27 #include "EndianSwap.h"
28 #include "FileUtils.h"
29 
30 
31 namespace DeprecatedGUI {
32 
33 static CGuiLayout	cMaped;
34 
35 // Map editor controls
36 enum {
37 	map_new,
38 	map_random,
39 	map_load,
40 	map_save,
41 	map_quit
42 };
43 
44 static CMap*		cMap = NULL;
45 static CViewport*	cMapedView = NULL;
46 static int			grabbed = false;
47 static int			grabX,  grabY;
48 static int			grabWX, grabWY;
49 
50 ///////////////////
51 // Initialize the map editor
Menu_MapEdInitialize()52 bool Menu_MapEdInitialize()
53 {
54 	tMenu->iMenuType = MNU_MAPED;
55 
56 	// Create the buffer
57 	/*DrawImage(tMenu->bmpBuffer,tMenu->bmpMainBack,0,0);
58 	Menu_DrawSubTitle(tMenu->bmpBuffer,SUB_MAPED);
59 
60 	Menu_DrawBox(tMenu->bmpBuffer,20,171, 619,458);
61 	Menu_DrawBox(tMenu->bmpBuffer,20,135, 54,169);*/
62 
63     DrawImage(tMenu->bmpBuffer.get(),tMenu->bmpMainBack_common,0,0);
64     Menu_DrawSubTitleAdv(tMenu->bmpBuffer.get(),SUB_MAPED,18);
65 	if (tMenu->tFrontendInfo.bPageBoxes)
66 		Menu_DrawBox(tMenu->bmpBuffer.get(), 15,100, 625, 465);
67 
68     Menu_DrawBox(tMenu->bmpBuffer.get(),20,105, 54,139);      // Preview box
69     Menu_DrawBox(tMenu->bmpBuffer.get(),20,146, 619,459);     // Level box
70 
71 
72 
73 	Menu_RedrawMouse(true);
74 
75 	// Create a map
76 	if(cMap) delete cMap;
77 	cMap = new CMap();
78 	cMap->New(504,350,"dirt");
79 	if(cMapedView) delete cMapedView;
80 	cMapedView = new CViewport();
81 	cMapedView->Setup(22,148, 596,310,0);
82 	cMapedView->SetWorldX(0);
83 	cMapedView->SetWorldY(0);
84 
85 	tMenu->iEditMode = 0;
86 	tMenu->iCurHole = 0;
87 	tMenu->iCurStone = 0;
88 	tMenu->iCurMisc = 0;
89 	tMenu->iCurDirt = 0;
90 
91 	cMaped.Shutdown();
92 	cMaped.Initialize();
93 
94 	grabbed = false;
95 
96 	// Add the controls
97 	cMaped.Add( new CButton(BUT_NEW, tMenu->bmpButtons),	map_new,	 230,110, 50,15);
98 	cMaped.Add( new CButton(BUT_RANDOM, tMenu->bmpButtons), map_random,  300,110, 80,15);
99 	cMaped.Add( new CButton(BUT_LOAD, tMenu->bmpButtons),   map_load,	 400,110, 50,15);
100 	cMaped.Add( new CButton(BUT_SAVE, tMenu->bmpButtons),   map_save,	 480,110, 50,15);
101 	cMaped.Add( new CButton(BUT_QUIT, tMenu->bmpButtons),   map_quit,	 550,110, 50,15);
102 
103 
104 	return true;
105 }
106 
107 /////////////
108 // Shutdown
Menu_MapEdShutdown()109 void Menu_MapEdShutdown()
110 {
111 	cMaped.Shutdown();
112 	if(cMap) {
113 		cMap->Shutdown();
114 		delete cMap;
115 		cMap = NULL;
116 	}
117 	if(cMapedView) {
118 		delete cMapedView;
119 		cMapedView = NULL;
120 	}
121 }
122 
123 
124 ///////////////////
125 // Map editor frame
Menu_MapEdFrame(SDL_Surface * bmpDest,int process)126 void Menu_MapEdFrame(SDL_Surface * bmpDest, int process)
127 {
128 	gui_event_t *ev = NULL;
129 	mouse_t *Mouse = GetMouse();
130 	int x,y,n,i;
131 
132 	// Re-draw the buffer over buttons
133 	//DrawImageAdv(bmpDest, tMenu->bmpBuffer, 230,140, 230,140, 410,50);
134 
135 	ev = cMaped.Process();
136 	cMaped.Draw(bmpDest);
137 
138 
139 	// Draw the map
140 	cMap->Draw(bmpDest, cMapedView);
141 
142 
143 	// Toolbar
144 	int down = -1;
145 	if(Mouse->Down || Mouse->Up) {
146 		if(Mouse->Y > 108 && Mouse->Y < 137) {
147 
148 			for(x=58,n=0;x<155;x+=32,n++) {
149 				if(Mouse->X > x && Mouse->X < x+29)
150 					down = n;
151 			}
152 		}
153 		if(Mouse->Up && down >= 0) {
154 			PlaySoundSample(sfxGeneral.smpClick);
155 
156 			tMenu->iEditMode = down;
157 		}
158 	}
159 
160 	for(x=0,n=58,i=0;x<116;x+=29,n+=32,i++) {
161 		y = tMenu->iEditMode == i || down == i ? 29 : 0;
162 		DrawImageAdv(bmpDest, tMenu->bmpMapEdTool, x,y, n, 108, 29,29);
163 	}
164 
165 	// Item clicked on?
166 	int Clicked = false;
167 	if(Mouse->Up) {
168 		if(Mouse->X > 20 && Mouse->X < 54)
169 			if(Mouse->Y > 105 && Mouse->Y < 139)
170 				Clicked = Mouse->Up;
171 	}
172 
173 
174 	DrawImageAdv(bmpDest, tMenu->bmpBuffer, 20,105, 20,105, 34,34);
175 
176 	//
177 	// Draw item
178 	//
179 	theme_t *t = cMap->GetTheme();
180 
181 	// Holes
182 	if(tMenu->iEditMode == 0) {
183 
184 		// left mouse button
185 		if(Clicked & SDL_BUTTON(1)) {
186 			tMenu->iCurHole++;
187 			if(tMenu->iCurHole >= 5)
188 				tMenu->iCurHole = 0;
189 		}
190 
191 		// Right mouse button
192 		if(Clicked & SDL_BUTTON(3)) {
193 			tMenu->iCurHole--;
194 			if(tMenu->iCurHole < 0)
195 				tMenu->iCurHole = 4;
196 		}
197 
198 
199 		int w = t->bmpHoles[ tMenu->iCurHole ].get()->w;
200 		int h = t->bmpHoles[ tMenu->iCurHole ].get()->h;
201 
202 		DrawImageStretch(bmpDest, t->bmpHoles[ tMenu->iCurHole ], 37-w, 122-h);
203 	}
204 
205 	// Stones
206 	if(tMenu->iEditMode == 1) {
207 
208 		// lmb
209 		if(Clicked & SDL_BUTTON(1)) {
210 			tMenu->iCurStone++;
211 			if(tMenu->iCurStone >= t->NumStones)
212 				tMenu->iCurStone = 0;
213 		}
214 
215 		// rmb
216 		if(Clicked & SDL_BUTTON(3)) {
217 			tMenu->iCurStone--;
218 			if(tMenu->iCurStone < 0)
219 				tMenu->iCurStone = t->NumStones-1;
220 		}
221 
222 
223 		int w = t->bmpStones[ tMenu->iCurStone ].get()->w;
224 		int h = t->bmpStones[ tMenu->iCurStone ].get()->h;
225 
226 		if(w > 17 || h > 17) {
227 			w >>= 1;
228 			h >>= 1;
229 			DrawImage(bmpDest,t->bmpStones[ tMenu->iCurStone ], 37-w, 122-h);
230 			DrawRect(bmpDest,22,107, 52,137, tLX->clWhite);
231 		} else
232 			DrawImageStretchKey(bmpDest, t->bmpStones[ tMenu->iCurStone ], 37-w, 122-h);
233 	}
234 
235 
236 	// Miscellanous
237 	if(tMenu->iEditMode == 2) {
238 
239 		// lmb
240 		if(Clicked & SDL_BUTTON(1)) {
241 			tMenu->iCurMisc++;
242 			if(tMenu->iCurMisc >= t->NumMisc)
243 				tMenu->iCurMisc = 0;
244 		}
245 
246 		// rmb
247 		if(Clicked & SDL_BUTTON(3)) {
248 			tMenu->iCurMisc--;
249 			if(tMenu->iCurMisc < 0)
250 				tMenu->iCurMisc = t->NumMisc-1;
251 		}
252 
253 
254 		int w = t->bmpMisc[ tMenu->iCurMisc ].get()->w;
255 		int h = t->bmpMisc[ tMenu->iCurMisc ].get()->h;
256 
257 		DrawImageStretchKey(bmpDest, t->bmpMisc[ tMenu->iCurMisc ], 37-w, 122-h);
258 	}
259 
260 	// Dirt
261 	if(tMenu->iEditMode == 3) {
262 
263 		// lmb
264 		if(Clicked & SDL_BUTTON(1)) {
265 			tMenu->iCurDirt++;
266 			if(tMenu->iCurDirt >= 5)
267 				tMenu->iCurDirt = 0;
268 		}
269 
270 		// rmb
271 		if(Clicked & SDL_BUTTON(3)) {
272 			tMenu->iCurDirt--;
273 			if(tMenu->iCurDirt < 0)
274 				tMenu->iCurDirt = 4;
275 		}
276 
277 		int w = t->bmpHoles[ tMenu->iCurDirt ].get()->w;
278 		int h = t->bmpHoles[ tMenu->iCurDirt ].get()->h;
279 
280 		DrawImageStretch(bmpDest, t->bmpHoles[ tMenu->iCurDirt ], 37-w, 122-h);
281 	}
282 
283 	if(!process)
284 		return;
285 
286 
287 	//
288 	// Place the objects on the map
289 	//
290 	SmartPointer<SDL_Surface> MouseImg = NULL;
291 	if(Mouse->X >= 22 && Mouse->X <= 618) {
292 		if(Mouse->Y >= 148 && Mouse->Y <= 457) {
293 
294 			x = (Mouse->X - 22)/2 + cMapedView->GetWorldX();
295 			y = (Mouse->Y - 148)/2 + cMapedView->GetWorldY();
296 			CVec pos = CVec((float)x, (float)y);
297 
298 
299 			switch(tMenu->iEditMode) {
300 
301 				// Hole
302 				case 0:
303 					MouseImg = t->bmpHoles[tMenu->iCurHole];
304 					if(Mouse->Down & SDL_BUTTON(1))
305 						cMap->CarveHole(tMenu->iCurHole,pos,false);
306 					break;
307 
308 				// Stone
309 				case 1:
310 					MouseImg = t->bmpStones[tMenu->iCurStone];
311 					if(Mouse->Up & SDL_BUTTON(1))
312 						cMap->PlaceStone(tMenu->iCurStone,pos);
313 					break;
314 
315 				// Misc
316 				case 2:
317 					MouseImg = t->bmpMisc[tMenu->iCurMisc];
318 					if(Mouse->Up & SDL_BUTTON(1))
319 						cMap->PlaceMisc(tMenu->iCurMisc,pos);
320 					break;
321 
322 				// Dirt
323 				case 3:
324 					MouseImg = t->bmpHoles[tMenu->iCurDirt];
325 					if(Mouse->Down & SDL_BUTTON(1))
326 						cMap->PlaceDirt(tMenu->iCurDirt,pos);
327 					break;
328 
329 				// Delete object
330 				/*case 4:
331 					if(Mouse->Up & SDL_BUTTON(1))
332 						cMap->DeleteObject(pos);
333 					break;*/
334 			}
335 		}
336 	}
337 
338 
339 
340 	//
341 	// Process the gui
342 	//
343 
344 	if(ev) {
345 
346 		if(ev->cWidget->getType() == wid_Button) {
347 			if(ev->iEventMsg == BTN_CLICKED)
348 				PlaySoundSample(sfxGeneral.smpClick);
349 		}
350 
351 		switch(ev->iControlID) {
352 
353 			// New
354 			case map_new:
355 				if(ev->iEventMsg == BTN_CLICKED) {
356 					Menu_MapEd_New();
357 				}
358 				break;
359 
360 			// Random
361 			case map_random:
362 				if(ev->iEventMsg == BTN_CLICKED)
363 					//cMap->ApplyRandom();
364 				break;
365 
366 			// Load
367 			case map_load:
368 				if(ev->iEventMsg == BTN_CLICKED) {
369 					Menu_MapEd_LoadSave(false);
370 				}
371 				break;
372 
373 			// Save
374 			case map_save:
375 				if(ev->iEventMsg == BTN_CLICKED) {
376 					Menu_MapEd_LoadSave(true);
377 				}
378 				break;
379 
380 			// Quit
381 			case map_quit:
382 				if(ev->iEventMsg == BTN_CLICKED) {
383 
384 					// Shutdown the classes
385 					Menu_MapEdShutdown();
386 
387 					Menu_MainInitialize();
388 					return;
389 				}
390 				break;
391 		}
392 	}
393 
394 
395 	// Keyboard arrows
396 	keyboard_t *kb = GetKeyboard();
397 	int Scroll = 250 * (int)tLX->fDeltaTime.seconds();
398 	// TODO: make this event-based (don't check GetKeyboard() directly)
399 	if(kb->keys[SDLK_UP])
400 		cMapedView->SetWorldY( cMapedView->GetWorldY() - Scroll );
401 	if(kb->keys[SDLK_DOWN])
402 		cMapedView->SetWorldY( cMapedView->GetWorldY() + Scroll );
403 	if(kb->keys[SDLK_LEFT])
404 		cMapedView->SetWorldX( cMapedView->GetWorldX() - Scroll );
405 	if(kb->keys[SDLK_RIGHT])
406 		cMapedView->SetWorldX( cMapedView->GetWorldX() + Scroll );
407 
408     // Grab the level & drag it
409 	if(Mouse->Down & SDL_BUTTON(2)) {
410 		if(Mouse->X >= 22 && Mouse->X <= 618) {
411 			if(Mouse->Y >= 173 && Mouse->Y <= 457) {
412 				// Mouse button grabs and moves the map
413 				x = (Mouse->X - 22)/2;
414 				y = (Mouse->Y - 173)/2;
415 
416 				// First grab
417 				if(!grabbed) {
418 					grabbed = true;
419 					grabX = x;
420 					grabY = y;
421 					grabWX = cMapedView->GetWorldX();
422 					grabWY = cMapedView->GetWorldY();
423 				} else {
424 
425 					cMapedView->SetWorldX( grabWX + (grabX-x));
426 					cMapedView->SetWorldY( grabWY + (grabY-y));
427 				}
428 			}
429 		}
430 	} else
431 		grabbed = false;
432 
433     // When the mouse is on the edges of the screen, move the level
434     int EdgeSize = 7;
435     if( !Mouse->Down && !Mouse->Up ) {
436 
437         // X Axis
438         if( Mouse->X < EdgeSize )
439             cMapedView->SetWorldX( cMapedView->GetWorldX() - Scroll );
440         if( Mouse->X > 640-EdgeSize )
441             cMapedView->SetWorldX( cMapedView->GetWorldX() + Scroll );
442 
443         // Y Axis
444         if( Mouse->Y < EdgeSize )
445             cMapedView->SetWorldY( cMapedView->GetWorldY() - Scroll );
446         if( Mouse->Y > 480-EdgeSize )
447             cMapedView->SetWorldY( cMapedView->GetWorldY() + Scroll );
448     }
449 
450 	// Clamp the viewport
451 	cMapedView->Clamp(cMap->GetWidth(), cMap->GetHeight());
452 
453 
454 
455 
456 	// Draw the mouse
457 	if(MouseImg.get()) {
458 		int w = MouseImg.get()->w;
459 		int h = MouseImg.get()->h;
460 		//if(tMenu->iEditMode == 0 || tMenu->iEditMode == 3)
461 		DrawImageStretchKey(VideoPostProcessor::videoSurface(),MouseImg, Mouse->X-w, Mouse->Y-h);
462 		//else
463 		//	DrawImageStretchKey(VideoPostProcessor::videoSurface(),MouseImg, Mouse->X-w, Mouse->Y-h, tLX->clPink);
464 	}
465 	else
466 		DrawCursor(VideoPostProcessor::videoSurface());
467 }
468 
469 
470 ///////////////////
471 // Show a 'new' dialog box
472 enum {
473 	mn_Cancel=0,
474 	mn_Ok,
475 	mn_Width,
476 	mn_Height,
477 	mn_Scheme
478 };
479 
480 
481 
482 	class ComboboxFiller { public:
483 		CGuiLayout* gui;
484 		int comboindex;
485 		int i;
486 		int* dirtindex;
ComboboxFiller(CGuiLayout * g,int c,int * d)487 		ComboboxFiller(CGuiLayout* g, int c, int* d) : gui(g), comboindex(c), i(0), dirtindex(d) {}
operator ()(const std::string & dir)488 		inline bool operator() (const std::string& dir) {
489 			if (!IsFileAvailable(dir+"/theme.txt"))
490 				return true;
491 			size_t p = findLastPathSep(dir);
492 			std::string f = dir.substr(p+1);
493 			if (((CCombobox *)gui->getWidget(comboindex))->getItem(f) != NULL)
494 				return true;
495 
496 			gui->SendMessage(comboindex,CBS_ADDITEM,f,i);
497 			if(stringcasecmp(f,"dirt"))
498 				*dirtindex = i;
499 			i++;
500 
501 			return true;
502 		}
503 	};
504 
Menu_MapEd_New()505 void Menu_MapEd_New()
506 {
507 	gui_event_t *ev = NULL;
508 	int quitloop = false;
509 	CTextbox *t1,*t2;
510 
511 	// Save the background
512 	Menu_MapEdFrame(tMenu->bmpBuffer.get(),false);
513 
514 	Menu_DrawBox(tMenu->bmpBuffer.get(), 210, 170, 430, 310);
515 	DrawImageAdv(tMenu->bmpBuffer.get(), tMenu->bmpMainBack_common, 212,172, 212,172, 217,137);
516 	if (tMenu->tFrontendInfo.bPageBoxes)
517 		Menu_DrawBox(tMenu->bmpBuffer.get(), 15,100, 625, 465);
518 	//DrawRectFill(tMenu->bmpBuffer, 212, 172, 429, 309, tLX->clBlack);
519 
520 	Menu_RedrawMouse(true);
521 
522 	CGuiLayout cg;
523 
524 	cg.Initialize();
525 
526 	cg.Add( new CButton(BUT_CANCEL, tMenu->bmpButtons), mn_Cancel, 220,285, 75,15);
527 	cg.Add( new CButton(BUT_OK, tMenu->bmpButtons),     mn_Ok, 390,285, 40,15);
528 	cg.Add( new CTextbox(),                             mn_Width, 280,200, 100,tLX->cFont.GetHeight());
529 	cg.Add( new CTextbox(),                             mn_Height, 280,230, 100,tLX->cFont.GetHeight());
530 	cg.Add( new CCombobox(),							mn_Scheme, 280,260, 120,17);
531 
532 	cg.SendMessage(mn_Width,TXM_SETMAX,64,0);
533 	cg.SendMessage(mn_Height,TXM_SETMAX,64,0);
534 
535 	int dirtindex = -1;
536 
537 	// Find directories in the theme dir
538 	ComboboxFiller filler(&cg, 4, &dirtindex);
539 	FindFiles(filler, "data/themes", false, FM_DIR);
540 
541 	if(dirtindex != -1)
542 		cg.SendMessage(4,CBM_SETCURSEL,dirtindex,0);
543 
544 
545 
546 	// Set initial values
547 	t1 = (CTextbox *)cg.getWidget(mn_Width);
548 	t2 = (CTextbox *)cg.getWidget(mn_Height);
549 
550 	t1->setText(itoa(cMap->GetWidth(),10));
551 	t2->setText(itoa(cMap->GetHeight(),10));
552 
553 	DrawImage(VideoPostProcessor::videoSurface(),tMenu->bmpBuffer, 0,0);
554 	doVideoFrameInMainThread();
555 	DrawImage(VideoPostProcessor::videoSurface(),tMenu->bmpBuffer, 0,0);
556 
557 	ProcessEvents();
558 	while(!WasKeyboardEventHappening(SDLK_ESCAPE,false) && !quitloop) {
559 		Menu_RedrawMouse(false);
560 
561 		DrawImageAdv(VideoPostProcessor::videoSurface(),tMenu->bmpBuffer, 210,170, 210,170, 222, 262);
562 
563 		tLX->cFont.DrawCentre(VideoPostProcessor::videoSurface(), 320, 175, tLX->clNormalLabel, "Level details");
564 		tLX->cFont.Draw(VideoPostProcessor::videoSurface(), 220, 202, tLX->clNormalLabel, "Width");
565 		tLX->cFont.Draw(VideoPostProcessor::videoSurface(), 220, 232, tLX->clNormalLabel, "Height");
566 		tLX->cFont.Draw(VideoPostProcessor::videoSurface(), 220, 262, tLX->clNormalLabel, "Theme");
567 
568 		ev = cg.Process();
569 		cg.Draw(VideoPostProcessor::videoSurface());
570 
571 		// Process the widgets
572 		if(ev) {
573 
574 			switch(ev->iControlID) {
575 
576 				// Cancel
577 				case mn_Cancel:
578 					if(ev->iEventMsg == BTN_CLICKED) {
579 						PlaySoundSample(sfxGeneral.smpClick);
580 						quitloop = true;
581 					}
582 					break;
583 
584 				// OK
585 				case mn_Ok:
586 					if(ev->iEventMsg == BTN_CLICKED) {
587 						PlaySoundSample(sfxGeneral.smpClick);
588 						int w = from_string<int>(t1->getText());
589 						int h = from_string<int>(t2->getText());
590 						std::string theme;
591 						theme = "dirt";
592 						cb_item_t *it = (cb_item_t *)cg.SendMessage(4,CBM_GETCURITEM,(DWORD)0,0); // TODO: 64bit unsafe (pointer cast)
593 						if(it)
594 							theme = it->sName;
595 
596 
597 						// Check for min & max sizes
598 						if(w >= 350 && h >= 250 &&
599 							w <= 4000 && h <= 4000) {
600 								quitloop = true;
601 								cMap->New(w,h,theme);
602 						}
603 					}
604 					break;
605 			}
606 
607 		}
608 
609 		// Game close
610 		if (tLX->bQuitGame || !tMenu->bMenuRunning)
611 			break;
612 
613 
614 		DrawCursor(VideoPostProcessor::videoSurface());
615 		doVideoFrameInMainThread();
616 		CapFPS();
617 		WaitForNextEvent();
618 	}
619 
620 	// Redraw back to normal
621 	DrawImage(tMenu->bmpBuffer.get(),tMenu->bmpMainBack_common,0,0);
622     Menu_DrawSubTitleAdv(tMenu->bmpBuffer.get(),SUB_MAPED,18);
623 	if (tMenu->tFrontendInfo.bPageBoxes)
624 		Menu_DrawBox(tMenu->bmpBuffer.get(), 15,100, 625, 465);
625 
626     Menu_DrawBox(tMenu->bmpBuffer.get(),20,105, 54,139);      // Preview box
627     Menu_DrawBox(tMenu->bmpBuffer.get(),20,146, 619,459);     // Level box
628 
629 	Menu_RedrawMouse(true);
630 
631 	cg.Shutdown();
632 }
633 
634 
635 ///////////////////
636 // File save/load dialog
637 enum  {
638 	sl_Cancel=0,
639 	sl_Ok,
640 	sl_FileList,
641 	sl_FileName
642 };
643 
644 
645 
646 	struct LevelListFiller {
647 		CListview* lv;
LevelListFillerDeprecatedGUI::LevelListFiller648 		LevelListFiller(CListview* l) : lv(l) {}
operator ()DeprecatedGUI::LevelListFiller649 		bool operator() (const std::string& filename) {
650 			std::string mapName = CMap::GetLevelName(filename, true);
651 			if(mapName != "") {
652 				std::string baseFile = GetBaseFilename(filename);
653 
654 				if(!lv->getItem(baseFile)) {
655 					lv->AddItem(baseFile, 0, tLX->clListView);
656 					lv->AddSubitem(LVS_TEXT, mapName, (DynDrawIntf*)NULL, NULL);
657 				}
658 			}
659 
660 			return true;
661 		}
662 	};
663 
Menu_MapEd_LoadSave(int save)664 void Menu_MapEd_LoadSave(int save)
665 {
666 	gui_event_t *ev = NULL;
667 	int quitloop = false;
668 	CTextbox *t;
669 
670 	// Save the background
671 	Menu_MapEdFrame(tMenu->bmpBuffer.get(),false);
672 
673 	Menu_DrawBox(tMenu->bmpBuffer.get(), 170, 150, 470, 330);
674 	DrawImageAdv(tMenu->bmpBuffer.get(), tMenu->bmpMainBack_common, 172,152, 172,152, 297,177);
675 
676 	Menu_RedrawMouse(true);
677 
678 	CGuiLayout cg;
679 
680 	cg.Initialize();
681 
682 	cg.Add( new CButton(BUT_CANCEL, tMenu->bmpButtons), 0, 180,310, 75,15);
683 	cg.Add( new CButton(BUT_OK, tMenu->bmpButtons),     1, 430,310, 40,15);
684 	cg.Add( new CListview(),                            2, 180,170, 280,110);
685 	cg.Add( new CTextbox(),                             3, 260,285, 200,tLX->cFont.GetHeight());
686 
687 	cg.SendMessage(2,		LVM_SETOLDSTYLE, (DWORD)0, 0);
688 
689 	t = (CTextbox *)cg.getWidget(3);
690 
691 	// Load the level list
692 	CListview *lv = (CListview *)cg.getWidget(2);
693 	lv->AddColumn("Levels",60);
694 
695 	LevelListFiller filler(lv);
696 	FindFiles(filler, "levels", false, FM_REG);
697 	lv->SortBy( 0, true );
698 
699 	DrawImage(VideoPostProcessor::videoSurface(),tMenu->bmpBuffer, 0,0);
700 	doVideoFrameInMainThread();
701 	DrawImage(VideoPostProcessor::videoSurface(),tMenu->bmpBuffer, 0,0);
702 
703 	ProcessEvents();
704 	while(!WasKeyboardEventHappening(SDLK_ESCAPE,false) && !quitloop && tMenu->bMenuRunning) {
705 		Menu_RedrawMouse(false);
706 
707 		DrawImageAdv(VideoPostProcessor::videoSurface(),tMenu->bmpBuffer, 170,150, 170,150, 302, 182);
708 
709 		tLX->cFont.DrawCentre(VideoPostProcessor::videoSurface(), 320, 155, tLX->clNormalLabel, save ? "Save" : "Load");
710 		tLX->cFont.Draw(VideoPostProcessor::videoSurface(), 180,288,tLX->clNormalLabel, "Level name");
711 
712 		ev = cg.Process();
713 		cg.Draw(VideoPostProcessor::videoSurface());
714 
715 		// Process the widgets
716 		if(ev) {
717 
718 			switch(ev->iControlID) {
719 
720 				// Cancel
721 				case sl_Cancel:
722 					if(ev->iEventMsg == BTN_CLICKED) {
723 						PlaySoundSample(sfxGeneral.smpClick);
724 						quitloop = true;
725 					}
726 					break;
727 
728 				// OK
729 				case sl_Ok:
730 					if(ev->iEventMsg == BTN_CLICKED) {
731 						PlaySoundSample(sfxGeneral.smpClick);
732 
733 						if(t->getText().length() > 0) {
734 
735 							quitloop = true;
736 							std::string buf;
737 							if(save) {
738 
739 								// Save
740 								if(stringtolower(GetFileExtension(t->getText())) != "lxl")
741 									buf = "levels/" + t->getText() + ".lxl";
742 								else
743 									buf = "levels/" + t->getText();
744 
745 								// Check if it exists already. If so, ask user if they wanna overwrite
746 								if(Menu_MapEd_OkSave(buf))
747 									cMap->Save(t->getText(),buf);
748 								else
749 									quitloop = false;
750 							} else {
751 
752 								// Load
753 								buf = "levels/" + t->getText();
754 								cMap->Load(buf);
755 							}
756 						}
757 					}
758 					break;
759 
760 				// Level list
761 				case sl_FileList:
762 					if(ev->iEventMsg != LV_NONE) {
763 						t->setText( lv->getCurSIndex() );
764 					}
765 					break;
766 			}
767 		}
768 
769 
770 		DrawCursor(VideoPostProcessor::videoSurface());
771 		doVideoFrameInMainThread();
772 		CapFPS();
773 		WaitForNextEvent();
774 	}
775 
776 	// Redraw back to normal
777 	DrawImage(tMenu->bmpBuffer.get(),tMenu->bmpMainBack_common,0,0);
778     Menu_DrawSubTitleAdv(tMenu->bmpBuffer.get(),SUB_MAPED,18);
779 	if (tMenu->tFrontendInfo.bPageBoxes)
780 		Menu_DrawBox(tMenu->bmpBuffer.get(), 15,100, 625, 465);
781 
782     Menu_DrawBox(tMenu->bmpBuffer.get(),20,105, 54,139);      // Preview box
783     Menu_DrawBox(tMenu->bmpBuffer.get(),20,146, 619,459);     // Level box
784 
785 	Menu_RedrawMouse(true);
786 
787 	cg.Shutdown();
788 }
789 
790 
791 ///////////////////
792 // Check if there is a possible overwrite
Menu_MapEd_OkSave(const std::string & szFilename)793 bool Menu_MapEd_OkSave(const std::string& szFilename)
794 {
795 	std::string filename = szFilename;
796 
797 	// Adjust the filename
798 	if( stringcasecmp(GetFileExtension( szFilename ), "lxl") != 0)
799 		filename += ".lxl";
800 
801 	FILE *fp = OpenGameFile(filename,"rb");
802 	if( fp == NULL)
803 		// File doesn't exist, ok to save
804 		return true;
805 
806 	fclose(fp);
807 
808 
809 	// The file already exists, show a message box to confirm the overwrite
810 	int nResult = Menu_MessageBox("Confirmation","The level already exists. Overwrite?", LMB_YESNO);
811 	if( nResult == MBR_YES )
812 		return true;
813 
814 
815 	// No overwrite
816 	// Fix the screen up
817 	Menu_MapEdFrame(tMenu->bmpBuffer.get(),false);
818 	Menu_DrawBox(tMenu->bmpBuffer.get(), 170, 150, 470, 330);
819 	DrawImageAdv(tMenu->bmpBuffer.get(), tMenu->bmpMainBack_common, 172,152, 172,152, 297,177);
820 	Menu_RedrawMouse(true);
821 
822 	return false;
823 }
824 
825 }; // namespace DeprecatedGUI
826