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