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