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