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