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