level-editor cleanups.
[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       printf("%s\n",filename);
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   if((i = string_list_find(level_settings_menu.item[3].list,le_current_level->theme)) != -1)
610     level_settings_menu.item[3].list->active_item = i;
611   if((i = string_list_find(level_settings_menu.item[4].list,le_current_level->song_title)) != -1)
612     level_settings_menu.item[4].list->active_item = i;
613   if((i = string_list_find(level_settings_menu.item[5].list,le_current_level->bkgd_image)) != -1)
614     level_settings_menu.item[5].list->active_item = i;
615
616   menu_item_change_input(&level_settings_menu.item[6], str);
617   sprintf(str,"%d",le_current_level->time_left);
618   menu_item_change_input(&level_settings_menu.item[7], str);
619   sprintf(str,"%2.0f",le_current_level->gravity);
620   menu_item_change_input(&level_settings_menu.item[8], str);
621   sprintf(str,"%d",le_current_level->bkgd_red);
622   menu_item_change_input(&level_settings_menu.item[9], str);
623   sprintf(str,"%d",le_current_level->bkgd_green);
624   menu_item_change_input(&level_settings_menu.item[10], str);
625   sprintf(str,"%d",le_current_level->bkgd_blue);
626   menu_item_change_input(&level_settings_menu.item[11], str);
627 }
628
629 void update_subset_settings_menu()
630 {
631   menu_item_change_input(&subset_settings_menu.item[2], le_level_subset.title);
632   menu_item_change_input(&subset_settings_menu.item[3], le_level_subset.description);
633 }
634
635 void apply_level_settings_menu()
636 {
637   int i,y,j;
638   i = NO;
639
640   strcpy(le_current_level->name,level_settings_menu.item[2].input);
641
642   if(strcmp(le_current_level->bkgd_image,string_list_active(level_settings_menu.item[5].list)) != 0)
643     {
644       strcpy(le_current_level->bkgd_image,string_list_active(level_settings_menu.item[5].list));
645       i = YES;
646     }
647
648   if(strcmp(le_current_level->theme,string_list_active(level_settings_menu.item[3].list)) != 0)
649     {
650       strcpy(le_current_level->theme,string_list_active(level_settings_menu.item[3].list));
651       le_update_buttons(le_current_level->theme);
652       i = YES;
653     }
654
655   if(i == YES)
656     {
657       level_free_gfx();
658       level_load_gfx(le_current_level);
659     }
660
661   strcpy(le_current_level->song_title,string_list_active(level_settings_menu.item[4].list));
662
663   i = le_current_level->width;
664   le_current_level->width = atoi(level_settings_menu.item[6].input);
665   if(le_current_level->width < i)
666     {
667       if(le_current_level->width < 21)
668         le_current_level->width = 21;
669       for(y = 0; y < 15; ++y)
670         {
671           le_current_level->tiles[y] = (unsigned char*) realloc(le_current_level->tiles[y],(le_current_level->width+1)*sizeof(unsigned char));
672           le_current_level->tiles[y][le_current_level->width] = (unsigned char) '\0';
673         }
674     }
675   else if(le_current_level->width > i)
676     {
677       for(y = 0; y < 15; ++y)
678         {
679           le_current_level->tiles[y] = (unsigned char*) realloc(le_current_level->tiles[y],(le_current_level->width+1)*sizeof(unsigned char));
680           for(j = 0; j < le_current_level->width - i; ++j)
681             le_current_level->tiles[y][i+j] = (unsigned char) '.';
682           le_current_level->tiles[y][le_current_level->width] = (unsigned char) '\0';
683         }
684     }
685   le_current_level->time_left = atoi(level_settings_menu.item[7].input);
686   le_current_level->gravity = atof(level_settings_menu.item[8].input);
687   le_current_level->bkgd_red = atoi(level_settings_menu.item[9].input);
688   le_current_level->bkgd_green = atoi(level_settings_menu.item[10].input);
689   le_current_level->bkgd_blue = atoi(level_settings_menu.item[11].input);
690 }
691
692 void save_subset_settings_menu()
693 {
694   free(le_level_subset.title);
695   le_level_subset.title = (char*) malloc(sizeof(char)*(strlen(subset_settings_menu.item[2].input)+1));
696   strcpy(le_level_subset.title,subset_settings_menu.item[2].input);
697   free(le_level_subset.description);
698   le_level_subset.description = (char*) malloc(sizeof(char)*(strlen(subset_settings_menu.item[3].input)+1));
699   strcpy(le_level_subset.description,subset_settings_menu.item[3].input);
700   subset_save(&le_level_subset);
701 }
702
703 void le_goto_level(int levelnb)
704 {
705   arrays_free();
706   arrays_init();
707
708   level_free(le_current_level);
709   if(level_load(le_current_level, le_level_subset.name, levelnb) != 0)
710     {
711       level_load(le_current_level, le_level_subset.name, le_level);
712     }
713   else
714     {
715       le_level = levelnb;
716     }
717
718   le_set_defaults();
719
720   le_update_buttons(le_current_level->theme);
721
722   level_free_gfx();
723   level_load_gfx(le_current_level);
724
725   le_activate_bad_guys();
726 }
727
728 void le_quit(void)
729 {
730   /*if(level_changed == YES)
731     if(askforsaving() == CANCEL)
732       return;*/ //FIXME
733
734   SDL_EnableKeyRepeat(0, 0);    // disables key repeating
735
736   texture_free(&le_selection);
737   menu_free(&leveleditor_menu);
738   menu_free(&subset_load_menu);
739   menu_free(&subset_new_menu);
740   menu_free(&subset_settings_menu);
741   menu_free(&level_settings_menu);
742   button_panel_free(&le_bkgd_panel);
743   button_panel_free(&le_fgd_panel);
744   button_panel_free(&le_bad_panel);
745   button_free(&le_save_level_bt);
746   button_free(&le_test_level_bt);
747   button_free(&le_next_level_bt);
748   button_free(&le_previous_level_bt);
749   button_free(&le_move_right_bt);
750   button_free(&le_move_left_bt);
751   button_free(&le_rubber_bt);
752   button_free(&le_select_mode_one_bt);
753   button_free(&le_select_mode_two_bt);
754   button_free(&le_settings_bt);
755   button_free(&le_bad_bt);
756   button_free(&le_bkgd_bt);
757   button_free(&le_fgd_bt);
758
759   if(le_current_level != NULL)
760     {
761       level_free_gfx();
762       level_free(le_current_level);
763       unloadshared();
764       arrays_free();
765     }
766 }
767
768 void le_drawinterface()
769 {
770   int x,y;
771   char str[80];
772
773   if(le_current_level != NULL)
774     {
775       /* draw a grid (if selected) */
776       if(le_show_grid)
777         {
778           for(x = 0; x < 19; x++)
779             fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255);
780           for(y = 0; y < 15; y++)
781             fillrect(0, y*32, screen->w - 32, 1, 225, 225, 225,255);
782         }
783     }
784
785   if(le_selection_mode == CURSOR)
786     texture_draw(&le_selection, cursor_x - pos_x, cursor_y, NO_UPDATE);
787   else if(le_selection_mode == SQUARE)
788     {
789       int w, h;
790       le_highlight_selection();
791       /* draw current selection */
792       w = selection.x2 - selection.x1;
793       h = selection.y2 - selection.y1;
794       fillrect(selection.x1 - pos_x, selection.y1, w, SELECT_W, SELECT_CLR);
795       fillrect(selection.x1 - pos_x + w, selection.y1, SELECT_W, h, SELECT_CLR);
796       fillrect(selection.x1 - pos_x, selection.y1 + h, w, SELECT_W, SELECT_CLR);
797       fillrect(selection.x1 - pos_x, selection.y1, SELECT_W, h, SELECT_CLR);
798     }
799
800
801   /* draw button bar */
802   fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255);
803   drawshape(19 * 32, 14 * 32, le_current_tile);
804   switch(le_current_tile)
805     {
806     case 'B':
807       texture_draw(&img_mints, 19 * 32, 14 * 32, NO_UPDATE);
808       break;
809     case '!':
810       texture_draw(&img_golden_herring,19 * 32, 14 * 32, NO_UPDATE);
811       break;
812     case 'x':
813     case 'y':
814     case 'A':
815       texture_draw(&img_distro[(le_frame / 5) % 4], 19 * 32, 14 * 32, NO_UPDATE);
816       break;
817     case '0':
818       texture_draw(&img_bsod_left[(le_frame / 5) % 4],19 * 32, 14 * 32, NO_UPDATE);
819       break;
820     case '1':
821       texture_draw(&img_laptop_left[(le_frame / 5) % 3],19 * 32, 14 * 32, NO_UPDATE);
822       break;
823     case '2':
824       texture_draw(&img_money_left[0],19 * 32, 14 * 32, NO_UPDATE);
825       break;
826     default:
827       break;
828     }
829
830   if(le_current_level != NULL)
831     {
832       button_draw(&le_save_level_bt);
833       button_draw(&le_test_level_bt);
834       button_draw(&le_next_level_bt);
835       button_draw(&le_previous_level_bt);
836       button_draw(&le_rubber_bt);
837       button_draw(&le_select_mode_one_bt);
838       button_draw(&le_select_mode_two_bt);
839       button_draw(&le_settings_bt);
840       button_draw(&le_move_right_bt);
841       button_draw(&le_move_left_bt);
842       button_draw(&le_bad_bt);
843       button_draw(&le_bkgd_bt);
844       button_draw(&le_fgd_bt);
845       button_panel_draw(&le_bkgd_panel);
846       button_panel_draw(&le_fgd_panel);
847       button_panel_draw(&le_bad_panel);
848
849       sprintf(str, "%d/%d", le_level,le_level_subset.levels);
850       text_drawf(&white_text, str, -8, 16, A_RIGHT, A_NONE, 1, NO_UPDATE);
851
852       text_draw(&white_small_text, "F1 for Help", 10, 430, 1, NO_UPDATE);
853     }
854   else
855     {
856       if(show_menu == NO)
857         text_draw(&white_small_text, "No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1, NO_UPDATE);
858       else
859         text_draw(&white_small_text, "No Level Subset loaded", 10, 430, 1, NO_UPDATE);
860     }
861
862 }
863
864 void le_drawlevel()
865 {
866   int y,x,i,s;
867   static char str[LEVEL_NAME_MAX];
868
869   /* Draw the real background */
870   if(le_current_level->bkgd_image[0] != '\0')
871     {
872       s = pos_x / 30;
873       texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s - 32, img_bkgd.h, NO_UPDATE);
874       texture_draw_part(&img_bkgd,0,0,screen->w - s - 32 ,0,s,img_bkgd.h, NO_UPDATE);
875     }
876   else
877     {
878       clearscreen(le_current_level->bkgd_red, le_current_level->bkgd_green, le_current_level->bkgd_blue);
879     }
880
881   /*       clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */
882
883   for (y = 0; y < 15; ++y)
884     for (x = 0; x < 20; ++x)
885       {
886         drawshape(x * 32 - ((int)pos_x % 32), y * 32, le_current_level->tiles[y][x + (int)(pos_x / 32)]);
887
888         /* draw whats inside stuff when cursor is selecting those */
889         /* (draw them all the time - is this the right behaviour?) */
890         switch(le_current_level->tiles[y][x + (int)(pos_x/32)])
891           {
892           case 'B':
893             texture_draw(&img_mints, x * 32 - ((int)pos_x % 32), y*32, NO_UPDATE);
894             break;
895           case '!':
896             texture_draw(&img_golden_herring, x * 32 - ((int)pos_x % 32), y*32, NO_UPDATE);
897             break;
898           case 'x':
899           case 'y':
900           case 'A':
901             texture_draw(&img_distro[(frame / 5) % 4], x * 32 - ((int)pos_x % 32), y*32, NO_UPDATE);
902             break;
903           default:
904             break;
905           }
906       }
907
908   /* Draw the Bad guys: */
909   for (i = 0; i < num_bad_guys; ++i)
910     {
911       if(bad_guys[i].base.alive == NO)
912         continue;
913       /* to support frames: img_bsod_left[(frame / 5) % 4] */
914       if(bad_guys[i].kind == BAD_BSOD)
915         texture_draw(&img_bsod_left[(le_frame / 5) % 4], bad_guys[i].base.x - pos_x, bad_guys[i].base.y, NO_UPDATE);
916       else if(bad_guys[i].kind == BAD_LAPTOP)
917         texture_draw(&img_laptop_left[(le_frame / 5) % 3], bad_guys[i].base.x - pos_x, bad_guys[i].base.y, NO_UPDATE);
918       else if (bad_guys[i].kind == BAD_MONEY)
919         texture_draw(&img_money_left[(le_frame / 5) % 2], bad_guys[i].base.x - pos_x, bad_guys[i].base.y, NO_UPDATE);
920     }
921
922
923   /* Draw the player: */
924   /* for now, the position is fixed at (0, 240) */
925   texture_draw(&tux_right[(frame / 5) % 3], 0 - pos_x, 240, NO_UPDATE);
926 }
927
928 void le_checkevents()
929 {
930   SDLKey key;
931   SDLMod keymod;
932   button_type* pbutton;
933   int x,y;
934
935   keymod = SDL_GetModState();
936
937   while(SDL_PollEvent(&event))
938     {
939       /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/
940       if(event.type == SDL_KEYDOWN || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION) && (event.motion.x > 0 && event.motion.x < screen->w - 64 &&
941                                        event.motion.y > 0 && event.motion.y < screen->h)))
942         {
943
944           switch(event.type)
945             {
946             case SDL_KEYDOWN:   // key pressed
947               key = event.key.keysym.sym;
948               if(show_menu)
949                 {
950                   menu_event(&event.key.keysym);
951                   if(key == SDLK_ESCAPE)
952                     {
953                       show_menu = NO;
954                       menu_set_current(&leveleditor_menu);
955                     }
956                   break;
957                 }
958               switch(key)
959                 {
960                 case SDLK_ESCAPE:
961                   if(!show_menu)
962                     show_menu = YES;
963                   else
964                     show_menu = NO;
965                   break;
966                 case SDLK_LEFT:
967                   if(fire == DOWN)
968                     cursor_x -= KEY_CURSOR_SPEED;
969                   else
970                     cursor_x -= KEY_CURSOR_FASTSPEED;
971
972                   if(cursor_x < pos_x + MOUSE_LEFT_MARGIN)
973                     pos_x = cursor_x - MOUSE_LEFT_MARGIN;
974
975                   break;
976                 case SDLK_RIGHT:
977                   if(fire == DOWN)
978                     cursor_x += KEY_CURSOR_SPEED;
979                   else
980                     cursor_x += KEY_CURSOR_FASTSPEED;
981
982                   if(cursor_x > pos_x + MOUSE_RIGHT_MARGIN-32)
983                     pos_x = cursor_x - MOUSE_RIGHT_MARGIN+32;
984
985                   break;
986                 case SDLK_UP:
987                   if(fire == DOWN)
988                     cursor_y -= KEY_CURSOR_SPEED;
989                   else
990                     cursor_y -= KEY_CURSOR_FASTSPEED;
991
992                   if(cursor_y < 0)
993                     cursor_y = 0;
994                   break;
995                 case SDLK_DOWN:
996                   if(fire == DOWN)
997                     cursor_y += KEY_CURSOR_SPEED;
998                   else
999                     cursor_y += KEY_CURSOR_FASTSPEED;
1000
1001                   if(cursor_y > screen->h-32)
1002                     cursor_y = screen->h-32;
1003                   break;
1004                 case SDLK_LCTRL:
1005                   fire =UP;
1006                   break;
1007                 case SDLK_F1:
1008                   le_showhelp();
1009                   break;
1010                 case SDLK_HOME:
1011                   cursor_x = 0;
1012                   pos_x = cursor_x;
1013                   break;
1014                 case SDLK_END:
1015                   cursor_x = (le_current_level->width * 32) - 32;
1016                   pos_x = cursor_x;
1017                   break;
1018                 case SDLK_F9:
1019                   le_show_grid = !le_show_grid;
1020                   break;
1021                 default:
1022                   break;
1023                 }
1024               break;
1025             case SDL_KEYUP:     /* key released */
1026               switch(event.key.keysym.sym)
1027                 {
1028                 case SDLK_LCTRL:
1029                   fire = DOWN;
1030                   break;
1031                 default:
1032                   break;
1033                 }
1034               break;
1035             case SDL_MOUSEBUTTONDOWN:
1036               if(event.button.button == SDL_BUTTON_LEFT)
1037                 {
1038                   le_mouse_pressed[LEFT] = YES;
1039
1040                   selection.x1 = event.motion.x + pos_x;
1041                   selection.y1 = event.motion.y;
1042                   selection.x2 = event.motion.x + pos_x;
1043                   selection.y2 = event.motion.y;
1044                 }
1045               else if(event.button.button == SDL_BUTTON_RIGHT)
1046                 le_mouse_pressed[RIGHT] = YES;
1047               break;
1048             case SDL_MOUSEBUTTONUP:
1049               if(event.button.button == SDL_BUTTON_LEFT)
1050                 le_mouse_pressed[LEFT] = NO;
1051               else if(event.button.button == SDL_BUTTON_RIGHT)
1052                 le_mouse_pressed[RIGHT] = NO;
1053               break;
1054             case SDL_MOUSEMOTION:
1055               if(!show_menu)
1056                 {
1057                   x = event.motion.x;
1058                   y = event.motion.y;
1059
1060                   cursor_x = ((int)(pos_x + x) / 32) * 32;
1061                   cursor_y = ((int) y / 32) * 32;
1062
1063                   if(le_mouse_pressed[LEFT] == YES)
1064                     {
1065                       selection.x2 = x + pos_x;
1066                       selection.y2 = y;
1067                     }
1068
1069                   if(le_mouse_pressed[RIGHT] == YES)
1070                     {
1071                       fprintf(stderr, "mouse scrolling\n");
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                    "X/x - Brick0",
1461                    "Y/y - Brick1",
1462                    "A/B/! - Box full",
1463                    "a - Box empty",
1464                    "C-F - Cloud0",
1465                    "c-f - Cloud1",
1466                    "G-J - Bkgd0",
1467                    "g-j - Bkgd1",
1468                    "# - Solid0",
1469                    "[ - Solid1",
1470                    "= - Solid2",
1471                    "] - Solid3",
1472                    "$ - Distro",
1473                    "^ - Waves",
1474                    "* - Poletop",
1475                    "| - Pole",
1476                    "\\ - Flag",
1477                    "& - Water",
1478                    "0-2 - BadGuys",
1479                    "./Del - Remove tile",
1480                    "F9 - Show/Hide Grid",
1481                    "F3 - Change Selection Mode",
1482                    "Esc - Menu"};
1483
1484
1485   text_drawf(&blue_text, "- Help -", 0, 30, A_HMIDDLE, A_TOP, 2, NO_UPDATE);
1486
1487   for(i = 0; i < sizeof(text)/sizeof(char *); i++)
1488     text_draw(&white_text, text[i], 40, 90+(i*16), 1, NO_UPDATE);
1489
1490   text_drawf(&gold_text, "Press Any Key to Continue", 0, 460, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1491
1492   flipscreen();
1493
1494   done = 0;
1495
1496   while(done == 0)
1497     {
1498       while(SDL_PollEvent(&event))
1499         switch(event.type)
1500           {
1501           case SDL_MOUSEBUTTONDOWN:             // mouse pressed
1502           case SDL_KEYDOWN:             // key pressed
1503             done = 1;
1504             break;
1505           default:
1506             break;
1507           }
1508       SDL_Delay(50);
1509     }
1510 }