- removed a few redundant "== true"'s
[supertux.git] / src / leveleditor.cpp
1 /***************************************************************************
2  *                                                                         *
3  *   This program is free software; you can redistribute it and/or modify  *
4  *   it under the terms of the GNU General Public License as published by  *
5  *   the Free Software Foundation; either version 2 of the License, or     *
6  *   (at your option) any later version.                                   *
7  *                                                                         *
8  ***************************************************************************/
9
10 /*  December 28, 2003 - March 15, 2004 */
11
12 /* leveleditor.c - A built-in level editor for SuperTux
13  Ricardo Cruz <rick2@aeiou.pt>
14  Tobias Glaesser <tobi.web@gmx.de>                      */
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <errno.h>
20 #include <unistd.h>
21 #include <SDL.h>
22 #include <SDL_image.h>
23 #include "leveleditor.h"
24
25 #include "screen.h"
26 #include "defines.h"
27 #include "globals.h"
28 #include "setup.h"
29 #include "menu.h"
30 #include "level.h"
31 #include "badguy.h"
32 #include "scene.h"
33 #include "button.h"
34
35 /* definitions to aid development */
36 #define DONE_LEVELEDITOR 1
37 #define DONE_QUIT        2
38 #define DONE_CHANGELEVEL 3
39
40 /* definitions that affect gameplay */
41 #define KEY_CURSOR_SPEED 32
42 #define KEY_CURSOR_FASTSPEED 64
43
44 /* when pagedown/up pressed speed:*/
45 #define PAGE_CURSOR_SPEED 13*32
46
47 #define MOUSE_LEFT_MARGIN 80
48 #define MOUSE_RIGHT_MARGIN (560-32)
49 /* right_margin should noticed that the cursor is 32 pixels,
50    so it should subtract that value */
51 #define MOUSE_POS_SPEED 20
52
53 /* look */
54 #define SELECT_W 2 // size of the selections lines
55 #define SELECT_CLR 0, 255, 0, 255  // lines color (R, G, B, A)
56
57 /* gameloop funcs declerations */
58
59 void loadshared(void);
60 void unloadshared(void);
61
62 /* own declerations */
63 /* crutial ones (main loop) */
64 int le_init();
65 void le_quit();
66 void le_drawlevel();
67 void le_drawinterface();
68 void le_checkevents();
69 void le_change(float x, float y, unsigned char c);
70 void le_testlevel();
71 void le_showhelp();
72 void le_set_defaults(void);
73 void le_activate_bad_guys(void);
74
75 void le_highlight_selection();
76
77 void apply_level_settings_menu();
78 void update_subset_settings_menu();
79 void save_subset_settings_menu();
80 void le_update_buttons(const char*);
81
82 /* leveleditor internals */
83 static string_list_type level_subsets;
84 static bool le_level_changed;  /* if changes, ask for saving, when quiting*/
85 static int pos_x, cursor_x, cursor_y, fire;
86 static int le_level;
87 static st_level* le_current_level;
88 static st_subset le_level_subset;
89 static int le_show_grid;
90 static int le_frame;
91 static texture_type le_selection;
92 static int done;
93 static char le_current_tile;
94 static bool le_mouse_pressed[2];
95 static button_type le_save_level_bt;
96 static button_type le_test_level_bt;
97 static button_type le_next_level_bt;
98 static button_type le_previous_level_bt;
99 static button_type le_move_right_bt;
100 static button_type le_move_left_bt;
101 static button_type le_rubber_bt;
102 static button_type le_select_mode_one_bt;
103 static button_type le_select_mode_two_bt;
104 static button_type le_settings_bt;
105 static button_type le_bad_bt;
106 static button_type le_bkgd_bt;
107 static button_type le_fgd_bt;
108 static button_panel_type le_bkgd_panel;
109 static button_panel_type le_fgd_panel;
110 static button_panel_type le_bad_panel;
111 static Menu* leveleditor_menu;
112 static Menu* subset_load_menu;
113 static Menu* subset_new_menu;
114 static Menu* subset_settings_menu;
115 static Menu* level_settings_menu;
116
117 static square selection;
118 static int le_selection_mode;
119 static SDL_Event event;
120
121 void le_activate_bad_guys(void)
122 {
123   int x,y;
124
125   /* Activate bad guys: */
126
127   /* as oposed to the gameloop.c func, this one doesn't remove
128   the badguys from tiles                                    */
129
130   for (y = 0; y < 15; ++y)
131     for (x = 0; x < le_current_level->width; ++x)
132       if (le_current_level->tiles[y][x] >= '0' && le_current_level->tiles[y][x] <= '9')
133         add_bad_guy(x * 32, y * 32, static_cast<BadGuyKind>(le_current_level->tiles[y][x] - '0'));
134 }
135
136 void le_set_defaults()
137 {
138   if(le_current_level != NULL)
139     {
140       /* Set defaults: */
141
142       if(le_current_level->time_left == 0)
143         le_current_level->time_left = 255;
144     }
145 }
146
147 int leveleditor(int levelnb)
148 {
149   int last_time, now_time, i;
150
151   le_level = levelnb;
152   if(le_init() != 0)
153     return 1;
154
155   /* Clear screen: */
156
157   clearscreen(0, 0, 0);
158   updatescreen();
159
160   while (SDL_PollEvent(&event))
161   {}
162
163   while(true)
164     {
165       last_time = SDL_GetTicks();
166       le_frame++;
167
168       le_checkevents();
169
170       if(le_current_level != NULL)
171         {
172           /* making events results to be in order */
173           if(pos_x < 0)
174             pos_x = 0;
175           if(pos_x > (le_current_level->width * 32) - screen->w)
176             pos_x = (le_current_level->width * 32) - screen->w;
177
178           /* draw the level */
179           le_drawlevel();
180         }
181       else
182         clearscreen(0, 0, 0);
183
184       /* draw editor interface */
185       le_drawinterface();
186
187       if(show_menu)
188         {
189           menu_process_current();
190           if(current_menu == leveleditor_menu)
191             {
192               switch (leveleditor_menu->check())
193                 {
194                 case 2:
195                   show_menu = false;
196                   break;
197                 case 3:
198                   update_subset_settings_menu();
199                   break;
200                 case 7:
201                   done = DONE_LEVELEDITOR;
202                   break;
203                 }
204             }
205           else if(current_menu == level_settings_menu)
206             {
207               switch (level_settings_menu->check())
208                 {
209                 case 13:
210                   apply_level_settings_menu();
211                   Menu::set_current(leveleditor_menu);
212                   break;
213                 default:
214                   show_menu = true;
215                   break;
216                 }
217             }
218           else if(current_menu == subset_load_menu)
219             {
220               switch (i = subset_load_menu->check())
221                 {
222                 case 0:
223                   break;
224                 default:
225                   if(i != -1)
226                     {
227                       le_level_subset.load(level_subsets.item[i-2]);
228                       leveleditor_menu->item[3].kind = MN_GOTO;
229                       le_level = 1;
230                       arrays_init();
231                       loadshared();
232                       le_current_level = new st_level;
233                       if(level_load(le_current_level, le_level_subset.name.c_str(), le_level) != 0)
234                         {
235                           le_quit();
236                           return 1;
237                         }
238                       le_update_buttons(le_current_level->theme.c_str());
239                       le_set_defaults();
240                       level_load_gfx(le_current_level);
241                       le_activate_bad_guys();
242                       show_menu = true;
243                     }
244                   break;
245                 }
246             }
247           else if(current_menu == subset_new_menu)
248             {
249               if(subset_new_menu->item[2].input[0] == '\0')
250                 subset_new_menu->item[3].kind = MN_DEACTIVE;
251               else
252                 {
253                   subset_new_menu->item[3].kind = MN_ACTION;
254
255                   switch (i = subset_new_menu->check())
256                     {
257                     case 3:
258                       st_subset::create(subset_new_menu->item[2].input);
259                       le_level_subset.load(subset_new_menu->item[2].input);
260                       leveleditor_menu->item[3].kind = MN_GOTO;
261                       le_level = 1;
262                       arrays_init();
263                       loadshared();
264                       le_current_level = new st_level;
265                       if(level_load(le_current_level, le_level_subset.name.c_str(), le_level) != 0)
266                         {
267                           le_quit();
268                           return 1;
269                         }
270                       le_update_buttons(le_current_level->theme.c_str());
271                       le_set_defaults();
272                       level_load_gfx(le_current_level);
273                       le_activate_bad_guys();
274                       menu_item_change_input(&subset_new_menu->item[2],"");
275                       show_menu = true;
276                       break;
277                     }
278                 }
279             }
280           else if(current_menu == subset_settings_menu)
281             {
282               if(le_level_subset.title.compare(subset_settings_menu->item[2].input) == 0 && le_level_subset.description.compare(subset_settings_menu->item[3].input) == 0  )
283                 subset_settings_menu->item[5].kind = MN_DEACTIVE;
284               else
285                 subset_settings_menu->item[5].kind = MN_ACTION;
286
287               switch (i = subset_settings_menu->check())
288                 {
289                 case 5:
290                   save_subset_settings_menu();
291                   show_menu = true;
292                   break;
293                 }
294             }
295         }
296
297       if(done)
298         {
299           le_quit();
300           return 0;
301         }
302
303       if(done == DONE_QUIT)
304         {
305           le_quit();
306           return 1;
307         }
308
309       SDL_Delay(25);
310       now_time = SDL_GetTicks();
311       if (now_time < last_time + FPS)
312         SDL_Delay(last_time + FPS - now_time);  /* delay some time */
313
314       flipscreen();
315     }
316
317   return done;
318 }
319
320
321 void le_update_buttons(const char *theme)
322 {
323   int i;
324   char filename[1024];
325   char pathname[1024];
326   SDLKey key;
327   string_list_type bkgd_files;
328   string_list_type fgd_files;
329
330   sprintf(pathname,"images/themes/%s",theme);
331   bkgd_files =  dfiles(pathname,"bkgd-", NULL);
332   string_list_sort(&bkgd_files);
333
334   le_bkgd_panel.hidden = true;
335   key = SDLK_a;
336   for(i = 0; i < bkgd_files.num_items; ++i)
337     {
338       sprintf(filename,"%s/%s",pathname,bkgd_files.item[i]);
339       button_change_icon(&le_bkgd_panel.item[i],filename);
340     }
341
342   sprintf(pathname,"images/themes/%s",theme);
343   fgd_files =  dfiles(pathname,"solid", NULL);
344   string_list_sort(&fgd_files);
345   key = SDLK_a;
346   for(i = 0; i < fgd_files.num_items; ++i)
347     {
348       sprintf(filename,"%s/%s",pathname,fgd_files.item[i]);
349       button_change_icon(&le_fgd_panel.item[i],filename);
350     }
351
352   string_list_free(&fgd_files);
353   fgd_files =  dfiles(pathname,"brick", NULL);
354   string_list_sort(&fgd_files);
355
356   for(i = 0; i < fgd_files.num_items; ++i)
357     {
358       sprintf(filename,"%s/%s",pathname,fgd_files.item[i]);
359       button_change_icon(&le_fgd_panel.item[i+14],filename);
360     }
361 }
362
363 int le_init()
364 {
365   int i;
366   char filename[1024];
367   SDLKey key;
368   string_list_type fgd_files;
369   string_list_type bkgd_files;
370   string_list_type bad_files;
371   level_subsets = dsubdirs("/levels", "info");
372
373   le_show_grid = true;
374
375   /*  level_changed = NO;*/
376   fire = DOWN;
377   done = 0;
378   le_frame = 0; /* support for frames in some tiles, like waves and bad guys */
379   le_level_changed = false;
380   le_current_level = NULL;
381
382   le_current_tile = '.';
383   le_mouse_pressed[LEFT] = false;
384   le_mouse_pressed[RIGHT] = false;
385
386   texture_load(&le_selection, datadir + "/images/leveleditor/select.png", USE_ALPHA);
387
388   /* Load buttons */
389   button_load(&le_save_level_bt,"/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32);
390   button_load(&le_next_level_bt,"/images/icons/up.png","Next level", SDLK_PAGEUP,screen->w-64,0);
391   button_load(&le_previous_level_bt,"/images/icons/down.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0);
392   button_load(&le_rubber_bt,"/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48);
393   button_load(&le_select_mode_one_bt,"/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48);
394   button_load(&le_select_mode_two_bt,"/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,64);
395   button_load(&le_test_level_bt,"/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64);
396   button_load(&le_settings_bt,"/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64);
397   button_load(&le_move_left_bt,"/images/icons/left.png","Move left",SDLK_LEFT,0,0);
398   button_load(&le_move_right_bt,"/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0);
399   button_load(&le_fgd_bt,"/images/icons/fgd.png","Foreground tiles", SDLK_F7,screen->w-64,82);
400   button_load(&le_bkgd_bt,"/images/icons/bgd.png","Background tiles", SDLK_F8,screen->w-43,82);
401   button_load(&le_bad_bt,"/images/icons/emy.png","Enemies", SDLK_F9,screen->w-22,82);
402
403   bkgd_files =  dfiles("images/themes/antarctica","bkgd-", NULL);
404   string_list_sort(&bkgd_files);
405
406   button_panel_init(&le_bkgd_panel, screen->w - 64,98, 64, 318);
407   le_bkgd_panel.hidden = true;
408   key = SDLK_a;
409   for(i = 0; i < bkgd_files.num_items; ++i)
410     {
411       sprintf(filename,"images/themes/antarctica/%s",bkgd_files.item[i]);
412       button_panel_additem(&le_bkgd_panel,button_create(filename, "Background Tile",(SDLKey)((int)key+i),0,0),i);
413     }
414
415   string_list_free(&bkgd_files);
416   bkgd_files = dfiles("images/shared","cloud-", NULL);
417   string_list_sort(&bkgd_files);
418
419   for(i = 0; i < bkgd_files.num_items; ++i)
420     {
421       sprintf(filename,"images/shared/%s",bkgd_files.item[i]);
422       button_panel_additem(&le_bkgd_panel,button_create(filename, "Background Tile",(SDLKey)((int)key+i+8),0,0),i+8);
423     }
424
425   fgd_files =  dfiles("images/themes/antarctica","solid", NULL);
426   string_list_sort(&fgd_files);
427   key = SDLK_a;
428   button_panel_init(&le_fgd_panel, screen->w - 64,98, 64, 318);
429   for(i = 0; i < fgd_files.num_items; ++i)
430     {
431       sprintf(filename,"images/themes/antarctica/%s",fgd_files.item[i]);
432       button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i),0,0),i);
433     }
434
435   string_list_free(&fgd_files);
436   string_list_add_item(&fgd_files,"waves-0.png");
437   string_list_add_item(&fgd_files,"water.png");
438   string_list_add_item(&fgd_files,"pole.png");
439   string_list_add_item(&fgd_files,"poletop.png");
440   string_list_add_item(&fgd_files,"flag-0.png");
441   string_list_add_item(&fgd_files,"box-empty.png");
442   string_list_add_item(&fgd_files,"mints.png");
443   string_list_add_item(&fgd_files,"distro-0.png");
444   string_list_add_item(&fgd_files,"golden-herring.png");
445   string_list_add_item(&fgd_files,"distro-0.png");
446
447   for(i = 0; i < fgd_files.num_items; ++i)
448     {
449       sprintf(filename,"images/shared/%s",fgd_files.item[i]);
450       button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i+4),0,0),i+4);
451     }
452
453   string_list_free(&fgd_files);
454   fgd_files =  dfiles("images/themes/antarctica","brick", NULL);
455   string_list_sort(&fgd_files);
456
457   for(i = 0; i < fgd_files.num_items; ++i)
458     {
459       sprintf(filename,"images/themes/antarctica/%s",fgd_files.item[i]);
460       button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i+14),0,0),i+14);
461     }
462
463   string_list_free(&fgd_files);
464   string_list_add_item(&fgd_files,"distro-0.png");
465   string_list_add_item(&fgd_files,"distro-0.png");
466   for(i = 0; i < fgd_files.num_items; ++i)
467     {
468       sprintf(filename,"images/shared/%s",fgd_files.item[i]);
469       button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i+16),0,0),i+16);
470     }
471
472   le_fgd_panel.item[10].bkgd = &le_fgd_panel.item[9].icon;
473   le_fgd_panel.item[11].bkgd = &le_fgd_panel.item[9].icon;
474   le_fgd_panel.item[12].bkgd = &le_fgd_panel.item[9].icon;
475   le_fgd_panel.item[16].bkgd = &le_fgd_panel.item[14].icon;
476   le_fgd_panel.item[17].bkgd = &le_fgd_panel.item[15].icon;
477
478   string_list_init(&bad_files);
479   string_list_add_item(&bad_files,"bsod-left-0.png");
480   string_list_add_item(&bad_files,"laptop-left-0.png");
481   string_list_add_item(&bad_files,"bag-left-0.png");
482   button_panel_init(&le_bad_panel, screen->w - 64,98, 64, 318);
483   le_bad_panel.hidden = true;
484   key = SDLK_a;
485   for(i = 0; i < bad_files.num_items; ++i)
486     {
487       sprintf(filename,"images/shared/%s",bad_files.item[i]);
488       button_panel_additem(&le_bad_panel,button_create(filename, "Bad Guy",(SDLKey)((int)key+i),0,0),i);
489     }
490
491   leveleditor_menu = new Menu();
492   subset_load_menu = new Menu();
493   subset_new_menu  = new Menu();
494   subset_settings_menu = new Menu();
495   level_settings_menu  = new Menu();
496
497   leveleditor_menu->additem(MN_LABEL,"Level Editor Menu",0,0);
498   leveleditor_menu->additem(MN_HL,"",0,0);
499   leveleditor_menu->additem(MN_ACTION,"Return To Level Editor",0,0);
500   leveleditor_menu->additem(MN_DEACTIVE,"Level Subset Settings",0,subset_settings_menu);
501   leveleditor_menu->additem(MN_GOTO,"Load Level Subset",0,subset_load_menu);
502   leveleditor_menu->additem(MN_GOTO,"New Level Subset",0,subset_new_menu);
503   leveleditor_menu->additem(MN_HL,"",0,0);
504   leveleditor_menu->additem(MN_ACTION,"Quit Level Editor",0,0);
505
506   menu_reset();
507   Menu::set_current(leveleditor_menu);
508   show_menu = true;
509
510   subset_load_menu->additem(MN_LABEL, "Load Level Subset", 0, 0);
511   subset_load_menu->additem(MN_HL, "", 0, 0);
512
513   for(i = 0; i < level_subsets.num_items; ++i)
514     {
515       subset_load_menu->additem(MN_ACTION,level_subsets.item[i],0,0);
516     }
517   subset_load_menu->additem(MN_HL,"",0,0);
518   subset_load_menu->additem(MN_BACK,"Back",0,0);
519
520   subset_new_menu->additem(MN_LABEL,"New Level Subset",0,0);
521   subset_new_menu->additem(MN_HL,"",0,0);
522   subset_new_menu->additem(MN_TEXTFIELD,"Enter Name",0,0);
523   subset_new_menu->additem(MN_ACTION,"Create",0,0);
524   subset_new_menu->additem(MN_HL,"",0,0);
525   subset_new_menu->additem(MN_BACK,"Back",0,0);
526
527   subset_settings_menu->additem(MN_LABEL,"Level Subset Settings",0,0);
528   subset_settings_menu->additem(MN_HL,"",0,0);
529   subset_settings_menu->additem(MN_TEXTFIELD,"Title",0,0);
530   subset_settings_menu->additem(MN_TEXTFIELD,"Description",0,0);
531   subset_settings_menu->additem(MN_HL,"",0,0);
532   subset_settings_menu->additem(MN_ACTION,"Save Changes",0,0);
533   subset_settings_menu->additem(MN_HL,"",0,0);
534   subset_settings_menu->additem(MN_BACK,"Back",0,0);
535
536   level_settings_menu->arrange_left = true;
537   level_settings_menu->additem(MN_LABEL,"Level Settings",0,0);
538   level_settings_menu->additem(MN_HL,"",0,0);
539   level_settings_menu->additem(MN_TEXTFIELD,"Name    ",0,0);
540   level_settings_menu->additem(MN_STRINGSELECT,"Theme   ",0,0);
541   level_settings_menu->additem(MN_STRINGSELECT,"Song    ",0,0);
542   level_settings_menu->additem(MN_STRINGSELECT,"Bg-Image",0,0);
543   level_settings_menu->additem(MN_NUMFIELD,"Length ",0,0);
544   level_settings_menu->additem(MN_NUMFIELD,"Time   ",0,0);
545   level_settings_menu->additem(MN_NUMFIELD,"Gravity",0,0);
546   level_settings_menu->additem(MN_NUMFIELD,"Red    ",0,0);
547   level_settings_menu->additem(MN_NUMFIELD,"Green  ",0,0);
548   level_settings_menu->additem(MN_NUMFIELD,"Blue   ",0,0);
549   level_settings_menu->additem(MN_HL,"",0,0);
550   level_settings_menu->additem(MN_ACTION,"Apply Changes",0,0);
551
552   SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
553
554   return 0;
555 }
556
557 void update_level_settings_menu()
558 {
559   char str[80];
560   int i;
561
562   menu_item_change_input(&level_settings_menu->item[2], le_current_level->name.c_str());
563   sprintf(str,"%d",le_current_level->width);
564
565   string_list_copy(level_settings_menu->item[3].list, dsubdirs("images/themes", "solid0.png"));
566   string_list_copy(level_settings_menu->item[4].list, dfiles("music/",NULL, "-fast"));
567   string_list_copy(level_settings_menu->item[5].list, dfiles("images/background",NULL, NULL));
568   string_list_add_item(level_settings_menu->item[5].list,"");
569   if((i = string_list_find(level_settings_menu->item[3].list,le_current_level->theme.c_str())) != -1)
570     level_settings_menu->item[3].list->active_item = i;
571   if((i = string_list_find(level_settings_menu->item[4].list,le_current_level->song_title.c_str())) != -1)
572     level_settings_menu->item[4].list->active_item = i;
573   if((i = string_list_find(level_settings_menu->item[5].list,le_current_level->bkgd_image.c_str())) != -1)
574     level_settings_menu->item[5].list->active_item = i;
575
576   menu_item_change_input(&level_settings_menu->item[6], str);
577   sprintf(str,"%d",le_current_level->time_left);
578   menu_item_change_input(&level_settings_menu->item[7], str);
579   sprintf(str,"%2.0f",le_current_level->gravity);
580   menu_item_change_input(&level_settings_menu->item[8], str);
581   sprintf(str,"%d",le_current_level->bkgd_red);
582   menu_item_change_input(&level_settings_menu->item[9], str);
583   sprintf(str,"%d",le_current_level->bkgd_green);
584   menu_item_change_input(&level_settings_menu->item[10], str);
585   sprintf(str,"%d",le_current_level->bkgd_blue);
586   menu_item_change_input(&level_settings_menu->item[11], str);
587 }
588
589 void update_subset_settings_menu()
590 {
591   menu_item_change_input(&subset_settings_menu->item[2], le_level_subset.title.c_str());
592   menu_item_change_input(&subset_settings_menu->item[3], le_level_subset.description.c_str());
593 }
594
595 void apply_level_settings_menu()
596 {
597   int i,y,j;
598   i = false;
599
600   le_current_level->name = level_settings_menu->item[2].input;
601
602   if(le_current_level->bkgd_image.compare(string_list_active(level_settings_menu->item[5].list)) != 0)
603     {
604       le_current_level->bkgd_image = string_list_active(level_settings_menu->item[5].list);
605       i = true;
606     }
607
608   if(le_current_level->theme.compare(string_list_active(level_settings_menu->item[3].list)) != 0)
609     {
610       le_current_level->theme = string_list_active(level_settings_menu->item[3].list);
611       le_update_buttons(le_current_level->theme.c_str());
612       i = true;
613     }
614
615   if(i)
616     {
617       level_free_gfx();
618       level_load_gfx(le_current_level);
619     }
620
621   le_current_level->song_title = string_list_active(level_settings_menu->item[4].list);
622
623   i = le_current_level->width;
624   le_current_level->width = atoi(level_settings_menu->item[6].input);
625   if(le_current_level->width < i)
626     {
627       if(le_current_level->width < 21)
628         le_current_level->width = 21;
629       for(y = 0; y < 15; ++y)
630         {
631           le_current_level->tiles[y] = (unsigned int*) realloc(le_current_level->tiles[y],(le_current_level->width+1)*sizeof(unsigned int));
632           le_current_level->tiles[y][le_current_level->width] = (unsigned int) '\0';
633         }
634     }
635   else if(le_current_level->width > i)
636     {
637       for(y = 0; y < 15; ++y)
638         {
639           le_current_level->tiles[y] = (unsigned int*) realloc(le_current_level->tiles[y],(le_current_level->width+1)*sizeof(unsigned int));
640           for(j = 0; j < le_current_level->width - i; ++j)
641             le_current_level->tiles[y][i+j] = (unsigned int) '.';
642           le_current_level->tiles[y][le_current_level->width] = (unsigned int) '\0';
643         }
644     }
645   le_current_level->time_left = atoi(level_settings_menu->item[7].input);
646   le_current_level->gravity = atof(level_settings_menu->item[8].input);
647   le_current_level->bkgd_red = atoi(level_settings_menu->item[9].input);
648   le_current_level->bkgd_green = atoi(level_settings_menu->item[10].input);
649   le_current_level->bkgd_blue = atoi(level_settings_menu->item[11].input);
650 }
651
652 void save_subset_settings_menu()
653 {
654   le_level_subset.title = subset_settings_menu->item[2].input;
655   le_level_subset.description = subset_settings_menu->item[3].input;
656   le_level_subset.save();
657 }
658
659 void le_goto_level(int levelnb)
660 {
661   arrays_free();
662   arrays_init();
663
664   level_free(le_current_level);
665   if(level_load(le_current_level, le_level_subset.name.c_str(), levelnb) != 0)
666     {
667       level_load(le_current_level, le_level_subset.name.c_str(), le_level);
668     }
669   else
670     {
671       le_level = levelnb;
672     }
673
674   le_set_defaults();
675
676   le_update_buttons(le_current_level->theme.c_str());
677
678   level_free_gfx();
679   level_load_gfx(le_current_level);
680
681   le_activate_bad_guys();
682 }
683
684 void le_quit(void)
685 {
686   /*if(level_changed == true)
687     if(askforsaving() == CANCEL)
688       return;*/ //FIXME
689
690   SDL_EnableKeyRepeat(0, 0);    // disables key repeating
691
692   texture_free(&le_selection);
693   delete leveleditor_menu;
694   delete subset_load_menu;
695   delete subset_new_menu;
696   delete subset_settings_menu;
697   delete level_settings_menu;
698   button_panel_free(&le_bkgd_panel);
699   button_panel_free(&le_fgd_panel);
700   button_panel_free(&le_bad_panel);
701   button_free(&le_save_level_bt);
702   button_free(&le_test_level_bt);
703   button_free(&le_next_level_bt);
704   button_free(&le_previous_level_bt);
705   button_free(&le_move_right_bt);
706   button_free(&le_move_left_bt);
707   button_free(&le_rubber_bt);
708   button_free(&le_select_mode_one_bt);
709   button_free(&le_select_mode_two_bt);
710   button_free(&le_settings_bt);
711   button_free(&le_bad_bt);
712   button_free(&le_bkgd_bt);
713   button_free(&le_fgd_bt);
714
715   if(le_current_level != NULL)
716     {
717       level_free_gfx();
718       level_free(le_current_level);
719       unloadshared();
720       arrays_free();
721     }
722 }
723
724 void le_drawinterface()
725 {
726   int x,y;
727   char str[80];
728
729   if(le_current_level != NULL)
730     {
731       /* draw a grid (if selected) */
732       if(le_show_grid)
733         {
734           for(x = 0; x < 19; x++)
735             fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
736           for(y = 0; y < 15; y++)
737             fillrect(0, y*32, screen->w - 32, 1, 225, 225, 225,255);
738         }
739     }
740
741   if(le_selection_mode == CURSOR)
742     texture_draw(&le_selection, cursor_x - pos_x, cursor_y);
743   else if(le_selection_mode == SQUARE)
744     {
745       int w, h;
746       le_highlight_selection();
747       /* draw current selection */
748       w = selection.x2 - selection.x1;
749       h = selection.y2 - selection.y1;
750       fillrect(selection.x1 - pos_x, selection.y1, w, SELECT_W, SELECT_CLR);
751       fillrect(selection.x1 - pos_x + w, selection.y1, SELECT_W, h, SELECT_CLR);
752       fillrect(selection.x1 - pos_x, selection.y1 + h, w, SELECT_W, SELECT_CLR);
753       fillrect(selection.x1 - pos_x, selection.y1, SELECT_W, h, SELECT_CLR);
754     }
755
756
757   /* draw button bar */
758   fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
759   drawshape(19 * 32, 14 * 32, le_current_tile);
760   switch(le_current_tile)
761     {
762     case 'B':
763       texture_draw(&img_mints, 19 * 32, 14 * 32);
764       break;
765     case '!':
766       texture_draw(&img_golden_herring,19 * 32, 14 * 32);
767       break;
768     case 'x':
769     case 'y':
770     case 'A':
771       texture_draw(&img_distro[(le_frame / 5) % 4], 19 * 32, 14 * 32);
772       break;
773     case '0':
774       texture_draw(&img_bsod_left[(le_frame / 5) % 4],19 * 32, 14 * 32);
775       break;
776     case '1':
777       texture_draw(&img_laptop_left[(le_frame / 5) % 3],19 * 32, 14 * 32);
778       break;
779     case '2':
780       texture_draw(&img_money_left[0],19 * 32, 14 * 32);
781       break;
782     default:
783       break;
784     }
785
786   if(le_current_level != NULL)
787     {
788       button_draw(&le_save_level_bt);
789       button_draw(&le_test_level_bt);
790       button_draw(&le_next_level_bt);
791       button_draw(&le_previous_level_bt);
792       button_draw(&le_rubber_bt);
793       button_draw(&le_select_mode_one_bt);
794       button_draw(&le_select_mode_two_bt);
795       button_draw(&le_settings_bt);
796       button_draw(&le_move_right_bt);
797       button_draw(&le_move_left_bt);
798       button_draw(&le_bad_bt);
799       button_draw(&le_bkgd_bt);
800       button_draw(&le_fgd_bt);
801       button_panel_draw(&le_bkgd_panel);
802       button_panel_draw(&le_fgd_panel);
803       button_panel_draw(&le_bad_panel);
804
805       sprintf(str, "%d/%d", le_level,le_level_subset.levels);
806       text_drawf(&white_text, str, -8, 16, A_RIGHT, A_TOP, 1);
807
808       text_draw(&white_small_text, "F1 for Help", 10, 430, 1);
809     }
810   else
811     {
812       if(show_menu == false)
813         text_draw(&white_small_text, "No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1);
814       else
815         text_draw(&white_small_text, "No Level Subset loaded", 10, 430, 1);
816     }
817
818 }
819
820 void le_drawlevel()
821 {
822   unsigned int y,x,i,s;
823
824   /* Draw the real background */
825   if(le_current_level->bkgd_image[0] != '\0')
826     {
827       s = pos_x / 30;
828       texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s - 32, img_bkgd.h);
829       texture_draw_part(&img_bkgd,0,0,screen->w - s - 32 ,0,s,img_bkgd.h);
830     }
831   else
832     {
833       clearscreen(le_current_level->bkgd_red, le_current_level->bkgd_green, le_current_level->bkgd_blue);
834     }
835
836   /*       clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
837
838   for (y = 0; y < 15; ++y)
839     for (x = 0; x < 20; ++x)
840       {
841         drawshape(x * 32 - ((int)pos_x % 32), y * 32,
842                   le_current_level->tiles[y][x + (int)(pos_x / 32)]);
843
844         /* draw whats inside stuff when cursor is selecting those */
845         /* (draw them all the time - is this the right behaviour?) */
846         switch(le_current_level->tiles[y][x + (int)(pos_x/32)])
847           {
848           case 'B':
849             texture_draw(&img_mints, x * 32 - ((int)pos_x % 32), y*32);
850             break;
851           case '!':
852             texture_draw(&img_golden_herring, x * 32 - ((int)pos_x % 32), y*32);
853             break;
854           case 'x':
855           case 'y':
856           case 'A':
857             texture_draw(&img_distro[(global_frame_counter / 5) % 4], x * 32 - ((int)pos_x % 32), y*32);
858             break;
859           default:
860             break;
861           }
862       }
863
864   /* Draw the Bad guys: */
865   for (i = 0; i < bad_guys.size(); ++i)
866     {
867       /* to support frames: img_bsod_left[(frame / 5) % 4] */
868       if(bad_guys[i].kind == BAD_BSOD)
869         texture_draw(&img_bsod_left[(le_frame / 5) % 4], bad_guys[i].base.x - pos_x, bad_guys[i].base.y);
870       else if(bad_guys[i].kind == BAD_LAPTOP)
871         texture_draw(&img_laptop_left[(le_frame / 5) % 3], bad_guys[i].base.x - pos_x, bad_guys[i].base.y);
872       else if (bad_guys[i].kind == BAD_MONEY)
873         texture_draw(&img_money_left[(le_frame / 5) % 2], bad_guys[i].base.x - pos_x, bad_guys[i].base.y);
874     }
875
876
877   /* Draw the player: */
878   /* for now, the position is fixed at (0, 240) */
879   texture_draw(&tux_right[(global_frame_counter / 5) % 3], 0 - pos_x, 240);
880 }
881
882 void le_checkevents()
883 {
884   SDLKey key;
885   SDLMod keymod;
886   button_type* pbutton;
887   int x,y;
888
889   keymod = SDL_GetModState();
890
891   while(SDL_PollEvent(&event))
892     {
893       /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
894       if(event.type == SDL_KEYDOWN || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION) && (event.motion.x > 0 && event.motion.x < screen->w - 64 &&
895                                        event.motion.y > 0 && event.motion.y < screen->h)))
896         {
897
898           switch(event.type)
899             {
900             case SDL_KEYDOWN:   // key pressed
901               key = event.key.keysym.sym;
902               if(show_menu)
903                 {
904                   menu_event(&event.key.keysym);
905                   if(key == SDLK_ESCAPE)
906                     {
907                       show_menu = false;
908                       Menu::set_current(leveleditor_menu);
909                     }
910                   break;
911                 }
912               switch(key)
913                 {
914                 case SDLK_ESCAPE:
915                   if(!show_menu)
916                     show_menu = true;
917                   else
918                     show_menu = false;
919                   break;
920                 case SDLK_LEFT:
921                   if(fire == DOWN)
922                     cursor_x -= KEY_CURSOR_SPEED;
923                   else
924                     cursor_x -= KEY_CURSOR_FASTSPEED;
925
926                   if(cursor_x < pos_x + MOUSE_LEFT_MARGIN)
927                     pos_x = cursor_x - MOUSE_LEFT_MARGIN;
928
929                   break;
930                 case SDLK_RIGHT:
931                   if(fire == DOWN)
932                     cursor_x += KEY_CURSOR_SPEED;
933                   else
934                     cursor_x += KEY_CURSOR_FASTSPEED;
935
936                   if(cursor_x > pos_x + MOUSE_RIGHT_MARGIN-32)
937                     pos_x = cursor_x - MOUSE_RIGHT_MARGIN+32;
938
939                   break;
940                 case SDLK_UP:
941                   if(fire == DOWN)
942                     cursor_y -= KEY_CURSOR_SPEED;
943                   else
944                     cursor_y -= KEY_CURSOR_FASTSPEED;
945
946                   if(cursor_y < 0)
947                     cursor_y = 0;
948                   break;
949                 case SDLK_DOWN:
950                   if(fire == DOWN)
951                     cursor_y += KEY_CURSOR_SPEED;
952                   else
953                     cursor_y += KEY_CURSOR_FASTSPEED;
954
955                   if(cursor_y > screen->h-32)
956                     cursor_y = screen->h-32;
957                   break;
958                 case SDLK_LCTRL:
959                   fire =UP;
960                   break;
961                 case SDLK_F1:
962                   le_showhelp();
963                   break;
964                 case SDLK_HOME:
965                   cursor_x = 0;
966                   pos_x = cursor_x;
967                   break;
968                 case SDLK_END:
969                   cursor_x = (le_current_level->width * 32) - 32;
970                   pos_x = cursor_x;
971                   break;
972                 case SDLK_F9:
973                   le_show_grid = !le_show_grid;
974                   break;
975                 default:
976                   break;
977                 }
978               break;
979             case SDL_KEYUP:     /* key released */
980               switch(event.key.keysym.sym)
981                 {
982                 case SDLK_LCTRL:
983                   fire = DOWN;
984                   break;
985                 default:
986                   break;
987                 }
988               break;
989             case SDL_MOUSEBUTTONDOWN:
990               if(event.button.button == SDL_BUTTON_LEFT)
991                 {
992                   le_mouse_pressed[LEFT] = true;
993
994                   selection.x1 = event.motion.x + pos_x;
995                   selection.y1 = event.motion.y;
996                   selection.x2 = event.motion.x + pos_x;
997                   selection.y2 = event.motion.y;
998                 }
999               else if(event.button.button == SDL_BUTTON_RIGHT)
1000                 le_mouse_pressed[RIGHT] = true;
1001               break;
1002             case SDL_MOUSEBUTTONUP:
1003               if(event.button.button == SDL_BUTTON_LEFT)
1004                 le_mouse_pressed[LEFT] = false;
1005               else if(event.button.button == SDL_BUTTON_RIGHT)
1006                 le_mouse_pressed[RIGHT] = false;
1007               break;
1008             case SDL_MOUSEMOTION:
1009               if(!show_menu)
1010                 {
1011                   x = event.motion.x;
1012                   y = event.motion.y;
1013
1014                   cursor_x = ((int)(pos_x + x) / 32) * 32;
1015                   cursor_y = ((int) y / 32) * 32;
1016
1017                   if(le_mouse_pressed[LEFT])
1018                     {
1019                       selection.x2 = x + pos_x;
1020                       selection.y2 = y;
1021                     }
1022
1023                   if(le_mouse_pressed[RIGHT])
1024                     {
1025                       pos_x += -1 * event.motion.xrel;
1026                     }
1027                 }
1028               break;
1029             case SDL_QUIT:      // window closed
1030               done = DONE_QUIT;
1031               break;
1032             default:
1033               break;
1034             }
1035         }
1036
1037       if(le_current_level != NULL)
1038         {
1039           if(event.type == SDL_KEYDOWN || event.type == SDL_KEYUP || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION) && (event.motion.x > screen->w-64 && event.motion.x < screen->w &&
1040               event.motion.y > 0 && event.motion.y < screen->h)))
1041             {
1042               le_mouse_pressed[LEFT] = false;
1043               le_mouse_pressed[RIGHT] = false;
1044
1045               if(show_menu == false)
1046                 {
1047                   /* Check for button events */
1048                   button_event(&le_test_level_bt,&event);
1049                   if(button_get_state(&le_test_level_bt) == BUTTON_CLICKED)
1050                     le_testlevel();
1051                   button_event(&le_save_level_bt,&event);
1052                   if(button_get_state(&le_save_level_bt) == BUTTON_CLICKED)
1053                     level_save(le_current_level,le_level_subset.name.c_str(),le_level);
1054                   button_event(&le_next_level_bt,&event);
1055                   if(button_get_state(&le_next_level_bt) == BUTTON_CLICKED)
1056                     {
1057                       if(le_level < le_level_subset.levels)
1058                         {
1059                           le_goto_level(++le_level);
1060                         }
1061                       else
1062                         {
1063                           st_level new_lev;
1064                           char str[1024];
1065                           int d = 0;
1066                           sprintf(str,"Level %d doesn't exist.",le_level+1);
1067                           text_drawf(&white_text,str,0,-18,A_HMIDDLE,A_VMIDDLE,2);
1068                           text_drawf(&white_text,"Do you want to create it?",0,0,A_HMIDDLE,A_VMIDDLE,2);
1069                           text_drawf(&red_text,"(Y)es/(N)o",0,20,A_HMIDDLE,A_VMIDDLE,2);
1070                           flipscreen();
1071                           while(d == 0)
1072                             {
1073                               while(SDL_PollEvent(&event))
1074                                 switch(event.type)
1075                                   {
1076                                   case SDL_KEYDOWN:             // key pressed
1077                                     switch(event.key.keysym.sym)
1078                                       {
1079                                       case SDLK_y:
1080                                         level_default(&new_lev);
1081                                         level_save(&new_lev,le_level_subset.name.c_str(),++le_level);
1082                                         le_level_subset.levels = le_level;
1083                                         le_goto_level(le_level);
1084                                         d = 1;
1085                                         break;
1086                                       case SDLK_n:
1087                                         d = 1;
1088                                         break;
1089                                       default:
1090                                         break;
1091                                       }
1092                                     break;
1093                                   default:
1094                                     break;
1095                                   }
1096                               SDL_Delay(50);
1097                             }
1098                         }
1099                     }
1100                   button_event(&le_previous_level_bt,&event);
1101                   if(button_get_state(&le_previous_level_bt) == BUTTON_CLICKED)
1102                     {
1103                       if(le_level > 1)
1104                         le_goto_level(--le_level);
1105                     }
1106                   button_event(&le_rubber_bt,&event);
1107                   if(button_get_state(&le_rubber_bt) == BUTTON_CLICKED)
1108                     le_current_tile = '.';
1109                   button_event(&le_select_mode_one_bt,&event);
1110                   if(button_get_state(&le_select_mode_one_bt) == BUTTON_CLICKED)
1111                     le_selection_mode = CURSOR;
1112                   button_event(&le_select_mode_two_bt,&event);
1113                   if(button_get_state(&le_select_mode_two_bt) == BUTTON_CLICKED)
1114                     le_selection_mode = SQUARE;
1115
1116                   button_event(&le_bad_bt,&event);
1117                   if(button_get_state(&le_bad_bt) == BUTTON_CLICKED)
1118                     {
1119                       le_bad_panel.hidden = false;
1120                       le_fgd_panel.hidden = true;
1121                       le_bkgd_panel.hidden = true;
1122                     }
1123
1124                   button_event(&le_fgd_bt,&event);
1125                   if(button_get_state(&le_fgd_bt) == BUTTON_CLICKED)
1126                     {
1127                       le_bad_panel.hidden = true;
1128                       le_fgd_panel.hidden = false;
1129                       le_bkgd_panel.hidden = true;
1130                     }
1131                   button_event(&le_bkgd_bt,&event);
1132                   if(button_get_state(&le_bkgd_bt) == BUTTON_CLICKED)
1133                     {
1134                       le_bad_panel.hidden = true;
1135                       le_fgd_panel.hidden = true;
1136                       le_bkgd_panel.hidden = false;
1137                     }
1138                   button_event(&le_settings_bt,&event);
1139                   if(button_get_state(&le_settings_bt) == BUTTON_CLICKED)
1140                     {
1141                       if(show_menu == false)
1142                         {
1143                           update_level_settings_menu();
1144                           Menu::set_current(level_settings_menu);
1145                           show_menu = true;
1146                         }
1147                       else
1148                         {
1149                           Menu::set_current(leveleditor_menu);
1150                           show_menu = false;
1151                         }
1152                     }
1153                   if((pbutton = button_panel_event(&le_bkgd_panel,&event)) != NULL)
1154                     {
1155                       if(button_get_state(pbutton) == BUTTON_CLICKED)
1156                         {
1157                           char c = '\0';
1158                           if(pbutton->tag >= 0 && pbutton->tag <= 3)
1159                             c = 'G' + pbutton->tag;
1160                           else if(pbutton->tag >= 4 && pbutton->tag <= 7)
1161                             c = 'g' + pbutton->tag - 4;
1162                           else if(pbutton->tag >= 8 && pbutton->tag <= 11)
1163                             c = 'C' + pbutton->tag - 8;
1164                           else if(pbutton->tag >= 12 && pbutton->tag <= 15)
1165                             c = 'c' + pbutton->tag - 12;
1166                           if(c != '\0')
1167                             le_current_tile = c;
1168                         }
1169                     }
1170                   if((pbutton = button_panel_event(&le_fgd_panel,&event)) != NULL)
1171                     {
1172                       if(button_get_state(pbutton) == BUTTON_CLICKED)
1173                         {
1174                           char c = '\0';
1175                           if(pbutton->tag == 0)
1176                             c = '#' ;
1177                           else if(pbutton->tag == 1)
1178                             c = '[';
1179                           else if(pbutton->tag == 2)
1180                             c = '=';
1181                           else if(pbutton->tag == 3)
1182                             c = ']';
1183                           else if(pbutton->tag == 4)
1184                             c = '^';
1185                           else if(pbutton->tag == 5)
1186                             c = '&';
1187                           else if(pbutton->tag == 6)
1188                             c = '|';
1189                           else if(pbutton->tag == 7)
1190                             c = '*';
1191                           else if(pbutton->tag == 8)
1192                             c = '\\';
1193                           else if(pbutton->tag == 9)
1194                             c = 'a';
1195                           else if(pbutton->tag == 10)
1196                             c = 'B';
1197                           else if(pbutton->tag == 11)
1198                             c = 'A';
1199                           else if(pbutton->tag == 12)
1200                             c = '!';
1201                           else if(pbutton->tag == 13)
1202                             c = '$';
1203                           else if(pbutton->tag == 14)
1204                             c = 'X';
1205                           else if(pbutton->tag == 15)
1206                             c = 'Y';
1207                           else if(pbutton->tag == 16)
1208                             c = 'x';
1209                           else if(pbutton->tag == 17)
1210                             c = 'y';
1211                           if(c != '\0')
1212                             le_current_tile = c;
1213                         }
1214                     }
1215                   if((pbutton = button_panel_event(&le_bad_panel,&event)) != NULL)
1216                     {
1217                       if(button_get_state(pbutton) == BUTTON_CLICKED)
1218                         {
1219                           char c = '\0';
1220                           if(pbutton->tag >= 0 && pbutton->tag <= 2)
1221                             c = '0' + pbutton->tag;
1222                           if(c != '\0')
1223                             le_current_tile = c;
1224                         }
1225                     }
1226                 }
1227               else
1228                 {
1229                   button_event(&le_settings_bt,&event);
1230                   if(button_get_state(&le_settings_bt) == BUTTON_CLICKED)
1231                     {
1232                       if(show_menu == false)
1233                         {
1234                           update_level_settings_menu();
1235                           Menu::set_current(level_settings_menu);
1236                           show_menu = true;
1237                         }
1238                       else
1239                         {
1240                           Menu::set_current(leveleditor_menu);
1241                           show_menu = false;
1242                         }
1243                     }
1244                 }
1245             }
1246           if(show_menu == false)
1247             {
1248               button_event(&le_move_left_bt,&event);
1249               button_event(&le_move_right_bt,&event);
1250
1251               if(le_mouse_pressed[LEFT])
1252                 {
1253                   le_change(cursor_x, cursor_y, le_current_tile);
1254                 }
1255             }
1256         }
1257     }
1258   if(show_menu == false)
1259     {
1260       if(button_get_state(&le_move_left_bt) == BUTTON_PRESSED)
1261         {
1262           pos_x -= 192;
1263         }
1264       else if(button_get_state(&le_move_left_bt) == BUTTON_HOVER)
1265         {
1266           pos_x -= 96;
1267         }
1268
1269       if(button_get_state(&le_move_right_bt) == BUTTON_PRESSED)
1270         {
1271           pos_x += 192;
1272         }
1273       else if(button_get_state(&le_move_right_bt) == BUTTON_HOVER)
1274         {
1275           pos_x += 96;
1276         }
1277     }
1278
1279 }
1280
1281 void le_highlight_selection()
1282 {
1283   int x1, x2, y1, y2;
1284
1285   if(selection.x1 < selection.x2)
1286     {
1287       x1 = selection.x1;
1288       x2 = selection.x2;
1289     }
1290   else
1291     {
1292       x1 = selection.x2;
1293       x2 = selection.x1;
1294     }
1295   if(selection.y1 < selection.y2)
1296     {
1297       y1 = selection.y1;
1298       y2 = selection.y2;
1299     }
1300   else
1301     {
1302       y1 = selection.y2;
1303       y2 = selection.y1;
1304     }
1305
1306   x1 /= 32;
1307   x2 /= 32;
1308   y1 /= 32;
1309   y2 /= 32;
1310
1311   fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103);
1312 }
1313
1314 void le_change(float x, float y, unsigned char c)
1315 {
1316   if(le_current_level != NULL)
1317     {
1318       int xx,yy;
1319       int x1, x2, y1, y2;
1320       unsigned int i;
1321
1322       /*  level_changed = true; */
1323
1324       switch(le_selection_mode)
1325         {
1326         case CURSOR:
1327           level_change(le_current_level,x,y,c);
1328
1329           yy = ((int)y / 32);
1330           xx = ((int)x / 32);
1331
1332           /* if there is a bad guy over there, remove it */
1333           for(i = 0; i < bad_guys.size(); ++i)
1334               if(xx == bad_guys[i].base.x/32 && yy == bad_guys[i].base.y/32)
1335                   bad_guys.erase(static_cast<std::vector<BadGuy>::iterator>(&bad_guys[i]));
1336
1337           if(c == '0')  /* if it's a bad guy */
1338             add_bad_guy(xx*32, yy*32, BAD_BSOD);
1339           else if(c == '1')
1340             add_bad_guy(xx*32, yy*32, BAD_LAPTOP);
1341           else if(c == '2')
1342             add_bad_guy(xx*32, yy*32, BAD_MONEY);
1343
1344           break;
1345         case SQUARE:
1346           if(selection.x1 < selection.x2)
1347             {
1348               x1 = selection.x1;
1349               x2 = selection.x2;
1350             }
1351           else
1352             {
1353               x1 = selection.x2;
1354               x2 = selection.x1;
1355             }
1356           if(selection.y1 < selection.y2)
1357             {
1358               y1 = selection.y1;
1359               y2 = selection.y2;
1360             }
1361           else
1362             {
1363               y1 = selection.y2;
1364               y2 = selection.y1;
1365             }
1366
1367           x1 /= 32;
1368           x2 /= 32;
1369           y1 /= 32;
1370           y2 /= 32;
1371
1372           /* if there is a bad guy over there, remove it */
1373           for(i = 0; i < bad_guys.size(); ++i)
1374               if(bad_guys[i].base.x/32 >= x1 && bad_guys[i].base.x/32 <= x2
1375                   && bad_guys[i].base.y/32 >= y1 && bad_guys[i].base.y/32 <= y2)
1376                   bad_guys.erase(static_cast<std::vector<BadGuy>::iterator>(&bad_guys[i]));
1377
1378           for(xx = x1; xx <= x2; xx++)
1379             for(yy = y1; yy <= y2; yy++)
1380               {
1381                 level_change(le_current_level, xx*32, yy*32, c);
1382
1383                 if(c == '0')  // if it's a bad guy
1384                   add_bad_guy(xx*32, yy*32, BAD_BSOD);
1385                 else if(c == '1')
1386                   add_bad_guy(xx*32, yy*32, BAD_LAPTOP);
1387                 else if(c == '2')
1388                   add_bad_guy(xx*32, yy*32, BAD_MONEY);
1389               }
1390           break;
1391         default:
1392           break;
1393         }
1394     }
1395 }
1396
1397 void le_testlevel()
1398 {
1399   level_save(le_current_level,"test",le_level);
1400   gameloop("test",le_level, ST_GL_TEST);
1401   Menu::set_current(leveleditor_menu);
1402   arrays_init();
1403   level_load_gfx(le_current_level);
1404   loadshared();
1405   le_activate_bad_guys();
1406 }
1407
1408 void le_showhelp()
1409 {
1410   SDL_Event event;
1411   unsigned int i, done;
1412   char *text[] = {
1413                    "  - This is SuperTux's built-in level editor -",
1414                    "It has been designed to be light and easy to use from the start.",
1415                    "",
1416                    "When you first load the level editor you are given a menu where you",
1417                    "can load level subsets, create a new level subset, edit the current",
1418                    "subset's settings, or simply quit the editor. You can access this menu",
1419                    "from the level editor at any time by pressing the escape key.",
1420                    "",
1421                    "To your right is your button bar. The center of this contains many",
1422                    "tiles you can use to make your level. To select a tile, click on it",
1423                    "with your left mouse button; your selection will be shown in the",
1424                    "bottom right corner of the button box. Click anywhere on your level",
1425                    "with the left mouse button to place that tile down. If you right click",
1426                    "a tile in the button bar, you can find out what its keyboard shortcut",
1427                    "is. The three buttons FGD, BGD and EMY let you pick from foreground,",
1428                    "background, and enemy tiles. The eraser lets you remove tiles.",
1429                    "The left and right arrow keys scroll back and forth through your level.",
1430                    "The button with the wrench and screwdriver, lets you change the",
1431                    "settings of your level, including how long it is or what music it will",
1432                    "play. When you are ready to give your level a test, click on the little",
1433                    "running Tux. If you like the changes you have made to your level,",
1434                                    "press the red save key to keep them.",
1435                    "To change which level in your subset you are editing, press the white",
1436                    "up and down arrow keys at the top of the button box.",
1437                                    "",
1438                    "Have fun making levels! If you make some good ones, send them to us on",
1439                                    "the SuperTux mailing list!",
1440                    "- SuperTux team"
1441                  };
1442
1443
1444   text_drawf(&blue_text, "- Help -", 0, 30, A_HMIDDLE, A_TOP, 2);
1445
1446   for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1447     text_draw(&white_small_text, text[i], 5, 80+(i*12), 1);
1448
1449   text_drawf(&gold_text, "Press Any Key to Continue", 0, 440, A_HMIDDLE, A_TOP, 1);
1450
1451   flipscreen();
1452
1453   done = 0;
1454
1455   while(done == 0)
1456     {
1457       while(SDL_PollEvent(&event))
1458         switch(event.type)
1459           {
1460           case SDL_MOUSEBUTTONDOWN:             // mouse pressed
1461           case SDL_KEYDOWN:             // key pressed
1462             done = 1;
1463             break;
1464           default:
1465             break;
1466           }
1467       SDL_Delay(50);
1468     }
1469 }