rnd-19990107-2
[rocksndiamonds.git] / src / editor.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  (c) 1995-98 Artsoft Entertainment                       *
5 *              Holger Schemel                              *
6 *              Oststrasse 11a                              *
7 *              33604 Bielefeld                             *
8 *              phone: ++49 +521 290471                     *
9 *              email: aeglos@valinor.owl.de                *
10 *----------------------------------------------------------*
11 *  editor.c                                                *
12 ***********************************************************/
13
14 #include "editor.h"
15 #include "screens.h"
16 #include "tools.h"
17 #include "misc.h"
18 #include "buttons.h"
19 #include "files.h"
20 #include "game.h"
21 #include "tape.h"
22
23 /* positions in the level editor */
24 #define ED_WIN_MB_LEFT_XPOS     7
25 #define ED_WIN_MB_LEFT_YPOS     6
26 #define ED_WIN_LEVELNR_XPOS     77
27 #define ED_WIN_LEVELNR_YPOS     7
28 #define ED_WIN_MB_MIDDLE_XPOS   7
29 #define ED_WIN_MB_MIDDLE_YPOS   258
30 #define ED_WIN_MB_RIGHT_XPOS    77
31 #define ED_WIN_MB_RIGHT_YPOS    258
32
33 /* other constants for the editor */
34 #define ED_SCROLL_NO            0
35 #define ED_SCROLL_LEFT          1
36 #define ED_SCROLL_RIGHT         2
37 #define ED_SCROLL_UP            4
38 #define ED_SCROLL_DOWN          8
39
40 /* screens in the level editor */
41 #define ED_MODE_DRAWING         0
42 #define ED_MODE_INFO            1
43 #define ED_MODE_PROPERTIES      2
44
45 /* how many steps can be cancelled */
46 #define NUM_UNDO_STEPS          (10 + 1)
47
48 /* values for random placement */
49 #define RANDOM_USE_PERCENTAGE   0
50 #define RANDOM_USE_NUM_OBJECTS  1
51
52 /* values for elements with content */
53 #define MAX_ELEMCONT            8
54
55 /* values for the control window */
56 #define ED_CTRL_BUTTONS_GFX_YPOS        236
57 #define ED_CTRL_BUTTONS_ALT_GFX_YPOS    142
58
59 #define ED_CTRL1_BUTTONS_HORIZ  4
60 #define ED_CTRL1_BUTTONS_VERT   4
61 #define ED_CTRL1_BUTTON_XSIZE   22
62 #define ED_CTRL1_BUTTON_YSIZE   22
63 #define ED_CTRL1_BUTTONS_XPOS   6
64 #define ED_CTRL1_BUTTONS_YPOS   6
65 #define ED_CTRL2_BUTTONS_HORIZ  3
66 #define ED_CTRL2_BUTTONS_VERT   2
67 #define ED_CTRL2_BUTTON_XSIZE   30
68 #define ED_CTRL2_BUTTON_YSIZE   20
69 #define ED_CTRL2_BUTTONS_XPOS   5
70 #define ED_CTRL2_BUTTONS_YPOS   100
71 #define ED_NUM_CTRL1_BUTTONS   (ED_CTRL1_BUTTONS_HORIZ * ED_CTRL1_BUTTONS_VERT)
72 #define ED_NUM_CTRL2_BUTTONS   (ED_CTRL2_BUTTONS_HORIZ * ED_CTRL2_BUTTONS_VERT)
73 #define ED_NUM_CTRL_BUTTONS    (ED_NUM_CTRL1_BUTTONS + ED_NUM_CTRL2_BUTTONS)
74
75 /* values for properties window */
76 #define ED_PROPERTIES_XPOS      (TILEX - MINI_TILEX/2)
77 /* values for counter gadgets */
78 #define ED_COUNT_VALUE_XOFFSET  5
79 #define ED_COUNT_VALUE_YOFFSET  3
80 #define ED_COUNT_SCORE_XPOS     ED_PROPERTIES_XPOS
81 #define ED_COUNT_SCORE_YPOS     (14 * MINI_TILEY)
82 #define ED_COUNT_ELEMCONT_XPOS  ED_PROPERTIES_XPOS
83 #define ED_COUNT_ELEMCONT_YPOS  (17 * MINI_TILEY)
84
85 /* values for element content drawing areas */
86 #define ED_AREA_ELEMCONT_XPOS   (TILEX)
87 #define ED_AREA_ELEMCONT_YPOS   (10 * TILEY)
88
89 /* control button identifiers */
90 #define ED_CTRL_ID_SINGLE_ITEMS         0
91 #define ED_CTRL_ID_CONNECTED_ITEMS      1
92 #define ED_CTRL_ID_LINE                 2
93 #define ED_CTRL_ID_TEXT                 3
94 #define ED_CTRL_ID_RECTANGLE            4
95 #define ED_CTRL_ID_FILLED_BOX           5
96 #define ED_CTRL_ID_WRAP_UP              6
97 #define ED_CTRL_ID_PROPERTIES           7
98 #define ED_CTRL_ID_FLOOD_FILL           8
99 #define ED_CTRL_ID_WRAP_LEFT            9
100 #define ED_CTRL_ID_UNUSED1              10
101 #define ED_CTRL_ID_WRAP_RIGHT           11
102 #define ED_CTRL_ID_RANDOM_PLACEMENT     12
103 #define ED_CTRL_ID_BRUSH                13
104 #define ED_CTRL_ID_WRAP_DOWN            14
105 #define ED_CTRL_ID_PICK_ELEMENT         15
106 #define ED_CTRL_ID_UNDO                 16
107 #define ED_CTRL_ID_INFO                 17
108 #define ED_CTRL_ID_SAVE                 18
109 #define ED_CTRL_ID_CLEAR                19
110 #define ED_CTRL_ID_TEST                 20
111 #define ED_CTRL_ID_EXIT                 21
112
113 /* counter button identifiers */
114 #define ED_CTRL_ID_SCORE_DOWN           22
115 #define ED_CTRL_ID_SCORE_UP             23
116 #define ED_CTRL_ID_ELEMCONT_DOWN        24
117 #define ED_CTRL_ID_ELEMCONT_UP          25
118
119 /* drawing area identifiers */
120 #define ED_CTRL_ID_DRAWING_LEVEL        26
121 #define ED_CTRL_ID_ELEMCONT_0           27
122 #define ED_CTRL_ID_ELEMCONT_7           34
123 #define ED_CTRL_ID_AMOEBA_CONTENT       35
124
125 /* text input identifiers */
126 #define ED_CTRL_ID_LEVEL_NAME           36
127
128 #define ED_NUM_GADGETS                  37
129
130 /* values for counter gadgets */
131 #define ED_COUNTER_SCORE                0
132 #define ED_COUNTER_ELEMCONT             1
133
134 #define ED_NUM_COUNTERS                 2
135
136 static struct
137 {
138   int x, y;
139   int gadget_id;
140 } counter_info[ED_NUM_COUNTERS] =
141 {
142   { ED_COUNT_SCORE_XPOS,        ED_COUNT_SCORE_YPOS,
143     ED_CTRL_ID_SCORE_DOWN },
144   { ED_COUNT_ELEMCONT_XPOS,     ED_COUNT_ELEMCONT_YPOS,
145     ED_CTRL_ID_ELEMCONT_DOWN }
146 };
147
148 /* forward declaration for internal use */
149 static void DrawDrawingWindow();
150 static void DrawPropertiesWindow();
151 static void CopyLevelToUndoBuffer();
152 static void HandleControlButtons(struct GadgetInfo *);
153 static void HandleCounterButtons(struct GadgetInfo *);
154 static void HandleDrawingAreas(struct GadgetInfo *);
155 static void HandleTextInputGadgets(struct GadgetInfo *);
156
157 static struct GadgetInfo *level_editor_gadget[ED_NUM_GADGETS];
158 static boolean level_editor_gadgets_created = FALSE;
159
160 static int drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
161 static int last_drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
162 static int properties_element = 0;
163
164 static short ElementContent[MAX_ELEMCONT][3][3];
165 static short OrigBackup[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
166 static short UndoBuffer[NUM_UNDO_STEPS][MAX_LEV_FIELDX][MAX_LEV_FIELDY];
167 static int undo_buffer_position = 0;
168 static int undo_buffer_steps = 0;
169
170 static int random_placement_percentage = 10;
171 static int random_placement_num_objects = 10;
172 #if 0
173 static int random_placement_method = RANDOM_USE_PERCENTAGE;
174 #else
175 static int random_placement_method = RANDOM_USE_NUM_OBJECTS;
176 #endif
177
178 /* pointer to score value */
179 static int *gadget_score_value;
180 static int *gadget_areas_value;
181
182 static int level_xpos,level_ypos;
183 static int edit_mode;
184 static boolean name_typing;
185 static int new_element1 = EL_MAUERWERK;
186 static int new_element2 = EL_LEERRAUM;
187 static int new_element3 = EL_ERDREICH;
188
189 int element_shift = 0;
190
191 int editor_element[] =
192 {
193   EL_CHAR_A + ('B' - 'A'),
194   EL_CHAR_A + ('O' - 'A'),
195   EL_CHAR_A + ('U' - 'A'),
196   EL_CHAR_A + ('L' - 'A'),
197
198   EL_CHAR_MINUS,
199   EL_CHAR_A + ('D' - 'A'),
200   EL_CHAR_A + ('E' - 'A'),
201   EL_CHAR_A + ('R' - 'A'),
202
203   EL_CHAR_A + ('D' - 'A'),
204   EL_CHAR_A + ('A' - 'A'),
205   EL_CHAR_A + ('S' - 'A'),
206   EL_CHAR_A + ('H' - 'A'),
207
208   EL_SPIELFIGUR,
209   EL_LEERRAUM,
210   EL_ERDREICH,
211   EL_BETON,
212
213   EL_FELSBODEN,
214   EL_SIEB2_INAKTIV,
215   EL_AUSGANG_ZU,
216   EL_AUSGANG_AUF,
217
218   EL_EDELSTEIN_BD,
219   EL_BUTTERFLY_O,
220   EL_FIREFLY_O,
221   EL_FELSBROCKEN,
222
223   EL_BUTTERFLY_L,
224   EL_FIREFLY_L,
225   EL_BUTTERFLY_R,
226   EL_FIREFLY_R,
227
228   EL_AMOEBE_BD,
229   EL_BUTTERFLY_U,
230   EL_FIREFLY_U,
231   EL_LEERRAUM,
232
233   EL_CHAR_A + ('E' - 'A'),
234   EL_CHAR_A + ('M' - 'A'),
235   EL_CHAR_A + ('E' - 'A'),
236   EL_CHAR_MINUS,
237
238   EL_CHAR_A + ('R' - 'A'),
239   EL_CHAR_A + ('A' - 'A'),
240   EL_CHAR_A + ('L' - 'A'),
241   EL_CHAR_A + ('D' - 'A'),
242
243   EL_CHAR_A + ('M' - 'A'),
244   EL_CHAR_A + ('I' - 'A'),
245   EL_CHAR_A + ('N' - 'A'),
246   EL_CHAR_A + ('E' - 'A'),
247
248   EL_SPIELER1,
249   EL_SPIELER2,
250   EL_SPIELER3,
251   EL_SPIELER4,
252
253   EL_SPIELFIGUR,
254   EL_LEERRAUM,
255   EL_ERDREICH,
256   EL_FELSBROCKEN,
257
258   EL_BETON,
259   EL_MAUERWERK,
260   EL_FELSBODEN,
261   EL_SIEB_INAKTIV,
262
263   EL_EDELSTEIN,
264   EL_DIAMANT,
265   EL_KOKOSNUSS,
266   EL_BOMBE,
267
268   EL_ERZ_EDEL,
269   EL_ERZ_DIAM,
270   EL_MORAST_LEER,
271   EL_MORAST_VOLL,
272
273   EL_DYNAMIT_AUS,
274   EL_DYNAMIT,
275   EL_AUSGANG_ZU,
276   EL_AUSGANG_AUF,
277
278   EL_MAMPFER,
279   EL_KAEFER_O,
280   EL_FLIEGER_O,
281   EL_ROBOT,
282
283   EL_KAEFER_L,
284   EL_FLIEGER_L,
285   EL_KAEFER_R,
286   EL_FLIEGER_R,
287
288   EL_ABLENK_AUS,
289   EL_KAEFER_U,
290   EL_FLIEGER_U,
291   EL_UNSICHTBAR,
292
293   EL_BADEWANNE1,
294   EL_SALZSAEURE,
295   EL_BADEWANNE2,
296   EL_LEERRAUM,
297
298   EL_BADEWANNE3,
299   EL_BADEWANNE4,
300   EL_BADEWANNE5,
301   EL_LEERRAUM,
302
303   EL_TROPFEN,
304   EL_AMOEBE_TOT,
305   EL_AMOEBE_NASS,
306   EL_AMOEBE_NORM,
307
308   EL_SCHLUESSEL1,
309   EL_SCHLUESSEL2,
310   EL_SCHLUESSEL3,
311   EL_SCHLUESSEL4,
312
313   EL_PFORTE1,
314   EL_PFORTE2,
315   EL_PFORTE3,
316   EL_PFORTE4,
317
318   EL_PFORTE1X,
319   EL_PFORTE2X,
320   EL_PFORTE3X,
321   EL_PFORTE4X,
322
323   EL_CHAR_A + ('M' - 'A'),
324   EL_CHAR_A + ('O' - 'A'),
325   EL_CHAR_A + ('R' - 'A'),
326   EL_CHAR_A + ('E' - 'A'),
327
328   EL_PFEIL_L,
329   EL_PFEIL_R,
330   EL_PFEIL_O,
331   EL_PFEIL_U,
332
333   EL_AMOEBE_VOLL,
334   EL_EDELSTEIN_GELB,
335   EL_EDELSTEIN_ROT,
336   EL_EDELSTEIN_LILA,
337
338   EL_ERZ_EDEL_BD,
339   EL_ERZ_EDEL_GELB,
340   EL_ERZ_EDEL_ROT,
341   EL_ERZ_EDEL_LILA,
342
343   EL_LIFE,
344   EL_PACMAN_O,
345   EL_ZEIT_VOLL,
346   EL_ZEIT_LEER,
347
348   EL_PACMAN_L,
349   EL_MAMPFER2,
350   EL_PACMAN_R,
351   EL_MAUER_LEBT,
352
353   EL_LIFE_ASYNC,
354   EL_PACMAN_U,
355   EL_BIRNE_AUS,
356   EL_BIRNE_EIN,
357
358   EL_DYNABOMB_NR,
359   EL_DYNABOMB_SZ,
360   EL_DYNABOMB_XL,
361   EL_BADEWANNE,
362
363   EL_MAULWURF,
364   EL_PINGUIN,
365   EL_SCHWEIN,
366   EL_DRACHE,
367
368   EL_SONDE,
369   EL_MAUER_X,
370   EL_MAUER_Y,
371   EL_MAUER_XY,
372
373   EL_SPEED_PILL,
374   EL_LEERRAUM,
375   EL_LEERRAUM,
376   EL_LEERRAUM,
377
378   EL_CHAR_A + ('S' - 'A'),
379   EL_CHAR_A + ('O' - 'A'),
380   EL_CHAR_A + ('K' - 'A'),
381   EL_CHAR_A + ('O' - 'A'),
382
383   EL_CHAR_MINUS,
384   EL_CHAR_A + ('B' - 'A'),
385   EL_CHAR_A + ('A' - 'A'),
386   EL_CHAR_A + ('N' - 'A'),
387
388   EL_SOKOBAN_OBJEKT,
389   EL_SOKOBAN_FELD_LEER,
390   EL_SOKOBAN_FELD_VOLL,
391   EL_BETON,
392
393   EL_LEERRAUM,
394   EL_LEERRAUM,
395   EL_LEERRAUM,
396   EL_LEERRAUM,
397
398   EL_CHAR('S'),
399   EL_CHAR('U'),
400   EL_CHAR('P'),
401   EL_CHAR('A'),
402
403   EL_CHAR('P'),
404   EL_CHAR('L'),
405   EL_CHAR('E'),
406   EL_CHAR('X'),
407
408   EL_SP_EMPTY,
409   EL_SP_ZONK,
410   EL_SP_BASE,
411   EL_SP_MURPHY,
412
413   EL_SP_INFOTRON,
414   EL_SP_CHIP_SINGLE,
415   EL_SP_HARD_GRAY,
416   EL_SP_EXIT,
417
418   EL_SP_DISK_ORANGE,
419   EL_SP_PORT1_RIGHT,
420   EL_SP_PORT1_DOWN,
421   EL_SP_PORT1_LEFT,
422
423   EL_SP_PORT1_UP,
424   EL_SP_PORT2_RIGHT,
425   EL_SP_PORT2_DOWN,
426   EL_SP_PORT2_LEFT,
427
428   EL_SP_PORT2_UP,
429   EL_SP_SNIKSNAK,
430   EL_SP_DISK_YELLOW,
431   EL_SP_TERMINAL,
432
433   EL_SP_DISK_RED,
434   EL_SP_PORT_Y,
435   EL_SP_PORT_X,
436   EL_SP_PORT_XY,
437
438   EL_SP_ELECTRON,
439   EL_SP_BUG,
440   EL_SP_CHIP_LEFT,
441   EL_SP_CHIP_RIGHT,
442
443   EL_SP_HARD_BASE1,
444   EL_SP_HARD_GREEN,
445   EL_SP_HARD_BLUE,
446   EL_SP_HARD_RED,
447
448   EL_SP_HARD_YELLOW,
449   EL_SP_HARD_BASE2,
450   EL_SP_HARD_BASE3,
451   EL_SP_HARD_BASE4,
452
453   EL_SP_HARD_BASE5,
454   EL_SP_HARD_BASE6,
455   EL_SP_CHIP_UPPER,
456   EL_SP_CHIP_LOWER,
457
458 /*
459   EL_CHAR_A + ('D' - 'A'),
460   EL_CHAR_A + ('Y' - 'A'),
461   EL_CHAR_A + ('N' - 'A'),
462   EL_CHAR_A + ('A' - 'A'),
463
464   EL_CHAR_A + ('B' - 'A'),
465   EL_CHAR_A + ('L' - 'A'),
466   EL_CHAR_A + ('A' - 'A'),
467   EL_CHAR_A + ('S' - 'A'),
468
469   EL_CHAR_MINUS,
470   EL_CHAR_A + ('T' - 'A'),
471   EL_CHAR_A + ('E' - 'A'),
472   EL_CHAR_A + ('R' - 'A'),
473 */
474
475   EL_LEERRAUM,
476   EL_LEERRAUM,
477   EL_LEERRAUM,
478   EL_LEERRAUM,
479
480   EL_CHAR_AUSRUF,
481   EL_CHAR_ZOLL,
482   EL_CHAR_DOLLAR,
483   EL_CHAR_PROZ,
484
485   EL_CHAR_APOSTR,
486   EL_CHAR_KLAMM1,
487   EL_CHAR_KLAMM2,
488   EL_CHAR_PLUS,
489
490   EL_CHAR_KOMMA,
491   EL_CHAR_MINUS,
492   EL_CHAR_PUNKT,
493   EL_CHAR_SLASH,
494
495   EL_CHAR_0 + 0,
496   EL_CHAR_0 + 1,
497   EL_CHAR_0 + 2,
498   EL_CHAR_0 + 3,
499
500   EL_CHAR_0 + 4,
501   EL_CHAR_0 + 5,
502   EL_CHAR_0 + 6,
503   EL_CHAR_0 + 7,
504
505   EL_CHAR_0 + 8,
506   EL_CHAR_0 + 9,
507   EL_CHAR_DOPPEL,
508   EL_CHAR_SEMIKL,
509
510   EL_CHAR_LT,
511   EL_CHAR_GLEICH,
512   EL_CHAR_GT,
513   EL_CHAR_FRAGE,
514
515   EL_CHAR_AT,
516   EL_CHAR_A + 0,
517   EL_CHAR_A + 1,
518   EL_CHAR_A + 2,
519
520   EL_CHAR_A + 3,
521   EL_CHAR_A + 4,
522   EL_CHAR_A + 5,
523   EL_CHAR_A + 6,
524
525   EL_CHAR_A + 7,
526   EL_CHAR_A + 8,
527   EL_CHAR_A + 9,
528   EL_CHAR_A + 10,
529
530   EL_CHAR_A + 11,
531   EL_CHAR_A + 12,
532   EL_CHAR_A + 13,
533   EL_CHAR_A + 14,
534
535   EL_CHAR_A + 15,
536   EL_CHAR_A + 16,
537   EL_CHAR_A + 17,
538   EL_CHAR_A + 18,
539
540   EL_CHAR_A + 19,
541   EL_CHAR_A + 20,
542   EL_CHAR_A + 21,
543   EL_CHAR_A + 22,
544
545   EL_CHAR_A + 23,
546   EL_CHAR_A + 24,
547   EL_CHAR_A + 25,
548   EL_CHAR_AE,
549
550   EL_CHAR_OE,
551   EL_CHAR_UE,
552   EL_CHAR_COPY,
553   EL_LEERRAUM
554 };
555 int elements_in_list = sizeof(editor_element)/sizeof(int);
556
557 static void ScrollMiniLevel(int from_x, int from_y, int scroll)
558 {
559   int x,y;
560   int dx = (scroll==ED_SCROLL_LEFT ? -1 : scroll==ED_SCROLL_RIGHT ? 1 : 0);
561   int dy = (scroll==ED_SCROLL_UP   ? -1 : scroll==ED_SCROLL_DOWN  ? 1 : 0);
562
563   XCopyArea(display,drawto,drawto,gc,
564             SX+MINI_TILEX*(dx==-1),SY+MINI_TILEY*(dy==-1),
565             SXSIZE-MINI_TILEX*ABS(dx),SYSIZE-MINI_TILEY*ABS(dy),
566             SX+MINI_TILEX*(dx==+1),SY+MINI_TILEY*(dy==+1));
567   if (dx)
568   {
569     x = (dx==1 ? 0 : 2*SCR_FIELDX-1);
570     for(y=0;y<2*SCR_FIELDY;y++)
571       DrawMiniElementOrWall(x,y,from_x,from_y);
572   }
573   else if (dy)
574   {
575     y = (dy==1 ? 0 : 2*SCR_FIELDY-1);
576     for(x=0;x<2*SCR_FIELDX;x++)
577       DrawMiniElementOrWall(x,y,from_x,from_y);
578   }
579
580   redraw_mask |= REDRAW_FIELD;
581   BackToFront();
582 }
583
584 void InitLevelEditorGadgets()
585 {
586   int i;
587
588   for (i=0; i<ED_NUM_GADGETS; i++)
589     level_editor_gadget[i] = NULL;
590 }
591
592 static void CreateControlButtons()
593 {
594   int i;
595
596   for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
597   {
598     Pixmap gd_pixmap = pix[PIX_DOOR];
599     struct GadgetInfo *gi;
600     int gd_xoffset, gd_yoffset;
601     int gd_x1, gd_x2, gd_y1, gd_y2;
602     int width, height;
603     int button_type;
604     int radio_button_nr;
605     boolean radio_button_pressed;
606     unsigned long event_mask;
607     int id = i;
608
609     if (id == ED_CTRL_ID_SINGLE_ITEMS ||
610         id == ED_CTRL_ID_CONNECTED_ITEMS ||
611         id == ED_CTRL_ID_LINE ||
612         id == ED_CTRL_ID_TEXT ||
613         id == ED_CTRL_ID_RECTANGLE ||
614         id == ED_CTRL_ID_FILLED_BOX ||
615         id == ED_CTRL_ID_FLOOD_FILL ||
616         id == ED_CTRL_ID_BRUSH ||
617         id == ED_CTRL_ID_PICK_ELEMENT)
618     {
619       button_type = GD_TYPE_RADIO_BUTTON;
620       radio_button_nr = 1;
621       radio_button_pressed = (id == drawing_function ? TRUE : FALSE);
622       event_mask = GD_EVENT_PRESSED;
623     }
624     else
625     {
626       button_type = GD_TYPE_NORMAL_BUTTON;
627       radio_button_nr = 0;
628       radio_button_pressed = FALSE;
629
630       if (id == ED_CTRL_ID_WRAP_LEFT ||
631           id == ED_CTRL_ID_WRAP_RIGHT ||
632           id == ED_CTRL_ID_WRAP_UP ||
633           id == ED_CTRL_ID_WRAP_DOWN)
634         event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
635       else
636         event_mask = GD_EVENT_RELEASED;
637     }
638
639     if (id < ED_NUM_CTRL1_BUTTONS)
640     {
641       int x = i % ED_CTRL1_BUTTONS_HORIZ;
642       int y = i / ED_CTRL1_BUTTONS_HORIZ;
643
644       gd_xoffset = ED_CTRL1_BUTTONS_XPOS + x * ED_CTRL1_BUTTON_XSIZE;
645       gd_yoffset = ED_CTRL1_BUTTONS_YPOS + y * ED_CTRL1_BUTTON_YSIZE;
646       width = ED_CTRL1_BUTTON_XSIZE;
647       height = ED_CTRL1_BUTTON_YSIZE;
648     }
649     else
650     {
651       int x = (i - ED_NUM_CTRL1_BUTTONS) % ED_CTRL2_BUTTONS_HORIZ;
652       int y = (i - ED_NUM_CTRL1_BUTTONS) / ED_CTRL2_BUTTONS_HORIZ;
653
654       gd_xoffset = ED_CTRL2_BUTTONS_XPOS + x * ED_CTRL2_BUTTON_XSIZE;
655       gd_yoffset = ED_CTRL2_BUTTONS_YPOS + y * ED_CTRL2_BUTTON_YSIZE;
656       width = ED_CTRL2_BUTTON_XSIZE;
657       height = ED_CTRL2_BUTTON_YSIZE;
658     }
659
660     gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
661     gd_x2 = DOOR_GFX_PAGEX7 + gd_xoffset;
662     gd_y1  = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_GFX_YPOS + gd_yoffset;
663     gd_y2  = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_ALT_GFX_YPOS + gd_yoffset;
664
665     gi = CreateGadget(GDI_CUSTOM_ID, id,
666                       GDI_X, EX + gd_xoffset,
667                       GDI_Y, EY + gd_yoffset,
668                       GDI_WIDTH, width,
669                       GDI_HEIGHT, height,
670                       GDI_TYPE, button_type,
671                       GDI_STATE, GD_BUTTON_UNPRESSED,
672                       GDI_RADIO_NR, radio_button_nr,
673                       GDI_RADIO_PRESSED, radio_button_pressed,
674                       GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
675                       GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y1,
676                       GDI_ALT_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y2,
677                       GDI_ALT_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
678                       GDI_EVENT_MASK, event_mask,
679                       GDI_CALLBACK, HandleControlButtons,
680                       GDI_END);
681
682     if (gi == NULL)
683       Error(ERR_EXIT, "cannot create gadget");
684
685     level_editor_gadget[id] = gi;
686   }
687 }
688
689 static void CreateCounterButtons()
690 {
691   int i, j;
692
693   for (i=0; i<ED_NUM_COUNTERS; i++)
694   {
695     for (j=0; j<2; j++)
696     {
697       Pixmap gd_pixmap = pix[PIX_DOOR];
698       struct GadgetInfo *gi;
699       int gd_xoffset;
700       int gd_x1, gd_x2, gd_y;
701       int id = counter_info[i].gadget_id + j;
702       unsigned long event_mask;
703
704       event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
705
706       gd_xoffset = (j == 0 ? ED_BUTTON_MINUS_XPOS : ED_BUTTON_PLUS_XPOS);
707       gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
708       gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
709       gd_y  = DOOR_GFX_PAGEY1 + ED_BUTTON_COUNT_YPOS;
710
711       gi = CreateGadget(GDI_CUSTOM_ID, id,
712                         GDI_X, SX + counter_info[i].x + gd_xoffset,
713                         GDI_Y, SY + counter_info[i].y,
714                         GDI_WIDTH, ED_BUTTON_COUNT_XSIZE,
715                         GDI_HEIGHT, ED_BUTTON_COUNT_YSIZE,
716                         GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
717                         GDI_STATE, GD_BUTTON_UNPRESSED,
718                         GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
719                         GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
720                         GDI_EVENT_MASK, event_mask,
721                         GDI_CALLBACK, HandleCounterButtons,
722                         GDI_END);
723
724       if (gi == NULL)
725         Error(ERR_EXIT, "cannot create gadget");
726
727       level_editor_gadget[id] = gi;
728     }
729   }
730 }
731
732 static void CreateDrawingAreas()
733 {
734   struct GadgetInfo *gi;
735   unsigned long event_mask;
736   int id;
737   int i;
738
739   event_mask =
740     GD_EVENT_PRESSED | GD_EVENT_RELEASED | GD_EVENT_MOVING |
741     GD_EVENT_OFF_BORDERS;
742
743   /* one for the level drawing area ... */
744   id = ED_CTRL_ID_DRAWING_LEVEL;
745   gi = CreateGadget(GDI_CUSTOM_ID, id,
746                     GDI_X, SX,
747                     GDI_Y, SY,
748                     GDI_WIDTH, SXSIZE,
749                     GDI_HEIGHT, SYSIZE,
750                     GDI_TYPE, GD_TYPE_DRAWING_AREA,
751                     GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
752                     GDI_EVENT_MASK, event_mask,
753                     GDI_CALLBACK, HandleDrawingAreas,
754                     GDI_END);
755
756   if (gi == NULL)
757     Error(ERR_EXIT, "cannot create gadget");
758
759   level_editor_gadget[id] = gi;
760
761   /* ... up to eight areas for element content ... */
762   for (i=0; i<MAX_ELEMCONT; i++)
763   {
764     int gx = SX + ED_AREA_ELEMCONT_XPOS + 5 * (i % 4) * MINI_TILEX;
765     int gy = SX + ED_AREA_ELEMCONT_YPOS + 6 * (i / 4) * MINI_TILEY;
766
767     id = ED_CTRL_ID_ELEMCONT_0 + i;
768     gi = CreateGadget(GDI_CUSTOM_ID, id,
769                       GDI_X, gx,
770                       GDI_Y, gy,
771                       GDI_WIDTH, 3 * MINI_TILEX,
772                       GDI_HEIGHT, 3 * MINI_TILEY,
773                       GDI_TYPE, GD_TYPE_DRAWING_AREA,
774                       GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
775                       GDI_EVENT_MASK, event_mask,
776                       GDI_CALLBACK, HandleDrawingAreas,
777                       GDI_END);
778
779     if (gi == NULL)
780       Error(ERR_EXIT, "cannot create gadget");
781
782     level_editor_gadget[id] = gi;
783   }
784
785   /* ... and one for the amoeba content */
786   id = ED_CTRL_ID_AMOEBA_CONTENT;
787   gi = CreateGadget(GDI_CUSTOM_ID, id,
788                     GDI_X, SX + ED_AREA_ELEMCONT_XPOS,
789                     GDI_Y, SY + ED_AREA_ELEMCONT_YPOS,
790                     GDI_WIDTH, MINI_TILEX,
791                     GDI_HEIGHT, MINI_TILEY,
792                     GDI_TYPE, GD_TYPE_DRAWING_AREA,
793                     GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
794                     GDI_EVENT_MASK, event_mask,
795                     GDI_CALLBACK, HandleDrawingAreas,
796                     GDI_END);
797
798   if (gi == NULL)
799     Error(ERR_EXIT, "cannot create gadget");
800
801   level_editor_gadget[id] = gi;
802 }
803
804 static void CreateTextInputGadgets()
805 {
806   Pixmap gd_pixmap = pix[PIX_DOOR];
807   int gd_x, gd_y;
808   struct GadgetInfo *gi;
809   unsigned long event_mask;
810   int id;
811
812   gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS;
813   gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS;
814   event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
815
816   /* text input gadget for the level name */
817   id = ED_CTRL_ID_LEVEL_NAME;
818   gi = CreateGadget(GDI_CUSTOM_ID, id,
819                     GDI_X, SX + ED_COUNT_ELEMCONT_XPOS,
820                     GDI_Y, SY + ED_AREA_ELEMCONT_YPOS + 3 * TILEX,
821                     GDI_TYPE, GD_TYPE_TEXTINPUT,
822                     GDI_TEXT_VALUE, level.name,
823                     GDI_TEXT_SIZE, 30,
824                     GDI_TEXT_BORDER, 3,
825                     GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x, gd_y,
826                     GDI_DESIGN_PRESSED, gd_pixmap, gd_x, gd_y,
827                     GDI_EVENT_MASK, event_mask,
828                     GDI_CALLBACK, HandleTextInputGadgets,
829                     GDI_END);
830
831   if (gi == NULL)
832     Error(ERR_EXIT, "cannot create gadget");
833
834   level_editor_gadget[id] = gi;
835 }
836
837 static void CreateLevelEditorGadgets()
838 {
839   if (level_editor_gadgets_created)
840     return;
841
842   CreateControlButtons();
843   CreateCounterButtons();
844   CreateDrawingAreas();
845   CreateTextInputGadgets();
846
847   level_editor_gadgets_created = TRUE;
848 }
849
850 static void MapControlButtons()
851 {
852   int i;
853
854   for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
855     MapGadget(level_editor_gadget[i]);
856 }
857
858 static void MapCounterButtons(int id)
859 {
860   int i;
861
862   for (i=0; i<2; i++)
863     MapGadget(level_editor_gadget[counter_info[id].gadget_id + i]);
864 }
865
866 static void MapDrawingArea(int id)
867 {
868   MapGadget(level_editor_gadget[id]);
869 }
870
871 static void MapTextInputGadget(int id)
872 {
873   MapGadget(level_editor_gadget[id]);
874 }
875
876 static void MapMainDrawingArea()
877 {
878   MapDrawingArea(ED_CTRL_ID_DRAWING_LEVEL);
879 }
880
881 static void UnmapDrawingArea(int id)
882 {
883   UnmapGadget(level_editor_gadget[id]);
884 }
885
886 void UnmapLevelEditorWindowGadgets()
887 {
888   int i;
889
890   for (i=ED_NUM_CTRL_BUTTONS; i<ED_NUM_GADGETS; i++)
891     UnmapGadget(level_editor_gadget[i]);
892 }
893
894 void UnmapLevelEditorGadgets()
895 {
896   int i;
897
898   for (i=0; i<ED_NUM_GADGETS; i++)
899     UnmapGadget(level_editor_gadget[i]);
900 }
901
902 void DrawLevelEd()
903 {
904   int i, x, y, graphic;
905
906   level_xpos=-1;
907   level_ypos=-1;
908   edit_mode = ED_MODE_DRAWING;
909   name_typing = FALSE;
910
911   CloseDoor(DOOR_CLOSE_ALL);
912
913   OpenDoor(DOOR_OPEN_2 | DOOR_NO_DELAY);
914
915   if (level_editor_test_game)
916   {
917     for(x=0; x<lev_fieldx; x++)
918       for(y=0; y<lev_fieldy; y++)
919         Feld[x][y] = Ur[x][y];
920
921     for(x=0; x<lev_fieldx; x++)
922       for(y=0; y<lev_fieldy; y++)
923         Ur[x][y] = OrigBackup[x][y];
924
925     level_editor_test_game = FALSE;
926   }
927   else
928   {
929     undo_buffer_position = -1;
930     undo_buffer_steps = -1;
931     CopyLevelToUndoBuffer();
932   }
933
934   DrawMiniLevel(level_xpos,level_ypos);
935   FadeToFront();
936
937   XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
938             DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY1,
939             DXSIZE,DYSIZE,
940             DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
941   XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
942             DOOR_GFX_PAGEX6+ED_BUTTON_ELEM_XPOS,
943             DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS,
944             4*ED_BUTTON_ELEM_XSIZE,5*ED_BUTTON_ELEM_YSIZE,
945             DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS,
946             DOOR_GFX_PAGEY1+ED_BUTTON_EUP_Y2POS);
947
948   for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
949   {
950     if (i < elements_in_list)
951       graphic = el2gfx(editor_element[i + element_shift]);
952     else
953       graphic = GFX_LEERRAUM;
954
955     DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
956                        DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS+3 + 
957                        (i%MAX_ELEM_X)*ED_BUTTON_ELEM_XSIZE,
958                        DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS+3 +
959                        (i/MAX_ELEM_X)*ED_BUTTON_ELEM_YSIZE,
960                        graphic);
961   }
962
963   DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
964                      DOOR_GFX_PAGEX1+ED_WIN_MB_LEFT_XPOS,
965                      DOOR_GFX_PAGEY1+ED_WIN_MB_LEFT_YPOS,
966                      el2gfx(new_element1));
967   DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
968                      DOOR_GFX_PAGEX1+ED_WIN_MB_MIDDLE_XPOS,
969                      DOOR_GFX_PAGEY1+ED_WIN_MB_MIDDLE_YPOS,
970                      el2gfx(new_element2));
971   DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
972                      DOOR_GFX_PAGEX1+ED_WIN_MB_RIGHT_XPOS,
973                      DOOR_GFX_PAGEY1+ED_WIN_MB_RIGHT_YPOS,
974                      el2gfx(new_element3));
975   DrawTextExt(pix[PIX_DB_DOOR],gc,
976               DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS,
977               DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
978               int2str(level_nr,2),FS_SMALL,FC_SPECIAL1);
979   XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
980             DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+3,
981             DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
982             7,FONT3_YSIZE,
983             DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS,
984             DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
985   XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
986             DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+14,
987             DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
988             7,FONT3_YSIZE,
989             DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS+9,
990             DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
991
992   XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
993             DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
994             VXSIZE,VYSIZE,
995             DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
996
997   /* draw bigger door */
998   XCopyArea(display, pix[PIX_DOOR], drawto, gc,
999             DOOR_GFX_PAGEX7, 0,
1000             108, 64,
1001             EX - 4, EY - 12);
1002
1003   /* draw new control window */
1004   XCopyArea(display, pix[PIX_DOOR], drawto, gc,
1005             DOOR_GFX_PAGEX8, 236,
1006             EXSIZE, EYSIZE,
1007             EX, EY);
1008
1009   redraw_mask |= REDRAW_ALL;
1010
1011   OpenDoor(DOOR_OPEN_1);
1012
1013   if (!level_editor_gadgets_created)
1014     CreateLevelEditorGadgets();
1015
1016   MapControlButtons();
1017   MapMainDrawingArea();
1018
1019   /*
1020   OpenDoor(DOOR_OPEN_1 | DOOR_OPEN_2);
1021   */
1022 }
1023
1024 void DrawControlWindow()
1025 {
1026   int i,x,y;
1027
1028   ClearWindow();
1029   UnmapLevelEditorWindowGadgets();
1030
1031   /* Inhalt der Mampfer */
1032   DrawText(ED_COUNT_GADGET_XPOS+1,SY+6,
1033            "Contents of a smashed cruncher:",FS_SMALL,FC_YELLOW);
1034   for(i=0;i<4;i++) for(y=0;y<4;y++) for(x=0;x<4;x++)
1035   {
1036     DrawMiniElement(1+5*i+x,2+y,EL_ERDREICH);
1037     XFillRectangle(display,drawto,gc,
1038                    SX+(1+5*i)*MINI_TILEX+MINI_TILEX/2-1,
1039                    SY+(2)*MINI_TILEY+MINI_TILEY/2-1,
1040                    3*MINI_TILEX+2,3*MINI_TILEY+2);
1041   }
1042   XCopyArea(display,drawto,drawto,gc,
1043             SX+1*MINI_TILEX,SY+2*MINI_TILEY,
1044             4*5*MINI_TILEX,5*MINI_TILEY,
1045             SX+1*MINI_TILEX-MINI_TILEX/2,SY+2*MINI_TILEY-MINI_TILEY/2);
1046   for(i=0;i<4;i++)
1047   {
1048     for(y=0;y<3;y++) for(x=0;x<3;x++)
1049       DrawMiniElement(1+5*i+x,2+y,level.mampfer_inhalt[i][x][y]);
1050
1051     DrawText(SX+MINI_TILEX+(5*i+1)*MINI_TILEX+1,
1052              SY+2*MINI_TILEY+(4)*MINI_TILEY-4,
1053              int2str(i+1,1),FS_SMALL,FC_YELLOW);
1054   }
1055
1056   /* Inhalt der Amöbe */
1057   for(y=0;y<2;y++) for(x=0;x<2;x++)
1058   {
1059     DrawMiniElement(29+x,26+y,EL_ERDREICH);
1060     XFillRectangle(display,drawto,gc,
1061                    SX+29*MINI_TILEX+MINI_TILEX/2-1,
1062                    SY+26*MINI_TILEY+MINI_TILEY/2-1,
1063                    MINI_TILEX+2,MINI_TILEY+2);
1064   }
1065   XCopyArea(display,drawto,drawto,gc,
1066             SX+29*MINI_TILEX,SY+26*MINI_TILEY,
1067             3*MINI_TILEX,3*MINI_TILEY,
1068             SX+29*MINI_TILEX-MINI_TILEX/2,SY+26*MINI_TILEY-MINI_TILEY/2);
1069   DrawMiniElement(29,26,level.amoebe_inhalt);
1070
1071   for(i=0;i<11+3+2;i++)
1072   {
1073     XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1074               DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1075               DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1076               DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1077               ED_COUNT_GADGET_XPOS,
1078               ED_COUNT_GADGET_YPOS+i*ED_COUNT_GADGET_YSIZE);
1079
1080     if (i<11)
1081       DrawText(ED_COUNT_VALUE_XPOS,
1082                ED_COUNT_VALUE_YPOS+i*ED_COUNT_GADGET_YSIZE,
1083                int2str(level.score[i],3),FS_SMALL,FC_YELLOW);
1084     else if (i==11)
1085       DrawText(ED_COUNT_VALUE_XPOS,
1086                ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
1087                int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
1088     else if (i==12)
1089       DrawText(ED_COUNT_VALUE_XPOS,
1090                ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
1091                int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
1092     else if (i==13)
1093       DrawText(ED_COUNT_VALUE_XPOS,
1094                ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
1095                int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
1096     else if (i==14)
1097       DrawText(ED_COUNT_VALUE_XPOS,
1098                ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
1099                int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
1100     else if (i==15)
1101       DrawText(ED_COUNT_VALUE_XPOS,
1102                ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
1103                int2str(level.time,3),FS_SMALL,FC_YELLOW);
1104   }
1105
1106   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+0*ED_COUNT_TEXT_YSIZE,
1107            "Score for Emerald",FS_SMALL,FC_YELLOW);
1108   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+1*ED_COUNT_TEXT_YSIZE,
1109            "Score for Diamond",FS_SMALL,FC_YELLOW);
1110   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+2*ED_COUNT_TEXT_YSIZE,
1111            "Score for smashing a Bug",FS_SMALL,FC_YELLOW);
1112   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+3*ED_COUNT_TEXT_YSIZE,
1113            "Score for smashing a Spaceship",FS_SMALL,FC_YELLOW);
1114   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+4*ED_COUNT_TEXT_YSIZE,
1115            "Score for smashing a Cruncher",FS_SMALL,FC_YELLOW);
1116   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+5*ED_COUNT_TEXT_YSIZE,
1117            "Score for smashing an Alien",FS_SMALL,FC_YELLOW);
1118   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+6*ED_COUNT_TEXT_YSIZE,
1119            "Score for smashing a Pacman",FS_SMALL,FC_YELLOW);
1120   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+7*ED_COUNT_TEXT_YSIZE,
1121            "Score for cracking a nut",FS_SMALL,FC_YELLOW);
1122   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+8*ED_COUNT_TEXT_YSIZE,
1123            "Score for dynamite",FS_SMALL,FC_YELLOW);
1124   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+9*ED_COUNT_TEXT_YSIZE,
1125            "Score for key",FS_SMALL,FC_YELLOW);
1126   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+10*ED_COUNT_TEXT_YSIZE,
1127            "Score for each 10 seconds left",FS_SMALL,FC_YELLOW);
1128   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+11*ED_COUNT_TEXT_YSIZE,
1129            "Speed of the amoeba / Content",FS_SMALL,FC_YELLOW);
1130   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+12*ED_COUNT_TEXT_YSIZE,
1131            "Time for magic wall",FS_SMALL,FC_YELLOW);
1132   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+13*ED_COUNT_TEXT_YSIZE,
1133            "Time for wheel",FS_SMALL,FC_YELLOW);
1134   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+14*ED_COUNT_TEXT_YSIZE,
1135            "Emeralds needed in this level",FS_SMALL,FC_YELLOW);
1136   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+15*ED_COUNT_TEXT_YSIZE,
1137            "Time available for this level",FS_SMALL,FC_YELLOW);
1138
1139   XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1140             DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS,
1141             DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
1142             ED_WIN_COUNT_XSIZE,ED_WIN_COUNT_YSIZE,
1143             ED_COUNT_GADGET_XPOS,
1144             ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
1145   for(i=1;i<31;i++)
1146     XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1147               DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS+3+2*FONT2_XSIZE,
1148               DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
1149               ED_WIN_COUNT_XSIZE-3-2*FONT2_XSIZE,ED_WIN_COUNT_YSIZE,
1150               ED_COUNT_GADGET_XPOS+3+i*FONT2_XSIZE,
1151               ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
1152   DrawText(ED_COUNT_GADGET_XPOS+5,
1153            ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1154            level.name,FS_SMALL,FC_YELLOW);
1155   DrawText(ED_COUNT_GADGET_XPOS+(30+3)*FONT2_XSIZE-5,
1156            ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1157            "Title",FS_SMALL,FC_YELLOW);
1158
1159   DrawText(ED_SIZE_GADGET_XPOS,ED_SIZE_GADGET_YPOS-18,
1160            "Playfield size:",FS_SMALL,FC_YELLOW);
1161   XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1162             DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1163             DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1164             DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1165             ED_SIZE_GADGET_XPOS,
1166             ED_SIZE_GADGET_YPOS+0*ED_COUNT_GADGET_YSIZE);
1167   XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1168             DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1169             DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1170             DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1171             ED_SIZE_GADGET_XPOS,
1172             ED_SIZE_GADGET_YPOS+1*ED_COUNT_GADGET_YSIZE);
1173   DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+0*ED_SIZE_TEXT_YSIZE,
1174            "Width",FS_SMALL,FC_YELLOW);
1175   DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+1*ED_SIZE_TEXT_YSIZE,
1176            "Height",FS_SMALL,FC_YELLOW);
1177   DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
1178            int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
1179   DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
1180            int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
1181 }
1182
1183 void AdjustLevelScrollPosition()
1184 {
1185   if (level_xpos < -1)
1186     level_xpos = -1;
1187   if (level_xpos > lev_fieldx - 2*SCR_FIELDX + 1)
1188     level_xpos = lev_fieldx - 2*SCR_FIELDX + 1;
1189   if (lev_fieldx < 2*SCR_FIELDX - 2)
1190     level_xpos = -1;
1191
1192   if (level_ypos < -1)
1193     level_ypos = -1;
1194   if (level_ypos > lev_fieldy - 2*SCR_FIELDY + 1)
1195     level_ypos = lev_fieldy - 2*SCR_FIELDY + 1;
1196   if (lev_fieldy < 2*SCR_FIELDY - 2)
1197     level_ypos = -1;
1198 }
1199
1200 static void PickDrawingElement(int button, int element)
1201 {
1202   if (button < 1 || button > 3)
1203     return;
1204
1205   if (button == 1)
1206   {
1207     new_element1 = element;
1208     DrawMiniGraphicExt(drawto, gc,
1209                        DX + ED_WIN_MB_LEFT_XPOS,
1210                        DY + ED_WIN_MB_LEFT_YPOS,
1211                        el2gfx(new_element1));
1212   }
1213   else if (button == 2)
1214   {
1215     new_element2 = element;
1216     DrawMiniGraphicExt(drawto, gc,
1217                        DX + ED_WIN_MB_MIDDLE_XPOS,
1218                        DY + ED_WIN_MB_MIDDLE_YPOS,
1219                        el2gfx(new_element2));
1220   }
1221   else
1222   {
1223     new_element3 = element;
1224     DrawMiniGraphicExt(drawto, gc,
1225                        DX + ED_WIN_MB_RIGHT_XPOS,
1226                        DY + ED_WIN_MB_RIGHT_YPOS,
1227                        el2gfx(new_element3));
1228   }
1229
1230   redraw_mask |= REDRAW_DOOR_1;
1231 }
1232
1233 void LevelEd(int mx, int my, int button)
1234 {
1235   static int last_button = 0;
1236   static int in_field_pressed = FALSE;
1237   static boolean use_floodfill = FALSE;
1238
1239
1240   /*
1241   int x = (mx-SX)/MINI_TILEX; 
1242   int y = (my-SY)/MINI_TILEY; 
1243   */
1244
1245   /*
1246   HandlePressedControlButtons();
1247   HandleDrawingFunctions(mx, my, button);
1248   */
1249
1250   if (use_floodfill)            /********** FLOOD FILL **********/
1251   {
1252
1253
1254 #if 0
1255
1256     if (button)
1257     {
1258       if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1259       {
1260         int from_x, from_y;
1261         int fill_element;
1262
1263         if (x>lev_fieldx || y>lev_fieldy ||
1264             (x==0 && level_xpos<0) ||
1265             (x==2*SCR_FIELDX-1 && level_xpos>lev_fieldx-2*SCR_FIELDX) ||
1266             (y==0 && level_ypos<0) ||
1267             (y==2*SCR_FIELDY-1 && level_ypos>lev_fieldy-2*SCR_FIELDY))
1268           return;
1269
1270         from_x = x+level_xpos;
1271         from_y = y+level_ypos;
1272         fill_element = (button==1 ? new_element1 :
1273                         button==2 ? new_element2 :
1274                         button==3 ? new_element3 : 0);
1275
1276         FloodFill(from_x,from_y,fill_element);
1277         DrawMiniLevel(level_xpos,level_ypos);
1278       }
1279
1280       use_floodfill = FALSE;
1281       CloseDoor(DOOR_CLOSE_1);
1282       OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
1283     }
1284     return;
1285
1286 #endif
1287
1288
1289
1290   }
1291   else                          /********** EDIT/CTRL-FENSTER **********/
1292   {
1293     static unsigned long choice_delay = 0;
1294     int choice = CheckElemButtons(mx,my,button);
1295     int elem_pos = choice-ED_BUTTON_ELEM;
1296
1297     if (((choice == ED_BUTTON_EUP && element_shift>0) ||
1298          (choice == ED_BUTTON_EDOWN &&
1299           element_shift<elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)) &&
1300         DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1301     {
1302       int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
1303       int i;
1304
1305 #if 0
1306       step = (button==1 ? MAX_ELEM_X : button==2 ? 5*MAX_ELEM_X :
1307               elements_in_list);
1308       element_shift += (choice==ED_BUTTON_EUP ? -step : step);
1309 #else
1310       step = step * MAX_ELEM_X * (choice == ED_BUTTON_EUP ? -1 : +1);
1311       element_shift += step;
1312 #endif
1313
1314       if (element_shift<0)
1315         element_shift = 0;
1316       if (element_shift>elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)
1317         element_shift = elements_in_list-MAX_ELEM_X*MAX_ELEM_Y;
1318       if (element_shift % MAX_ELEM_X)
1319         element_shift += MAX_ELEM_X-(element_shift % MAX_ELEM_X);
1320
1321       for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
1322         DrawElemButton(i+2,ED_BUTTON_RELEASED);
1323     }
1324     else if (elem_pos>=0 && elem_pos<MAX_ELEM_X*MAX_ELEM_Y)
1325     {
1326       int new_element;
1327
1328       if (elem_pos+element_shift < elements_in_list)
1329         new_element = editor_element[elem_pos+element_shift];
1330       else
1331         new_element = EL_LEERRAUM;
1332
1333       PickDrawingElement(last_button, new_element);
1334
1335       if (!HAS_CONTENT(properties_element))
1336       {
1337         properties_element = new_element;
1338         if (edit_mode == ED_MODE_PROPERTIES)
1339           DrawPropertiesWindow();
1340       }
1341     }
1342   
1343     if (edit_mode == ED_MODE_DRAWING)   /********** EDIT-FENSTER **********/
1344     {
1345
1346
1347
1348 #if 0
1349
1350       switch(CheckEditButtons(mx,my,button))
1351       {
1352         case ED_BUTTON_CTRL:
1353           CloseDoor(DOOR_CLOSE_2);
1354           DrawControlWindow();
1355           XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1356                     DOOR_GFX_PAGEX4,DOOR_GFX_PAGEY1+80,
1357                     VXSIZE,VYSIZE,
1358                     DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1359           OpenDoor(DOOR_OPEN_2);
1360           edit_mode = ED_MODE_INFO;
1361           break;
1362         case ED_BUTTON_FILL:
1363           Request("Caution ! Flood fill mode ! Choose area !",REQ_OPEN);
1364           use_floodfill = TRUE;
1365           return;
1366           break;
1367         case ED_BUTTON_LEFT:
1368           if (level_xpos>=0)
1369           {
1370             if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1371               break;
1372             if (lev_fieldx<2*SCR_FIELDX-2)
1373               break;
1374
1375             level_xpos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
1376             if (level_xpos<-1)
1377               level_xpos = -1;
1378             if (button==1)
1379               ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_RIGHT);
1380             else
1381               DrawMiniLevel(level_xpos,level_ypos);
1382           }
1383           break;
1384         case ED_BUTTON_RIGHT:
1385           if (level_xpos<=lev_fieldx-2*SCR_FIELDX)
1386           {
1387             if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1388               break;
1389             if (lev_fieldx<2*SCR_FIELDX-2)
1390               break;
1391
1392             level_xpos += (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
1393             if (level_xpos>lev_fieldx-2*SCR_FIELDX+1)
1394               level_xpos = lev_fieldx-2*SCR_FIELDX+1;
1395             if (button==1)
1396               ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_LEFT);
1397             else
1398               DrawMiniLevel(level_xpos,level_ypos);
1399           }
1400           break;
1401         case ED_BUTTON_UP:
1402           if (level_ypos>=0)
1403           {
1404             if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1405               break;
1406             if (lev_fieldy<2*SCR_FIELDY-2)
1407               break;
1408
1409             level_ypos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1410             if (level_ypos<-1)
1411               level_ypos = -1;
1412             if (button==1)
1413               ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_DOWN);
1414             else
1415               DrawMiniLevel(level_xpos,level_ypos);
1416           }
1417           break;
1418         case ED_BUTTON_DOWN:
1419           if (level_ypos<=lev_fieldy-2*SCR_FIELDY)
1420           {
1421             if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1422               break;
1423             if (lev_fieldy<2*SCR_FIELDY-2)
1424               break;
1425
1426             level_ypos += (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1427             if (level_ypos>lev_fieldy-2*SCR_FIELDY+1)
1428               level_ypos = lev_fieldy-2*SCR_FIELDY+1;
1429             if (button==1)
1430               ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_UP);
1431             else
1432               DrawMiniLevel(level_xpos,level_ypos);
1433           }
1434           break;
1435         default:
1436           break;
1437       }
1438
1439 #endif
1440
1441
1442
1443 #if 0
1444
1445       if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1446       {
1447         int new_element;
1448
1449         if (button && !motion_status)
1450           in_field_pressed = TRUE;
1451
1452         if (!button || !in_field_pressed || button<1 || button>3 ||
1453             (y==0 && level_ypos<0) ||
1454             (y==2*SCR_FIELDY-1 && level_ypos>lev_fieldy-2*SCR_FIELDY) ||
1455             (x==0 && level_xpos<0) ||
1456             (x==2*SCR_FIELDX-1 && level_xpos>lev_fieldx-2*SCR_FIELDX) ||
1457             x>lev_fieldx || y>lev_fieldy)
1458           return;
1459
1460         new_element = (button==1 ? new_element1 :
1461                        button==2 ? new_element2 :
1462                        button==3 ? new_element3 : 0);
1463
1464         if (new_element != Feld[x+level_xpos][y+level_ypos])
1465         {
1466           if (new_element==EL_SPIELFIGUR) /* Jeder nur EINE Figur bitte... */
1467           {
1468             int x,y;
1469
1470             for(x=0;x<lev_fieldx;x++) for(y=0;y<lev_fieldy;y++)
1471             {
1472               if (Feld[x][y]==EL_SPIELFIGUR || Feld[x][y]==EL_SPIELER1)
1473               {
1474                 Feld[x][y] = EL_LEERRAUM;
1475                 if (x-level_xpos>=0 && x-level_xpos<2*SCR_FIELDX &&
1476                     y-level_ypos>=0 && y-level_ypos<2*SCR_FIELDY)
1477                   DrawMiniElement(x-level_xpos,y-level_ypos,EL_LEERRAUM);
1478               }
1479             }
1480           }
1481
1482           Feld[x+level_xpos][y+level_ypos] = new_element;
1483           DrawMiniElement(x,y,new_element);
1484         }
1485       }
1486       else if (!motion_status)  /* Mauszeiger nicht im Level-Feld */
1487         in_field_pressed = FALSE;
1488
1489 #endif
1490
1491
1492
1493     }
1494     else if (edit_mode == ED_MODE_INFO)/********** KONTROLL-FENSTER **********/
1495     {
1496       int choice = CheckCountButtons(mx,my,button);
1497       int step = (button==1 ? 1 : button==2 ? 5 : button==3 ? 10 : 0);
1498
1499       if (choice >= 0 && choice < 36 &&
1500           DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1501       {
1502         if (!(choice % 2))
1503           step = -step;
1504
1505         choice /= 2;
1506
1507         if (choice<11)
1508         {
1509           level.score[choice] += step;
1510           if (level.score[choice]<0)
1511             level.score[choice] = 0;
1512           else if (level.score[choice]>255)
1513             level.score[choice] = 255;
1514         }
1515         else if (choice==11)
1516         {
1517           level.tempo_amoebe += step;
1518           if (level.tempo_amoebe<0)
1519             level.tempo_amoebe = 0;
1520           else if (level.tempo_amoebe>255)
1521             level.tempo_amoebe = 255;
1522         }
1523         else if (choice==12)
1524         {
1525           level.dauer_sieb += step;
1526           if (level.dauer_sieb<0)
1527             level.dauer_sieb = 0;
1528           else if (level.dauer_sieb>255)
1529             level.dauer_sieb = 255;
1530         }
1531         else if (choice==13)
1532         {
1533           level.dauer_ablenk += step;
1534           if (level.dauer_ablenk<0)
1535             level.dauer_ablenk = 0;
1536           else if (level.dauer_ablenk>255)
1537             level.dauer_ablenk = 255;
1538         }
1539         else if (choice==14)
1540         {
1541           level.edelsteine += step;
1542           if (level.edelsteine<0)
1543             level.edelsteine = 0;
1544           else if (level.edelsteine>999)
1545             level.edelsteine = 999;
1546         }
1547         else if (choice==15)
1548         {
1549           level.time += step;
1550           if (level.time<0)
1551             level.time = 0;
1552           else if (level.time>999)
1553             level.time = 999;
1554         }
1555         else if (choice==16)
1556         {
1557           lev_fieldx += step;
1558           if (lev_fieldx<MIN_LEV_FIELDX)
1559             lev_fieldx = MIN_LEV_FIELDX;
1560           else if (lev_fieldx>MAX_LEV_FIELDX)
1561             lev_fieldx = MAX_LEV_FIELDX;
1562           level.fieldx = lev_fieldx;
1563         }
1564         else if (choice==17)
1565         {
1566           lev_fieldy += step;
1567           if (lev_fieldy<MIN_LEV_FIELDY)
1568             lev_fieldy = MIN_LEV_FIELDY;
1569           else if (lev_fieldy>MAX_LEV_FIELDY)
1570             lev_fieldy = MAX_LEV_FIELDY;
1571           level.fieldy = lev_fieldy;
1572         }
1573
1574         if (choice<11)
1575           DrawText(ED_COUNT_VALUE_XPOS,
1576                    ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
1577                    int2str(level.score[choice],3),FS_SMALL,FC_YELLOW);
1578         else if (choice==11)
1579           DrawText(ED_COUNT_VALUE_XPOS,
1580                    ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
1581                    int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
1582         else if (choice==12)
1583           DrawText(ED_COUNT_VALUE_XPOS,
1584                    ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
1585                    int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
1586         else if (choice==13)
1587           DrawText(ED_COUNT_VALUE_XPOS,
1588                    ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
1589                    int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
1590         else if (choice==14)
1591           DrawText(ED_COUNT_VALUE_XPOS,
1592                    ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
1593                    int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
1594         else if (choice==15)
1595           DrawText(ED_COUNT_VALUE_XPOS,
1596                    ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
1597                    int2str(level.time,3),FS_SMALL,FC_YELLOW);
1598         else if (choice==16)
1599           DrawText(ED_SIZE_VALUE_XPOS,
1600                    ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
1601                    int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
1602         else if (choice==17)
1603           DrawText(ED_SIZE_VALUE_XPOS,
1604                    ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
1605                    int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
1606
1607         redraw_mask &= ~REDRAW_FIELD;
1608         if (choice<16)
1609           XCopyArea(display,drawto,window,gc,
1610                     ED_COUNT_VALUE_XPOS,
1611                     ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
1612                     3*FONT2_XSIZE,FONT2_YSIZE,
1613                     ED_COUNT_VALUE_XPOS,
1614                     ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE);
1615         else
1616           XCopyArea(display,drawto,window,gc,
1617                     ED_SIZE_VALUE_XPOS,
1618                     ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE,
1619                     3*FONT2_XSIZE,FONT2_YSIZE,
1620                     ED_SIZE_VALUE_XPOS,
1621                     ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE);
1622         XFlush(display);
1623       }
1624
1625
1626
1627 #if 0
1628
1629       switch(CheckCtrlButtons(mx,my,button))
1630       {
1631         case ED_BUTTON_EDIT:
1632           CloseDoor(DOOR_CLOSE_2);
1633           AdjustLevelScrollPosition();
1634           DrawMiniLevel(level_xpos,level_ypos);
1635           XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1636                     DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
1637                     VXSIZE,VYSIZE,
1638                     DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1639           OpenDoor(DOOR_OPEN_2);
1640           edit_mode = ED_MODE_DRAWING;
1641           break;
1642         case ED_BUTTON_CLEAR:
1643           if (Request("Are you sure to clear this level ?",REQ_ASK))
1644           {
1645             for(x=0;x<MAX_LEV_FIELDX;x++) 
1646               for(y=0;y<MAX_LEV_FIELDY;y++) 
1647                 Feld[x][y] = EL_ERDREICH;
1648             DrawMiniLevel(level_xpos,level_ypos);
1649           }
1650           break;
1651         case ED_BUTTON_UNDO:
1652           if (leveldir[leveldir_nr].readonly ||
1653               Request("Exit without saving ?",REQ_ASK | REQ_STAY_OPEN))
1654           {
1655             CloseDoor(DOOR_CLOSE_ALL);
1656             game_status=MAINMENU;
1657             DrawMainMenu();
1658           }
1659           else
1660           {
1661             CloseDoor(DOOR_CLOSE_1);
1662             OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
1663           }
1664           break;
1665         case ED_BUTTON_EXIT:
1666           {
1667             int figur_vorhanden = FALSE;
1668
1669             if (leveldir[leveldir_nr].readonly)
1670             {
1671               Request("This level is read only !",REQ_CONFIRM);
1672               break;
1673             }
1674
1675             for(y=0;y<lev_fieldy;y++) 
1676               for(x=0;x<lev_fieldx;x++)
1677                 if (Feld[x][y] == EL_SPIELFIGUR ||
1678                     Feld[x][y] == EL_SPIELER1 ||
1679                     Feld[x][y] == EL_SP_MURPHY) 
1680                   figur_vorhanden = TRUE;
1681
1682             if (!figur_vorhanden)
1683               Request("No Level without Gregor Mc Duffin please !",
1684                          REQ_CONFIRM);
1685             else
1686             {
1687               if (Request("Save this level and kill the old ?",
1688                              REQ_ASK | REQ_STAY_OPEN))
1689               {
1690                 for(x=0;x<lev_fieldx;x++)
1691                   for(y=0;y<lev_fieldy;y++) 
1692                     Ur[x][y]=Feld[x][y];
1693                 SaveLevel(level_nr);
1694               }
1695               CloseDoor(DOOR_CLOSE_ALL);
1696               game_status=MAINMENU;
1697               DrawMainMenu();
1698             }
1699           }
1700           break;
1701         default:
1702           break;
1703       }
1704
1705 #endif
1706
1707
1708
1709       if (mx>=ED_COUNT_GADGET_XPOS &&
1710           mx<ED_COUNT_GADGET_XPOS+31*FONT2_XSIZE+10 &&
1711           my>=ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE &&
1712           my<ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE+ED_WIN_COUNT_YSIZE)
1713       {
1714         if (!name_typing)
1715         {
1716           name_typing = TRUE;
1717           DrawText(ED_COUNT_GADGET_XPOS+5,
1718                    ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1719                    level.name,FS_SMALL,FC_GREEN);
1720           DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
1721                    ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1722                    "<",FS_SMALL,FC_RED);
1723         }
1724       }
1725       else
1726       {
1727         if (name_typing)
1728         {
1729           name_typing = FALSE;
1730           DrawText(ED_COUNT_GADGET_XPOS+5,
1731                    ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1732                    level.name,FS_SMALL,FC_YELLOW);
1733           DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
1734                    ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1735                    " ",FS_SMALL,FC_RED);
1736         }
1737       }
1738
1739       if (mx>=SX+29*MINI_TILEX && mx<SX+30*MINI_TILEX &&
1740           my>=SY+26*MINI_TILEY && my<SY+27*MINI_TILEY)
1741       {
1742         int new_element;
1743
1744         if (!button || button<1 || button>3)
1745           return;
1746
1747         new_element = (button==1 ? new_element1 :
1748                        button==2 ? new_element2 :
1749                        button==3 ? new_element3 : 0);
1750
1751         if (new_element != level.amoebe_inhalt)
1752         {
1753           level.amoebe_inhalt = new_element;
1754           DrawMiniElement(29,26,new_element);
1755         }
1756       }
1757
1758       if (mx>=SX+1*MINI_TILEX && mx<SX+(1+4*5)*MINI_TILEX &&
1759           my>=SY+2*MINI_TILEY && my<SY+(2+3)*MINI_TILEY)
1760       {
1761         int x = (mx-SX-1*MINI_TILEX)/MINI_TILEX;
1762         int y = (my-SY-2*MINI_TILEY)/MINI_TILEY;
1763         int i = x/5;
1764         int new_element;
1765
1766         x = x-i*5;
1767         if (i>=0 && i<43 && x>=0 && x<3 && y>=0 && y<3)
1768         {
1769           if (button && !motion_status)
1770             in_field_pressed = TRUE;
1771
1772           if (!button || !in_field_pressed || button<1 || button>3)
1773             return;
1774
1775           new_element = (button==1 ? new_element1 :
1776                          button==2 ? new_element2 :
1777                          button==3 ? new_element3 : 0);
1778
1779           if (new_element != level.mampfer_inhalt[i][x][y])
1780           {
1781             level.mampfer_inhalt[i][x][y] = new_element;
1782             DrawMiniElement(1+5*i+x,2+y,new_element);
1783           }
1784         }
1785         else if (!motion_status)/* Mauszeiger nicht im Cruncher-Feld */
1786           in_field_pressed = FALSE;
1787       }
1788       else if (!motion_status)  /* Mauszeiger nicht im Cruncher-Feld */
1789         in_field_pressed = FALSE;
1790     }
1791   }
1792
1793   last_button = button;
1794
1795   BackToFront();
1796 }
1797
1798 void LevelNameTyping(KeySym key)
1799 {
1800   unsigned char ascii = 0;
1801   int len = strlen(level.name);
1802
1803   if (!name_typing)
1804     return;
1805
1806   if (key>=XK_A && key<=XK_Z)
1807     ascii = 'A'+(char)(key-XK_A);
1808   else if (key>=XK_a && key<=XK_z)
1809     ascii = 'a'+(char)(key-XK_a);
1810   else if (key>=XK_0 && key<=XK_9)
1811     ascii = '0'+(char)(key-XK_0);
1812 #ifdef XK_LATIN1
1813   else if (key>=XK_space && key<=XK_at)
1814     ascii = ' '+(char)(key-XK_space);
1815   else if (key==XK_Adiaeresis)
1816     ascii = 'Ä';
1817   else if (key==XK_Odiaeresis)
1818     ascii = 'Ö';
1819   else if (key==XK_Udiaeresis)
1820     ascii = 'Ü';
1821   else if (key==XK_adiaeresis)
1822     ascii = 'ä';
1823   else if (key==XK_odiaeresis)
1824     ascii = 'ö';
1825   else if (key==XK_udiaeresis)
1826     ascii = 'ü';
1827   else if (key==XK_underscore)
1828     ascii = '_';
1829 #endif
1830
1831   if (ascii && len<MAX_LEVNAMLEN-2)
1832   {
1833     level.name[len] = ascii;
1834     level.name[len+1] = 0;
1835     len++;
1836
1837     DrawTextExt(drawto,gc,
1838                 ED_COUNT_GADGET_XPOS+5,
1839                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1840                 level.name,FS_SMALL,FC_GREEN);
1841     DrawTextExt(window,gc,
1842                 ED_COUNT_GADGET_XPOS+5,
1843                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1844                 level.name,FS_SMALL,FC_GREEN);
1845     DrawTextExt(drawto,gc,
1846                 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1847                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1848                 "<",FS_SMALL,FC_RED);
1849     DrawTextExt(window,gc,
1850                 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1851                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1852                 "<",FS_SMALL,FC_RED);
1853   }
1854   else if ((key==XK_Delete || key==XK_BackSpace) && len>0)
1855   {
1856     level.name[len-1] = 0;
1857     len--;
1858
1859     DrawTextExt(drawto,gc,
1860                 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1861                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1862                 "< ",FS_SMALL,FC_GREEN);
1863     DrawTextExt(window,gc,
1864                 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1865                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1866                 "< ",FS_SMALL,FC_GREEN);
1867   }
1868   else if (key==XK_Return)
1869   {
1870     DrawTextExt(drawto,gc,
1871                 ED_COUNT_GADGET_XPOS+5,
1872                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1873                 level.name,FS_SMALL,FC_YELLOW);
1874     DrawTextExt(window,gc,
1875                 ED_COUNT_GADGET_XPOS+5,
1876                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1877                 level.name,FS_SMALL,FC_YELLOW);
1878     DrawTextExt(drawto,gc,
1879                 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1880                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1881                 " ",FS_SMALL,FC_YELLOW);
1882     DrawTextExt(window,gc,
1883                 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1884                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1885                 " ",FS_SMALL,FC_YELLOW);
1886
1887     name_typing = FALSE;
1888   }
1889 }
1890
1891 static void DrawCounterValueField(int counter_id, int value)
1892 {
1893   int x = SX + counter_info[counter_id].x + ED_WIN_COUNT_XPOS;
1894   int y = SY + counter_info[counter_id].y;
1895
1896   XCopyArea(display, pix[PIX_DOOR], drawto, gc,
1897             DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS,
1898             DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS,
1899             ED_WIN_COUNT_XSIZE, ED_WIN_COUNT_YSIZE,
1900             x, y);
1901
1902   DrawText(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
1903            int2str(value, 3), FS_SMALL, FC_YELLOW);
1904 }
1905
1906 static void DrawDrawingWindow()
1907 {
1908   ClearWindow();
1909   UnmapLevelEditorWindowGadgets();
1910   MapMainDrawingArea();
1911   AdjustLevelScrollPosition();
1912   DrawMiniLevel(level_xpos, level_ypos);
1913 }
1914
1915 static void DrawElementContentAreas()
1916 {
1917   int *num_areas = &MampferMax;
1918   int area_x = ED_AREA_ELEMCONT_XPOS / MINI_TILEX;
1919   int area_y = ED_AREA_ELEMCONT_YPOS / MINI_TILEY;
1920   int area_sx = SX + ED_AREA_ELEMCONT_XPOS;
1921   int area_sy = SY + ED_AREA_ELEMCONT_YPOS;
1922   int i, x, y;
1923
1924   for (i=0; i<MAX_ELEMCONT; i++)
1925     for (y=0; y<3; y++)
1926       for (x=0; x<3; x++)
1927         ElementContent[i][x][y] = level.mampfer_inhalt[i][x][y];
1928
1929   for (i=0; i<MAX_ELEMCONT; i++)
1930     UnmapDrawingArea(ED_CTRL_ID_ELEMCONT_0 + i);
1931
1932   /* display counter to choose number of element content areas */
1933   gadget_areas_value = num_areas;
1934   DrawCounterValueField(ED_COUNTER_ELEMCONT, *gadget_areas_value);
1935   x = counter_info[ED_COUNTER_ELEMCONT].x + DXSIZE;
1936   y = counter_info[ED_COUNTER_ELEMCONT].y;
1937   DrawTextF(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
1938             FC_YELLOW, "number of content areas");
1939   MapCounterButtons(ED_COUNTER_ELEMCONT);
1940
1941   /* delete content areas in case of reducing number of them */
1942   XFillRectangle(display, backbuffer, gc,
1943                  SX, area_sy - MINI_TILEX,
1944                  SXSIZE, 12 * MINI_TILEY);
1945
1946   /* draw some decorative border for the objects */
1947   for (i=0; i<*num_areas; i++)
1948   {
1949     for (y=0; y<4; y++)
1950       for (x=0; x<4; x++)
1951         DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
1952                         EL_ERDREICH);
1953
1954     XFillRectangle(display, drawto, gc,
1955                    area_sx + 5 * (i % 4) * MINI_TILEX + MINI_TILEX/2 - 1,
1956                    area_sy + 6 * (i / 4) * MINI_TILEY + MINI_TILEY/2 - 1,
1957                    3 * MINI_TILEX + 2, 3 * MINI_TILEY + 2);
1958   }
1959
1960   /* copy border to the right location */
1961   XCopyArea(display, drawto, drawto, gc,
1962             area_sx, area_sy, (5 * 4 + 1) * MINI_TILEX, 12 * MINI_TILEY,
1963             area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
1964
1965   DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 0 * MINI_TILEY + 1,
1966            "Content", FS_SMALL, FC_YELLOW);
1967   DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 1 * MINI_TILEY + 1,
1968            "when", FS_SMALL, FC_YELLOW);
1969   DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 2 * MINI_TILEY + 1,
1970            "smashed", FS_SMALL, FC_YELLOW);
1971
1972   for (i=0; i<*num_areas; i++)
1973   {
1974     for (y=0; y<3; y++)
1975       for (x=0; x<3; x++)
1976         DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
1977                         ElementContent[i][x][y]);
1978
1979     DrawTextF(area_sx - SX + 5 * (i % 4) * MINI_TILEX + MINI_TILEX + 1,
1980               area_sy - SY + 6 * (i / 4) * MINI_TILEY + 4 * MINI_TILEY - 4,
1981               FC_YELLOW, "%d", i + 1);
1982   }
1983
1984   for (i=0; i<*num_areas; i++)
1985     MapDrawingArea(ED_CTRL_ID_ELEMCONT_0 + i);
1986 }
1987
1988 static void DrawAmoebaContentArea()
1989 {
1990   int area_x = ED_AREA_ELEMCONT_XPOS / MINI_TILEX;
1991   int area_y = ED_AREA_ELEMCONT_YPOS / MINI_TILEY;
1992   int area_sx = SX + ED_AREA_ELEMCONT_XPOS;
1993   int area_sy = SY + ED_AREA_ELEMCONT_YPOS;
1994   int x, y;
1995
1996   ElementContent[0][0][0] = level.amoebe_inhalt;
1997
1998   /* draw decorative border for the object */
1999   for (y=0; y<2; y++)
2000     for (x=0; x<2; x++)
2001       DrawMiniElement(area_x + x, area_y + y, EL_ERDREICH);
2002
2003   XFillRectangle(display, drawto, gc,
2004                  area_sx + MINI_TILEX/2 - 1, area_sy + MINI_TILEY/2 - 1,
2005                  MINI_TILEX + 2, MINI_TILEY + 2);
2006
2007   /* copy border to the right location */
2008   XCopyArea(display, drawto, drawto, gc,
2009             area_sx, area_sy, 3 * MINI_TILEX, 3 * MINI_TILEY,
2010             area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
2011
2012   DrawText(area_sx + TILEX, area_sy + 1, "Content of amoeba",
2013            FS_SMALL, FC_YELLOW);
2014
2015   DrawMiniElement(area_x, area_y, ElementContent[0][0][0]);
2016
2017   MapDrawingArea(ED_CTRL_ID_AMOEBA_CONTENT);
2018 }
2019
2020 #define TEXT_COLLECTING         "Score for collecting"
2021 #define TEXT_SMASHING           "Score for smashing"
2022 #define TEXT_CRACKING           "Score for cracking"
2023 #define TEXT_SPEED              "Speed of amoeba growth"
2024 #define TEXT_DURATION           "Duration when activated"
2025
2026 static void DrawPropertiesWindow()
2027 {
2028   int i, x, y;
2029   int num_elements_in_level;
2030   static struct
2031   {
2032     int element;
2033     int *counter_value;
2034     char *text;
2035   } elements_with_counter[] =
2036   {
2037     { EL_EDELSTEIN,     &level.score[0],        TEXT_COLLECTING },
2038     { EL_EDELSTEIN_BD,  &level.score[0],        TEXT_COLLECTING },
2039     { EL_EDELSTEIN_GELB,&level.score[0],        TEXT_COLLECTING },
2040     { EL_EDELSTEIN_ROT, &level.score[0],        TEXT_COLLECTING },
2041     { EL_EDELSTEIN_LILA,&level.score[0],        TEXT_COLLECTING },
2042     { EL_DIAMANT,       &level.score[1],        TEXT_COLLECTING },
2043     { EL_KAEFER_R,      &level.score[2],        TEXT_SMASHING },
2044     { EL_KAEFER_O,      &level.score[2],        TEXT_SMASHING },
2045     { EL_KAEFER_L,      &level.score[2],        TEXT_SMASHING },
2046     { EL_KAEFER_U,      &level.score[2],        TEXT_SMASHING },
2047     { EL_BUTTERFLY_R,   &level.score[2],        TEXT_SMASHING },
2048     { EL_BUTTERFLY_O,   &level.score[2],        TEXT_SMASHING },
2049     { EL_BUTTERFLY_L,   &level.score[2],        TEXT_SMASHING },
2050     { EL_BUTTERFLY_U,   &level.score[2],        TEXT_SMASHING },
2051     { EL_FLIEGER_R,     &level.score[3],        TEXT_SMASHING },
2052     { EL_FLIEGER_O,     &level.score[3],        TEXT_SMASHING },
2053     { EL_FLIEGER_L,     &level.score[3],        TEXT_SMASHING },
2054     { EL_FLIEGER_U,     &level.score[3],        TEXT_SMASHING },
2055     { EL_FIREFLY_R,     &level.score[3],        TEXT_SMASHING },
2056     { EL_FIREFLY_O,     &level.score[3],        TEXT_SMASHING },
2057     { EL_FIREFLY_L,     &level.score[3],        TEXT_SMASHING },
2058     { EL_FIREFLY_U,     &level.score[3],        TEXT_SMASHING },
2059     { EL_MAMPFER,       &level.score[4],        TEXT_SMASHING },
2060     { EL_MAMPFER2,      &level.score[4],        TEXT_SMASHING },
2061     { EL_ROBOT,         &level.score[5],        TEXT_SMASHING },
2062     { EL_PACMAN_R,      &level.score[6],        TEXT_SMASHING },
2063     { EL_PACMAN_O,      &level.score[6],        TEXT_SMASHING },
2064     { EL_PACMAN_L,      &level.score[6],        TEXT_SMASHING },
2065     { EL_PACMAN_U,      &level.score[6],        TEXT_SMASHING },
2066     { EL_KOKOSNUSS,     &level.score[7],        TEXT_CRACKING },
2067     { EL_DYNAMIT_AUS,   &level.score[8],        TEXT_COLLECTING },
2068     { EL_SCHLUESSEL1,   &level.score[9],        TEXT_COLLECTING },
2069     { EL_SCHLUESSEL2,   &level.score[9],        TEXT_COLLECTING },
2070     { EL_SCHLUESSEL3,   &level.score[9],        TEXT_COLLECTING },
2071     { EL_SCHLUESSEL4,   &level.score[9],        TEXT_COLLECTING },
2072     { EL_AMOEBE_NASS,   &level.tempo_amoebe,    TEXT_SPEED },
2073     { EL_AMOEBE_NORM,   &level.tempo_amoebe,    TEXT_SPEED },
2074     { EL_AMOEBE_VOLL,   &level.tempo_amoebe,    TEXT_SPEED },
2075     { EL_AMOEBE_BD,     &level.tempo_amoebe,    TEXT_SPEED },
2076     { EL_SIEB_INAKTIV,  &level.dauer_sieb,      TEXT_DURATION },
2077     { EL_ABLENK_AUS,    &level.dauer_ablenk,    TEXT_DURATION },
2078     { -1, NULL, NULL }
2079   };
2080
2081   ClearWindow();
2082   UnmapLevelEditorWindowGadgets();
2083
2084   /* draw some decorative border for the object */
2085   for (y=0; y<3; y++)
2086     for (x=0; x<3; x++)
2087       DrawMiniElement(2 + x , 2 + y, EL_ERDREICH);
2088
2089   XFillRectangle(display, drawto, gc,
2090                  SX + TILEX + MINI_TILEX/2 - 1,
2091                  SY + TILEY + MINI_TILEY/2 - 1,
2092                  TILEX + 2, TILEY + 2);
2093
2094   /* copy border to the right location */
2095   XCopyArea(display, drawto, drawto, gc,
2096             SX + TILEX, SY + TILEY,
2097             2 * TILEX, 2 * TILEY,
2098             SX + TILEX - MINI_TILEX/2, SY + TILEY - MINI_TILEY/2);
2099
2100   DrawGraphic(1, 1, el2gfx(properties_element));
2101   DrawText(SX + 3*TILEX, SY + 5*TILEY/4, "Element Properties",
2102            FS_SMALL, FC_YELLOW);
2103
2104   num_elements_in_level = 0;
2105   for (y=0; y<lev_fieldy; y++) 
2106     for (x=0; x<lev_fieldx; x++)
2107       if (Feld[x][y] == properties_element)
2108         num_elements_in_level++;
2109
2110   DrawTextF(ED_PROPERTIES_XPOS, 5*TILEY, FC_YELLOW, "%d x contained in level",
2111             num_elements_in_level);
2112
2113   /* check if there are elements where a score can be chosen for */
2114   for (i=0; elements_with_counter[i].element != -1; i++)
2115   {
2116     if (elements_with_counter[i].element == properties_element)
2117     {
2118       int x = counter_info[ED_COUNTER_SCORE].x + DXSIZE;
2119       int y = counter_info[ED_COUNTER_SCORE].y;
2120
2121       gadget_score_value = elements_with_counter[i].counter_value;
2122       DrawCounterValueField(ED_COUNTER_SCORE, *gadget_score_value);
2123       DrawTextF(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2124                 FC_YELLOW, elements_with_counter[i].text);
2125       MapCounterButtons(ED_COUNTER_SCORE);
2126       break;
2127     }
2128   }
2129
2130   if (HAS_CONTENT(properties_element))
2131   {
2132     if (IS_AMOEBOID(properties_element))
2133       DrawAmoebaContentArea();
2134     else
2135       DrawElementContentAreas();
2136   }
2137
2138   /* TEST ONLY: level name text input gadget */
2139   MapTextInputGadget(ED_CTRL_ID_LEVEL_NAME);
2140 }
2141
2142 static void swap_numbers(int *i1, int *i2)
2143 {
2144   int help = *i1;
2145
2146   *i1 = *i2;
2147   *i2 = help;
2148 }
2149
2150 static void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
2151 {
2152   int help_x = *x1;
2153   int help_y = *y1;
2154
2155   *x1 = *x2;
2156   *x2 = help_x;
2157
2158   *y1 = *y2;
2159   *y2 = help_y;
2160 }
2161
2162 static void DrawLineElement(int sx, int sy, int element, boolean change_level)
2163 {
2164   int lx = sx + level_xpos;
2165   int ly = sy + level_ypos;
2166
2167   DrawMiniElement(sx, sy, (element < 0 ? Feld[lx][ly] : element));
2168
2169   if (change_level)
2170     Feld[lx][ly] = element;
2171 }
2172
2173 static void DrawLine(int from_x, int from_y, int to_x, int to_y,
2174                      int element, boolean change_level)
2175 {
2176   if (from_y == to_y)                   /* horizontal line */
2177   {
2178     int x;
2179     int y = from_y;
2180
2181     if (from_x > to_x)
2182       swap_numbers(&from_x, &to_x);
2183
2184     for (x=from_x; x<=to_x; x++)
2185       DrawLineElement(x, y, element, change_level);
2186   }
2187   else if (from_x == to_x)              /* vertical line */
2188   {
2189     int x = from_x;
2190     int y;
2191
2192     if (from_y > to_y)
2193       swap_numbers(&from_y, &to_y);
2194
2195     for (y=from_y; y<=to_y; y++)
2196       DrawLineElement(x, y, element, change_level);
2197   }
2198   else                                  /* diagonal line */
2199   {
2200     int len_x = ABS(to_x - from_x);
2201     int len_y = ABS(to_y - from_y);
2202     int x, y;
2203
2204     if (len_y < len_x)                  /* a < 1 */
2205     {
2206       float a = (float)len_y / (float)len_x;
2207
2208       if (from_x > to_x)
2209         swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2210
2211       for (x=0; x<=len_x; x++)
2212       {
2213         int y = (int)(a * x + 0.5) * (to_y < from_y ? -1 : +1);
2214
2215         DrawLineElement(from_x + x, from_y + y, element, change_level);
2216       }
2217     }
2218     else                                /* a >= 1 */
2219     {
2220       float a = (float)len_x / (float)len_y;
2221
2222       if (from_y > to_y)
2223         swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2224
2225       for (y=0; y<=len_y; y++)
2226       {
2227         int x = (int)(a * y + 0.5) * (to_x < from_x ? -1 : +1);
2228
2229         DrawLineElement(from_x + x, from_y + y, element, change_level);
2230       }
2231     }
2232   }
2233 }
2234
2235 static void DrawRectangle(int from_x, int from_y, int to_x, int to_y,
2236                           int element, boolean change_level)
2237 {
2238   DrawLine(from_x, from_y, from_x, to_y, element, change_level);
2239   DrawLine(from_x, to_y, to_x, to_y, element, change_level);
2240   DrawLine(to_x, to_y, to_x, from_y, element, change_level);
2241   DrawLine(to_x, from_y, from_x, from_y, element, change_level);
2242 }
2243
2244 static void DrawFilledBox(int from_x, int from_y, int to_x, int to_y,
2245                           int element, boolean change_level)
2246 {
2247   int y;
2248
2249   if (from_y > to_y)
2250     swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2251
2252   for (y=from_y; y<=to_y; y++)
2253     DrawLine(from_x, y, to_x, y, element, change_level);
2254 }
2255
2256 static void DrawAreaBorder(int from_x, int from_y, int to_x, int to_y)
2257 {
2258   int from_sx, from_sy;
2259   int to_sx, to_sy;
2260
2261   if (from_x > to_x)
2262     swap_numbers(&from_x, &to_x);
2263
2264   if (from_y > to_y)
2265     swap_numbers(&from_y, &to_y);
2266
2267   from_sx = SX + from_x * MINI_TILEX;
2268   from_sy = SY + from_y * MINI_TILEY;
2269   to_sx = SX + to_x * MINI_TILEX + MINI_TILEX - 1;
2270   to_sy = SY + to_y * MINI_TILEY + MINI_TILEY - 1;
2271
2272   XSetForeground(display, gc, WhitePixel(display, screen));
2273
2274   XDrawLine(display, drawto, gc, from_sx, from_sy, to_sx, from_sy);
2275   XDrawLine(display, drawto, gc, to_sx, from_sy, to_sx, to_sy);
2276   XDrawLine(display, drawto, gc, to_sx, to_sy, from_sx, to_sy);
2277   XDrawLine(display, drawto, gc, from_sx, to_sy, from_sx, from_sy);
2278
2279   XSetForeground(display, gc, BlackPixel(display, screen));
2280
2281   if (from_x == to_x && from_y == to_y)
2282     MarkTileDirty(from_x/2, from_y/2);
2283   else
2284     redraw_mask |= REDRAW_FIELD;
2285 }
2286
2287 static void SelectArea(int from_x, int from_y, int to_x, int to_y,
2288                        int element, boolean change_level)
2289 {
2290   if (element == -1 || change_level)
2291     DrawRectangle(from_x, from_y, to_x, to_y, -1, FALSE);
2292   else
2293     DrawAreaBorder(from_x, from_y, to_x, to_y);
2294 }
2295
2296 /* values for CopyBrushExt() */
2297 #define CB_AREA_TO_BRUSH        0
2298 #define CB_BRUSH_TO_LEVEL       1
2299
2300 static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, int mode)
2301 {
2302   static short brush_buffer[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
2303   static brush_from_x, brush_from_y;
2304   static brush_to_x, brush_to_y;
2305   int x, y;
2306
2307   if (from_x > to_x)
2308     swap_numbers(&from_x, &to_x);
2309
2310   if (from_y > to_y)
2311     swap_numbers(&from_y, &to_y);
2312
2313   if (mode == CB_AREA_TO_BRUSH)
2314   {
2315     for (y=from_y; y<=to_y; y++)
2316       for (x=from_x; x<=to_x; x++)
2317         brush_buffer[x][y] = Feld[x][y];
2318
2319     brush_from_x = from_x;
2320     brush_from_y = from_y;
2321     brush_to_x = to_x;
2322     brush_to_y = to_y;
2323   }
2324   else
2325   {
2326     for (y=brush_from_y; y<=brush_to_y; y++)
2327       for (x=brush_from_x; x<=brush_to_x; x++)
2328         Feld[x][y] = brush_buffer[x][y];
2329     CopyLevelToUndoBuffer();
2330   }
2331 }
2332
2333 static void CopyAreaToBrush(int from_x, int from_y, int to_x, int to_y)
2334 {
2335   CopyBrushExt(from_x, from_y, to_x, to_y, CB_AREA_TO_BRUSH);
2336 }
2337
2338 #if 0
2339 static void CopyBrushToLevel()
2340 {
2341   CopyBrushExt(0, 0, 0, 0, CB_BRUSH_TO_LEVEL);
2342 }
2343 #endif
2344
2345 static void FloodFill(int from_x, int from_y, int fill_element)
2346 {
2347   int i,x,y;
2348   int old_element;
2349   static int check[4][2] = { {-1,0}, {0,-1}, {1,0}, {0,1} };
2350   static int safety = 0;
2351
2352   /* check if starting field still has the desired content */
2353   if (Feld[from_x][from_y] == fill_element)
2354     return;
2355
2356   safety++;
2357
2358   if (safety > lev_fieldx*lev_fieldy)
2359     Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
2360
2361   old_element = Feld[from_x][from_y];
2362   Feld[from_x][from_y] = fill_element;
2363
2364   for(i=0;i<4;i++)
2365   {
2366     x = from_x + check[i][0];
2367     y = from_y + check[i][1];
2368
2369     if (IN_LEV_FIELD(x,y) && Feld[x][y] == old_element)
2370       FloodFill(x, y, fill_element);
2371   }
2372
2373   safety--;
2374 }
2375
2376 /* values for DrawLevelText() modes */
2377 #define TEXT_INIT       0
2378 #define TEXT_SETCURSOR  1
2379 #define TEXT_WRITECHAR  2
2380 #define TEXT_BACKSPACE  3
2381 #define TEXT_NEWLINE    4
2382 #define TEXT_END        5
2383
2384 static void DrawLevelText(int sx, int sy, char letter, int mode)
2385 {
2386   static short delete_buffer[MAX_LEV_FIELDX];
2387   static int start_sx, start_sy;
2388   static int last_sx, last_sy;
2389   static boolean typing = FALSE;
2390   int letter_element = EL_CHAR_ASCII0 + letter;
2391   int lx, ly;
2392
2393   if (mode != TEXT_INIT)
2394   {
2395     if (!typing)
2396       return;
2397
2398     if (mode != TEXT_SETCURSOR)
2399     {
2400       sx = last_sx;
2401       sy = last_sy;
2402     }
2403
2404     lx = last_sx + level_xpos;
2405     ly = last_sy + level_ypos;
2406   }
2407
2408   switch (mode)
2409   {
2410     case TEXT_INIT:
2411       if (typing)
2412         DrawLevelText(0, 0, 0, TEXT_END);
2413
2414       typing = TRUE;
2415       start_sx = last_sx = sx;
2416       start_sy = last_sy = sy;
2417       DrawLevelText(sx, sy, 0, TEXT_SETCURSOR);
2418       break;
2419
2420     case TEXT_SETCURSOR:
2421       DrawMiniElement(last_sx, last_sy, Feld[lx][ly]);
2422       DrawAreaBorder(sx, sy, sx, sy);
2423       last_sx = sx;
2424       last_sy = sy;
2425       break;
2426
2427     case TEXT_WRITECHAR:
2428       if (letter_element >= EL_CHAR_START && letter_element <= EL_CHAR_END)
2429       {
2430         delete_buffer[sx - start_sx] = Feld[lx][ly];
2431         Feld[lx][ly] = letter_element;
2432
2433         if (sx + 1 < 2*SCR_FIELDX && lx + 1 < lev_fieldx)
2434           DrawLevelText(sx + 1, sy, 0, TEXT_SETCURSOR);
2435         else if (sy + 1 < 2*SCR_FIELDY && ly + 1 < lev_fieldy)
2436           DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
2437         else
2438           DrawLevelText(0, 0, 0, TEXT_END);
2439       }
2440       break;
2441
2442     case TEXT_BACKSPACE:
2443       if (sx > start_sx)
2444       {
2445         Feld[lx - 1][ly] = delete_buffer[sx - start_sx - 1];
2446         DrawMiniElement(sx - 1, sy, new_element3);
2447         DrawLevelText(sx - 1, sy, 0, TEXT_SETCURSOR);
2448       }
2449       break;
2450
2451     case TEXT_NEWLINE:
2452       if (sy + 1 < 2*SCR_FIELDY - 1 && ly + 1 < lev_fieldy - 1)
2453         DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
2454       else
2455         DrawLevelText(0, 0, 0, TEXT_END);
2456       break;
2457
2458     case TEXT_END:
2459       CopyLevelToUndoBuffer();
2460       DrawMiniElement(sx, sy, Feld[lx][ly]);
2461       typing = FALSE;
2462       break;
2463
2464     default:
2465       break;
2466   }
2467 }
2468
2469 static void CopyLevelToUndoBuffer()
2470 {
2471   int x, y;
2472
2473   undo_buffer_position = (undo_buffer_position + 1) % NUM_UNDO_STEPS;
2474
2475   if (undo_buffer_steps < NUM_UNDO_STEPS - 1)
2476     undo_buffer_steps++;
2477
2478   for(x=0; x<lev_fieldx; x++)
2479     for(y=0; y<lev_fieldy; y++)
2480       UndoBuffer[undo_buffer_position][x][y] = Feld[x][y];
2481 }
2482
2483 static void RandomPlacement(int button)
2484 {
2485   int new_element;
2486   int x, y;
2487
2488   new_element = (button == 1 ? new_element1 :
2489                  button == 2 ? new_element2 :
2490                  button == 3 ? new_element3 : 0);
2491
2492   if (random_placement_method == RANDOM_USE_PERCENTAGE)
2493   {
2494     for(x=0; x<lev_fieldx; x++)
2495       for(y=0; y<lev_fieldy; y++)
2496         if (RND(100) < random_placement_percentage)
2497           Feld[x][y] = new_element;
2498   }
2499   else
2500   {
2501     int elements_left = random_placement_num_objects;
2502
2503     while (elements_left > 0)
2504     {
2505       x = RND(lev_fieldx);
2506       y = RND(lev_fieldy);
2507
2508       if (Feld[x][y] != new_element)
2509       {
2510         Feld[x][y] = new_element;
2511         elements_left--;
2512       }
2513     }
2514   }
2515
2516   DrawMiniLevel(level_xpos, level_ypos);
2517   CopyLevelToUndoBuffer();
2518 }
2519
2520 static void HandleDrawingAreas(struct GadgetInfo *gi)
2521 {
2522   static boolean started_inside_drawing_area = FALSE;
2523   static boolean draw_with_brush = FALSE;
2524   int id = gi->custom_id;
2525   boolean inside_drawing_area = !gi->event.off_borders;
2526   boolean button_press_event;
2527   boolean button_release_event;
2528   boolean draw_level = (id == ED_CTRL_ID_DRAWING_LEVEL);
2529   int new_element;
2530   int button = gi->event.button;
2531   int sx = gi->event.x, sy = gi->event.y;
2532   int min_sx = 0, min_sy = 0;
2533   int max_sx = gi->drawing.area_xsize - 1, max_sy = gi->drawing.area_ysize - 1;
2534   int lx, ly;
2535   int min_lx = 0, min_ly = 0;
2536   int max_lx = lev_fieldx - 1, max_ly = lev_fieldy - 1;
2537   int x, y;
2538
2539   /*
2540   if (edit_mode != ED_MODE_DRAWING)
2541     return;
2542   */
2543
2544   button_press_event = (gi->event.type == GD_EVENT_PRESSED);
2545   button_release_event = (gi->event.type == GD_EVENT_RELEASED);
2546
2547   /* make sure to stay inside drawing area boundaries */
2548   sx = (sx < min_sx ? min_sx : sx > max_sx ? max_sx : sx);
2549   sy = (sy < min_sy ? min_sy : sy > max_sy ? max_sy : sy);
2550
2551   if (draw_level)
2552   {
2553     /* get positions inside level field */
2554     lx = sx + level_xpos;
2555     ly = sy + level_ypos;
2556
2557     /* make sure to stay inside level field boundaries */
2558     lx = (lx < min_lx ? min_lx : lx > max_lx ? max_lx : lx);
2559     ly = (ly < min_ly ? min_ly : ly > max_ly ? max_ly : ly);
2560
2561     /* correct drawing area positions accordingly */
2562     sx = lx - level_xpos;
2563     sy = ly - level_ypos;
2564   }
2565
2566   if (button_press_event)
2567     started_inside_drawing_area = inside_drawing_area;
2568
2569   if (!started_inside_drawing_area)
2570     return;
2571
2572   if (!button && !button_release_event)
2573     return;
2574
2575   new_element = (button == 1 ? new_element1 :
2576                  button == 2 ? new_element2 :
2577                  button == 3 ? new_element3 : 0);
2578
2579   if (!draw_level && drawing_function != ED_CTRL_ID_SINGLE_ITEMS)
2580     return;
2581
2582   switch (drawing_function)
2583   {
2584     case ED_CTRL_ID_SINGLE_ITEMS:
2585       if (draw_level)
2586       {
2587         if (button_release_event)
2588           CopyLevelToUndoBuffer();
2589
2590         if (!button)
2591           break;
2592
2593         if (new_element != Feld[lx][ly])
2594         {
2595           if (new_element == EL_SPIELFIGUR)
2596           {
2597             /* remove player at old position */
2598             for(y=0; y<lev_fieldy; y++)
2599             {
2600               for(x=0; x<lev_fieldx; x++)
2601               {
2602                 if (Feld[x][y] == EL_SPIELFIGUR || Feld[x][y] == EL_SPIELER1)
2603                 {
2604                   Feld[x][y] = EL_LEERRAUM;
2605                   if (x - level_xpos >= 0 && x - level_xpos < 2*SCR_FIELDX &&
2606                       y - level_ypos >= 0 && y - level_ypos < 2*SCR_FIELDY)
2607                     DrawMiniElement(x - level_xpos, y - level_ypos,
2608                                     EL_LEERRAUM);
2609                 }
2610               }
2611             }
2612           }
2613
2614           Feld[lx][ly] = new_element;
2615           DrawMiniElement(sx, sy, new_element);
2616         }
2617       }
2618       else
2619       {
2620         DrawMiniGraphicExt(drawto, gc,
2621                            gi->x + sx * MINI_TILEX,
2622                            gi->y + sy * MINI_TILEY,
2623                            el2gfx(new_element));
2624         DrawMiniGraphicExt(window, gc,
2625                            gi->x + sx * MINI_TILEX,
2626                            gi->y + sy * MINI_TILEY,
2627                            el2gfx(new_element));
2628
2629         if (id == ED_CTRL_ID_AMOEBA_CONTENT)
2630           level.amoebe_inhalt = new_element;
2631         else if (id >= ED_CTRL_ID_ELEMCONT_0 && id <= ED_CTRL_ID_ELEMCONT_7)
2632           level.mampfer_inhalt[id - ED_CTRL_ID_ELEMCONT_0][sx][sy] =
2633             new_element;
2634       }
2635       break;
2636
2637     case ED_CTRL_ID_CONNECTED_ITEMS:
2638       {
2639         static int last_sx = -1;
2640         static int last_sy = -1;
2641
2642         if (button_release_event)
2643           CopyLevelToUndoBuffer();
2644
2645         if (button)
2646         {
2647           if (!button_press_event)
2648             DrawLine(last_sx, last_sy, sx, sy, new_element, TRUE);
2649
2650           last_sx = sx;
2651           last_sy = sy;
2652         }
2653       }
2654       break;
2655
2656     case ED_CTRL_ID_LINE:
2657     case ED_CTRL_ID_RECTANGLE:
2658     case ED_CTRL_ID_FILLED_BOX:
2659     case ED_CTRL_ID_BRUSH:
2660       {
2661         static int last_sx = -1;
2662         static int last_sy = -1;
2663         static int start_sx = -1;
2664         static int start_sy = -1;
2665         void (*draw_func)(int, int, int, int, int, boolean);
2666
2667         if (drawing_function == ED_CTRL_ID_LINE)
2668           draw_func = DrawLine;
2669         else if (drawing_function == ED_CTRL_ID_RECTANGLE)
2670           draw_func = DrawRectangle;
2671         else if (drawing_function == ED_CTRL_ID_FILLED_BOX)
2672           draw_func = DrawFilledBox;
2673         else
2674           draw_func = SelectArea;
2675
2676         if (button_press_event)
2677         {
2678           draw_func(sx, sy, sx, sy, new_element, FALSE);
2679           start_sx = last_sx = sx;
2680           start_sy = last_sy = sy;
2681         }
2682         else if (button_release_event)
2683         {
2684           draw_func(start_sx, start_sy, sx, sy, new_element, TRUE);
2685           if (drawing_function == ED_CTRL_ID_BRUSH)
2686           {
2687             CopyAreaToBrush(start_sx, start_sy, sx, sy);
2688             draw_with_brush = TRUE;
2689           }
2690           else
2691             CopyLevelToUndoBuffer();
2692         }
2693         else if (last_sx != sx || last_sy != sy)
2694         {
2695           draw_func(start_sx, start_sy, last_sx, last_sy, -1, FALSE);
2696           draw_func(start_sx, start_sy, sx, sy, new_element, FALSE);
2697           last_sx = sx;
2698           last_sy = sy;
2699         }
2700       }
2701       break;
2702
2703     case ED_CTRL_ID_TEXT:
2704       if (button_press_event)
2705         DrawLevelText(sx, sy, 0, TEXT_INIT);
2706       break;
2707
2708     case ED_CTRL_ID_FLOOD_FILL:
2709       if (button_press_event && Feld[lx][ly] != new_element)
2710       {
2711         FloodFill(lx, ly, new_element);
2712         DrawMiniLevel(level_xpos, level_ypos);
2713         CopyLevelToUndoBuffer();
2714       }
2715       break;
2716
2717     case ED_CTRL_ID_PICK_ELEMENT:
2718       if (button_press_event)
2719         PickDrawingElement(button, Feld[lx][ly]);
2720       if (button_release_event)
2721         ClickOnGadget(level_editor_gadget[last_drawing_function]);
2722       break;
2723
2724     default:
2725       break;
2726   }
2727 }
2728
2729 static void HandleCounterButtons(struct GadgetInfo *gi)
2730 {
2731   int id = gi->custom_id;
2732   int button = gi->event.button;
2733   int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
2734
2735   switch (id)
2736   {
2737     case ED_CTRL_ID_SCORE_DOWN:
2738     case ED_CTRL_ID_SCORE_UP:
2739       *gadget_score_value += (id == ED_CTRL_ID_SCORE_DOWN ? -step : step);
2740       if (*gadget_score_value < 0)
2741         *gadget_score_value = 0;
2742       else if (*gadget_score_value > 255)
2743         *gadget_score_value = 255;
2744
2745       DrawCounterValueField(ED_COUNTER_SCORE, *gadget_score_value);
2746       break;
2747
2748     case ED_CTRL_ID_ELEMCONT_DOWN:
2749     case ED_CTRL_ID_ELEMCONT_UP:
2750       *gadget_areas_value += (id == ED_CTRL_ID_ELEMCONT_DOWN ? -step : step);
2751       if (*gadget_areas_value < 1)
2752         *gadget_areas_value = 1;
2753       else if (*gadget_areas_value > MAX_ELEMCONT)
2754         *gadget_areas_value = MAX_ELEMCONT;
2755
2756       DrawCounterValueField(ED_COUNTER_ELEMCONT, *gadget_areas_value);
2757       DrawElementContentAreas();
2758       break;
2759
2760     default:
2761       break;
2762   }
2763 }
2764
2765 static void HandleControlButtons(struct GadgetInfo *gi)
2766 {
2767   int id = gi->custom_id;
2768   int button = gi->event.button;
2769   int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
2770   int new_element;
2771   int player_present = FALSE;
2772   int level_changed = FALSE;
2773   int x, y;
2774
2775   new_element = (button == 1 ? new_element1 :
2776                  button == 2 ? new_element2 :
2777                  button == 3 ? new_element3 : 0);
2778
2779   if (edit_mode == ED_MODE_DRAWING && drawing_function == ED_CTRL_ID_TEXT)
2780     DrawLevelText(0, 0, 0, TEXT_END);
2781
2782   if (id < ED_NUM_CTRL1_BUTTONS && edit_mode != ED_MODE_DRAWING)
2783   {
2784     DrawDrawingWindow();
2785     edit_mode = ED_MODE_DRAWING;
2786   }
2787
2788   switch (id)
2789   {
2790     case ED_CTRL_ID_SINGLE_ITEMS:
2791     case ED_CTRL_ID_CONNECTED_ITEMS:
2792     case ED_CTRL_ID_LINE:
2793     case ED_CTRL_ID_TEXT:
2794     case ED_CTRL_ID_RECTANGLE:
2795     case ED_CTRL_ID_FILLED_BOX:
2796     case ED_CTRL_ID_FLOOD_FILL:
2797     case ED_CTRL_ID_BRUSH:
2798     case ED_CTRL_ID_PICK_ELEMENT:
2799       last_drawing_function = drawing_function;
2800       drawing_function = id;
2801       break;
2802
2803     case ED_CTRL_ID_WRAP_LEFT:
2804       if (level_xpos >= 0)
2805       {
2806         if (lev_fieldx < 2*SCR_FIELDX - 2)
2807           break;
2808
2809         level_xpos -= step;
2810         if (level_xpos <- 1)
2811           level_xpos = -1;
2812         if (button == 1)
2813           ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_RIGHT);
2814         else
2815           DrawMiniLevel(level_xpos, level_ypos);
2816       }
2817       break;
2818
2819     case ED_CTRL_ID_WRAP_RIGHT:
2820       if (level_xpos <= lev_fieldx - 2*SCR_FIELDX)
2821       {
2822         if (lev_fieldx < 2*SCR_FIELDX - 2)
2823           break;
2824
2825         level_xpos += step;
2826         if (level_xpos > lev_fieldx - 2*SCR_FIELDX + 1)
2827           level_xpos = lev_fieldx - 2*SCR_FIELDX + 1;
2828         if (button == 1)
2829           ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_LEFT);
2830         else
2831           DrawMiniLevel(level_xpos, level_ypos);
2832       }
2833       break;
2834
2835     case ED_CTRL_ID_WRAP_UP:
2836       if (level_ypos >= 0)
2837       {
2838         if (lev_fieldy < 2*SCR_FIELDY - 2)
2839           break;
2840
2841         level_ypos -= step;
2842         if (level_ypos < -1)
2843           level_ypos = -1;
2844         if (button == 1)
2845           ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_DOWN);
2846         else
2847           DrawMiniLevel(level_xpos, level_ypos);
2848       }
2849       break;
2850
2851     case ED_CTRL_ID_WRAP_DOWN:
2852       if (level_ypos <= lev_fieldy - 2*SCR_FIELDY)
2853       {
2854         if (lev_fieldy < 2*SCR_FIELDY - 2)
2855           break;
2856
2857         level_ypos += step;
2858         if (level_ypos > lev_fieldy - 2*SCR_FIELDY + 1)
2859           level_ypos = lev_fieldy - 2*SCR_FIELDY + 1;
2860         if (button == 1)
2861           ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_UP);
2862         else
2863           DrawMiniLevel(level_xpos, level_ypos);
2864       }
2865       break;
2866
2867     case ED_CTRL_ID_PROPERTIES:
2868       properties_element = new_element;
2869       DrawPropertiesWindow();
2870       edit_mode = ED_MODE_PROPERTIES;
2871       break;
2872
2873     case ED_CTRL_ID_RANDOM_PLACEMENT:
2874       RandomPlacement(button);
2875       break;
2876
2877     case ED_CTRL_ID_UNDO:
2878       if (undo_buffer_steps == 0)
2879       {
2880         Request("Undo buffer empty !", REQ_CONFIRM);
2881         break;
2882       }
2883
2884       undo_buffer_position =
2885         (undo_buffer_position - 1 + NUM_UNDO_STEPS) % NUM_UNDO_STEPS;
2886       undo_buffer_steps--;
2887
2888       for(x=0; x<lev_fieldx; x++)
2889         for(y=0; y<lev_fieldy; y++)
2890           Feld[x][y] = UndoBuffer[undo_buffer_position][x][y];
2891       DrawMiniLevel(level_xpos,level_ypos);
2892       break;
2893
2894     case ED_CTRL_ID_INFO:
2895       if (edit_mode != ED_MODE_INFO)
2896       {
2897         DrawControlWindow();
2898         edit_mode = ED_MODE_INFO;
2899       }
2900       else
2901       {
2902         DrawDrawingWindow();
2903         edit_mode = ED_MODE_DRAWING;
2904       }
2905       break;
2906
2907     case ED_CTRL_ID_CLEAR:
2908       for(x=0; x<MAX_LEV_FIELDX; x++) 
2909         for(y=0; y<MAX_LEV_FIELDY; y++) 
2910           Feld[x][y] = new_element3;
2911       CopyLevelToUndoBuffer();
2912
2913       DrawMiniLevel(level_xpos, level_ypos);
2914       break;
2915
2916     case ED_CTRL_ID_SAVE:
2917       if (leveldir[leveldir_nr].readonly)
2918       {
2919         Request("This level is read only !", REQ_CONFIRM);
2920         break;
2921       }
2922
2923       for(y=0; y<lev_fieldy; y++) 
2924         for(x=0; x<lev_fieldx; x++)
2925           if (Feld[x][y] != Ur[x][y])
2926             level_changed = TRUE;
2927
2928       if (0 && !level_changed)
2929       {
2930         Request("Level has not changed !", REQ_CONFIRM);
2931         break;
2932       }
2933
2934       for(y=0; y<lev_fieldy; y++) 
2935         for(x=0; x<lev_fieldx; x++)
2936           if (Feld[x][y] == EL_SPIELFIGUR ||
2937               Feld[x][y] == EL_SPIELER1 ||
2938               Feld[x][y] == EL_SP_MURPHY) 
2939             player_present = TRUE;
2940
2941       if (!player_present)
2942         Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
2943       else
2944       {
2945         if (Request("Save this level and kill the old ?", REQ_ASK))
2946         {
2947           for(x=0; x<lev_fieldx; x++)
2948             for(y=0; y<lev_fieldy; y++) 
2949               Ur[x][y] = Feld[x][y];
2950           SaveLevel(level_nr);
2951         }
2952       }
2953       break;
2954
2955     case ED_CTRL_ID_TEST:
2956       for(y=0; y<lev_fieldy; y++) 
2957         for(x=0; x<lev_fieldx; x++)
2958           if (Feld[x][y] == EL_SPIELFIGUR ||
2959               Feld[x][y] == EL_SPIELER1 ||
2960               Feld[x][y] == EL_SP_MURPHY) 
2961             player_present = TRUE;
2962
2963       if (!player_present)
2964         Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
2965       else
2966       {
2967         for(x=0; x<lev_fieldx; x++)
2968           for(y=0; y<lev_fieldy; y++)
2969             OrigBackup[x][y] = Ur[x][y];
2970
2971         for(x=0; x<lev_fieldx; x++)
2972           for(y=0; y<lev_fieldy; y++)
2973             Ur[x][y] = Feld[x][y];
2974
2975         UnmapLevelEditorGadgets();
2976
2977         /* draw smaller door */
2978         XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2979                   DOOR_GFX_PAGEX7, 64,
2980                   108, 64,
2981                   EX - 4, EY - 12);
2982         redraw_mask |= REDRAW_ALL;
2983
2984         CloseDoor(DOOR_CLOSE_ALL);
2985
2986         DrawCompleteVideoDisplay();
2987
2988         if (setup.autorecord)
2989           TapeStartRecording();
2990
2991         level_editor_test_game = TRUE;
2992         game_status = PLAYING;
2993
2994         InitGame();
2995       }
2996       break;
2997
2998     case ED_CTRL_ID_EXIT:
2999       for(y=0; y<lev_fieldy; y++) 
3000         for(x=0; x<lev_fieldx; x++)
3001           if (Feld[x][y] != Ur[x][y])
3002             level_changed = TRUE;
3003
3004       if (!level_changed ||
3005           Request("Level has changed! Exit without saving ?",
3006                   REQ_ASK | REQ_STAY_OPEN))
3007       {
3008         CloseDoor(DOOR_CLOSE_1);
3009
3010         /*
3011         CloseDoor(DOOR_CLOSE_ALL);
3012         */
3013
3014         /* draw smaller door */
3015         XCopyArea(display, pix[PIX_DOOR], drawto, gc,
3016                   DOOR_GFX_PAGEX7, 64,
3017                   108, 64,
3018                   EX - 4, EY - 12);
3019         redraw_mask |= REDRAW_ALL;
3020
3021         game_status = MAINMENU;
3022         DrawMainMenu();
3023       }
3024       else
3025       {
3026         CloseDoor(DOOR_CLOSE_1);
3027         XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
3028                   DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
3029                   DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
3030         OpenDoor(DOOR_OPEN_1);
3031       }
3032       break;
3033
3034     default:
3035       if (gi->event.type == GD_EVENT_PRESSED)
3036         printf("default: HandleControlButtons: GD_EVENT_PRESSED\n");
3037       else if (gi->event.type == GD_EVENT_RELEASED)
3038         printf("default: HandleControlButtons: GD_EVENT_RELEASED\n");
3039       else if (gi->event.type == GD_EVENT_MOVING)
3040         printf("default: HandleControlButtons: GD_EVENT_MOVING\n");
3041       else
3042         printf("default: HandleControlButtons: ?\n");
3043       break;
3044   }
3045 }
3046
3047 void HandleLevelEditorKeyInput(KeySym key)
3048 {
3049   if (edit_mode == ED_MODE_DRAWING && drawing_function == ED_CTRL_ID_TEXT)
3050   {
3051     char letter = getCharFromKeySym(key);
3052
3053     /* map lower case letters to upper case */
3054     if (letter >= 'a' && letter <= 'z')
3055       letter += (int)('A' - 'a');
3056     else if (letter == 'ä')
3057       letter = 'Ä';
3058     else if (letter == 'ä')
3059       letter = 'Ö';
3060     else if (letter == 'ä')
3061       letter = 'Ü';
3062
3063     if (letter)
3064       DrawLevelText(0, 0, letter, TEXT_WRITECHAR);
3065     else if (key == XK_Delete || key == XK_BackSpace)
3066       DrawLevelText(0, 0, 0, TEXT_BACKSPACE);
3067     else if (key == XK_Return)
3068       DrawLevelText(0, 0, 0, TEXT_NEWLINE);
3069   }
3070 }
3071
3072
3073 static void HandleTextInputGadgets(struct GadgetInfo *gi)
3074 {
3075   int id = gi->custom_id;
3076
3077   switch (id)
3078   {
3079     case ED_CTRL_ID_LEVEL_NAME:
3080       strcpy(level.name, gi->text_value);
3081       break;
3082
3083     default:
3084       break;
3085   }
3086 }