rnd-19981215-2
[rocksndiamonds.git] / src / editor.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  (c) 1995-98 Artsoft Entertainment                       *
5 *              Holger Schemel                              *
6 *              Oststrasse 11a                              *
7 *              33604 Bielefeld                             *
8 *              phone: ++49 +521 290471                     *
9 *              email: aeglos@valinor.owl.de                *
10 *----------------------------------------------------------*
11 *  editor.c                                                *
12 ***********************************************************/
13
14 #include "editor.h"
15 #include "screens.h"
16 #include "tools.h"
17 #include "misc.h"
18 #include "buttons.h"
19 #include "files.h"
20 #include "game.h"
21
22 /* positions in the level editor */
23 #define ED_WIN_MB_LEFT_XPOS     7
24 #define ED_WIN_MB_LEFT_YPOS     6
25 #define ED_WIN_LEVELNR_XPOS     77
26 #define ED_WIN_LEVELNR_YPOS     7
27 #define ED_WIN_MB_MIDDLE_XPOS   7
28 #define ED_WIN_MB_MIDDLE_YPOS   258
29 #define ED_WIN_MB_RIGHT_XPOS    77
30 #define ED_WIN_MB_RIGHT_YPOS    258
31
32 /* other constants for the editor */
33 #define ED_SCROLL_NO            0
34 #define ED_SCROLL_LEFT          1
35 #define ED_SCROLL_RIGHT         2
36 #define ED_SCROLL_UP            4
37 #define ED_SCROLL_DOWN          8
38
39 /* delay value to avoid too fast scrolling etc. */
40 #define CHOICE_DELAY_VALUE      100
41
42 /* how many steps can be cancelled */
43 #define NUM_UNDO_STEPS          (10 + 1)
44
45 /* values for random placement */
46 #define RANDOM_USE_PERCENTAGE   0
47 #define RANDOM_USE_NUM_OBJECTS  1
48
49 /* values for the control window */
50 #define ED_CTRL_BUTTONS_GFX_YPOS 236
51 #define ED_CTRL1_BUTTONS_HORIZ  4
52 #define ED_CTRL1_BUTTONS_VERT   4
53 #define ED_CTRL1_BUTTON_XSIZE   22
54 #define ED_CTRL1_BUTTON_YSIZE   22
55 #define ED_CTRL1_BUTTONS_XPOS   6
56 #define ED_CTRL1_BUTTONS_YPOS   6
57 #define ED_CTRL2_BUTTONS_HORIZ  3
58 #define ED_CTRL2_BUTTONS_VERT   2
59 #define ED_CTRL2_BUTTON_XSIZE   30
60 #define ED_CTRL2_BUTTON_YSIZE   20
61 #define ED_CTRL2_BUTTONS_XPOS   5
62 #define ED_CTRL2_BUTTONS_YPOS   100
63 #define ED_NUM_CTRL1_BUTTONS   (ED_CTRL1_BUTTONS_HORIZ * ED_CTRL1_BUTTONS_VERT)
64 #define ED_NUM_CTRL2_BUTTONS   (ED_CTRL2_BUTTONS_HORIZ * ED_CTRL2_BUTTONS_VERT)
65 #define ED_NUM_CTRL_BUTTONS    (ED_NUM_CTRL1_BUTTONS + ED_NUM_CTRL2_BUTTONS)
66
67 /* control button names */
68 #define ED_CTRL_ID_SINGLE_ITEMS         0
69 #define ED_CTRL_ID_CONNECTED_ITEMS      1
70 #define ED_CTRL_ID_LINE                 2
71 #define ED_CTRL_ID_TEXT                 3
72 #define ED_CTRL_ID_RECTANGLE            4
73 #define ED_CTRL_ID_FILLED_BOX           5
74 #define ED_CTRL_ID_WRAP_UP              6
75 #define ED_CTRL_ID_ITEM_PROPERTIES      7
76 #define ED_CTRL_ID_FLOOD_FILL           8
77 #define ED_CTRL_ID_WRAP_LEFT            9
78 #define ED_CTRL_ID_WRAP_RIGHT           11
79 #define ED_CTRL_ID_RANDOM_PLACEMENT     12
80 #define ED_CTRL_ID_BRUSH                13
81 #define ED_CTRL_ID_WRAP_DOWN            14
82 #define ED_CTRL_ID_UNDO                 16
83 #define ED_CTRL_ID_INFO                 17
84 #define ED_CTRL_ID_SAVE                 18
85 #define ED_CTRL_ID_CLEAR                19
86 #define ED_CTRL_ID_TEST                 20
87 #define ED_CTRL_ID_EXIT                 21
88
89 /* forward declaration for internal use */
90 void HandleDrawingFunctions(int, int, int);
91 void HandlePressedControlButtons();
92 void HandleControlButtons(struct GadgetInfo *);
93
94 static struct GadgetInfo *control_button_gadget[ED_NUM_CTRL_BUTTONS];
95 static boolean control_button_gadgets_created = FALSE;
96 static boolean control_button_gadgets_mapped = FALSE;
97
98 static int drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
99
100 static short OrigBackup[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
101 static short UndoBuffer[NUM_UNDO_STEPS][MAX_LEV_FIELDX][MAX_LEV_FIELDY];
102 static int undo_buffer_position = 0;
103 static int undo_buffer_steps = 0;
104
105 static int random_placement_percentage = 10;
106 static int random_placement_num_objects = 10;
107 #if 0
108 static int random_placement_method = RANDOM_USE_PERCENTAGE;
109 #else
110 static int random_placement_method = RANDOM_USE_NUM_OBJECTS;
111 #endif
112
113 static int level_xpos,level_ypos;
114 static boolean edit_mode;
115 static boolean name_typing;
116 static int new_element1 = EL_MAUERWERK;
117 static int new_element2 = EL_LEERRAUM;
118 static int new_element3 = EL_ERDREICH;
119
120 int element_shift;
121 int editor_element[] =
122 {
123   EL_CHAR_A + ('B' - 'A'),
124   EL_CHAR_A + ('O' - 'A'),
125   EL_CHAR_A + ('U' - 'A'),
126   EL_CHAR_A + ('L' - 'A'),
127
128   EL_CHAR_MINUS,
129   EL_CHAR_A + ('D' - 'A'),
130   EL_CHAR_A + ('E' - 'A'),
131   EL_CHAR_A + ('R' - 'A'),
132
133   EL_CHAR_A + ('D' - 'A'),
134   EL_CHAR_A + ('A' - 'A'),
135   EL_CHAR_A + ('S' - 'A'),
136   EL_CHAR_A + ('H' - 'A'),
137
138   EL_SPIELFIGUR,
139   EL_LEERRAUM,
140   EL_ERDREICH,
141   EL_BETON,
142
143   EL_FELSBODEN,
144   EL_SIEB2_LEER,
145   EL_AUSGANG_ZU,
146   EL_AUSGANG_AUF,
147
148   EL_EDELSTEIN_BD,
149   EL_BUTTERFLY_O,
150   EL_FIREFLY_O,
151   EL_FELSBROCKEN,
152
153   EL_BUTTERFLY_L,
154   EL_FIREFLY_L,
155   EL_BUTTERFLY_R,
156   EL_FIREFLY_R,
157
158   EL_AMOEBE_BD,
159   EL_BUTTERFLY_U,
160   EL_FIREFLY_U,
161   EL_LEERRAUM,
162
163   EL_CHAR_A + ('E' - 'A'),
164   EL_CHAR_A + ('M' - 'A'),
165   EL_CHAR_A + ('E' - 'A'),
166   EL_CHAR_MINUS,
167
168   EL_CHAR_A + ('R' - 'A'),
169   EL_CHAR_A + ('A' - 'A'),
170   EL_CHAR_A + ('L' - 'A'),
171   EL_CHAR_A + ('D' - 'A'),
172
173   EL_CHAR_A + ('M' - 'A'),
174   EL_CHAR_A + ('I' - 'A'),
175   EL_CHAR_A + ('N' - 'A'),
176   EL_CHAR_A + ('E' - 'A'),
177
178   EL_SPIELER1,
179   EL_SPIELER2,
180   EL_SPIELER3,
181   EL_SPIELER4,
182
183   EL_SPIELFIGUR,
184   EL_LEERRAUM,
185   EL_ERDREICH,
186   EL_FELSBROCKEN,
187
188   EL_BETON,
189   EL_MAUERWERK,
190   EL_FELSBODEN,
191   EL_SIEB_LEER,
192
193   EL_EDELSTEIN,
194   EL_DIAMANT,
195   EL_KOKOSNUSS,
196   EL_BOMBE,
197
198   EL_ERZ_EDEL,
199   EL_ERZ_DIAM,
200   EL_MORAST_LEER,
201   EL_MORAST_VOLL,
202
203   EL_DYNAMIT_AUS,
204   EL_DYNAMIT,
205   EL_AUSGANG_ZU,
206   EL_AUSGANG_AUF,
207
208   EL_MAMPFER,
209   EL_KAEFER_O,
210   EL_FLIEGER_O,
211   EL_ROBOT,
212
213   EL_KAEFER_L,
214   EL_FLIEGER_L,
215   EL_KAEFER_R,
216   EL_FLIEGER_R,
217
218   EL_ABLENK_AUS,
219   EL_KAEFER_U,
220   EL_FLIEGER_U,
221   EL_UNSICHTBAR,
222
223   EL_BADEWANNE1,
224   EL_SALZSAEURE,
225   EL_BADEWANNE2,
226   EL_LEERRAUM,
227
228   EL_BADEWANNE3,
229   EL_BADEWANNE4,
230   EL_BADEWANNE5,
231   EL_LEERRAUM,
232
233   EL_TROPFEN,
234   EL_AMOEBE_TOT,
235   EL_AMOEBE_NASS,
236   EL_AMOEBE_NORM,
237
238   EL_SCHLUESSEL1,
239   EL_SCHLUESSEL2,
240   EL_SCHLUESSEL3,
241   EL_SCHLUESSEL4,
242
243   EL_PFORTE1,
244   EL_PFORTE2,
245   EL_PFORTE3,
246   EL_PFORTE4,
247
248   EL_PFORTE1X,
249   EL_PFORTE2X,
250   EL_PFORTE3X,
251   EL_PFORTE4X,
252
253   EL_CHAR_A + ('M' - 'A'),
254   EL_CHAR_A + ('O' - 'A'),
255   EL_CHAR_A + ('R' - 'A'),
256   EL_CHAR_A + ('E' - 'A'),
257
258   EL_PFEIL_L,
259   EL_PFEIL_R,
260   EL_PFEIL_O,
261   EL_PFEIL_U,
262
263   EL_AMOEBE_VOLL,
264   EL_EDELSTEIN_GELB,
265   EL_EDELSTEIN_ROT,
266   EL_EDELSTEIN_LILA,
267
268   EL_ERZ_EDEL_BD,
269   EL_ERZ_EDEL_GELB,
270   EL_ERZ_EDEL_ROT,
271   EL_ERZ_EDEL_LILA,
272
273   EL_LIFE,
274   EL_PACMAN_O,
275   EL_ZEIT_VOLL,
276   EL_ZEIT_LEER,
277
278   EL_PACMAN_L,
279   EL_MAMPFER2,
280   EL_PACMAN_R,
281   EL_MAUER_LEBT,
282
283   EL_LIFE_ASYNC,
284   EL_PACMAN_U,
285   EL_BIRNE_AUS,
286   EL_BIRNE_EIN,
287
288   EL_DYNABOMB_NR,
289   EL_DYNABOMB_SZ,
290   EL_DYNABOMB_XL,
291   EL_BADEWANNE,
292
293   EL_MAULWURF,
294   EL_PINGUIN,
295   EL_SCHWEIN,
296   EL_DRACHE,
297
298   EL_SONDE,
299   EL_MAUER_X,
300   EL_MAUER_Y,
301   EL_MAUER_XY,
302
303   EL_CHAR_A + ('S' - 'A'),
304   EL_CHAR_A + ('O' - 'A'),
305   EL_CHAR_A + ('K' - 'A'),
306   EL_CHAR_A + ('O' - 'A'),
307
308   EL_CHAR_MINUS,
309   EL_CHAR_A + ('B' - 'A'),
310   EL_CHAR_A + ('A' - 'A'),
311   EL_CHAR_A + ('N' - 'A'),
312
313   EL_SOKOBAN_OBJEKT,
314   EL_SOKOBAN_FELD_LEER,
315   EL_SOKOBAN_FELD_VOLL,
316   EL_BETON,
317
318 /*
319   EL_CHAR_A + ('D' - 'A'),
320   EL_CHAR_A + ('Y' - 'A'),
321   EL_CHAR_A + ('N' - 'A'),
322   EL_CHAR_A + ('A' - 'A'),
323
324   EL_CHAR_A + ('B' - 'A'),
325   EL_CHAR_A + ('L' - 'A'),
326   EL_CHAR_A + ('A' - 'A'),
327   EL_CHAR_A + ('S' - 'A'),
328
329   EL_CHAR_MINUS,
330   EL_CHAR_A + ('T' - 'A'),
331   EL_CHAR_A + ('E' - 'A'),
332   EL_CHAR_A + ('R' - 'A'),
333 */
334
335   EL_LEERRAUM,
336   EL_LEERRAUM,
337   EL_LEERRAUM,
338   EL_LEERRAUM,
339
340   EL_CHAR_AUSRUF,
341   EL_CHAR_ZOLL,
342   EL_CHAR_DOLLAR,
343   EL_CHAR_PROZ,
344
345   EL_CHAR_APOSTR,
346   EL_CHAR_KLAMM1,
347   EL_CHAR_KLAMM2,
348   EL_CHAR_PLUS,
349
350   EL_CHAR_KOMMA,
351   EL_CHAR_MINUS,
352   EL_CHAR_PUNKT,
353   EL_CHAR_SLASH,
354
355   EL_CHAR_0 + 0,
356   EL_CHAR_0 + 1,
357   EL_CHAR_0 + 2,
358   EL_CHAR_0 + 3,
359
360   EL_CHAR_0 + 4,
361   EL_CHAR_0 + 5,
362   EL_CHAR_0 + 6,
363   EL_CHAR_0 + 7,
364
365   EL_CHAR_0 + 8,
366   EL_CHAR_0 + 9,
367   EL_CHAR_DOPPEL,
368   EL_CHAR_SEMIKL,
369
370   EL_CHAR_LT,
371   EL_CHAR_GLEICH,
372   EL_CHAR_GT,
373   EL_CHAR_FRAGE,
374
375   EL_CHAR_AT,
376   EL_CHAR_A + 0,
377   EL_CHAR_A + 1,
378   EL_CHAR_A + 2,
379
380   EL_CHAR_A + 3,
381   EL_CHAR_A + 4,
382   EL_CHAR_A + 5,
383   EL_CHAR_A + 6,
384
385   EL_CHAR_A + 7,
386   EL_CHAR_A + 8,
387   EL_CHAR_A + 9,
388   EL_CHAR_A + 10,
389
390   EL_CHAR_A + 11,
391   EL_CHAR_A + 12,
392   EL_CHAR_A + 13,
393   EL_CHAR_A + 14,
394
395   EL_CHAR_A + 15,
396   EL_CHAR_A + 16,
397   EL_CHAR_A + 17,
398   EL_CHAR_A + 18,
399
400   EL_CHAR_A + 19,
401   EL_CHAR_A + 20,
402   EL_CHAR_A + 21,
403   EL_CHAR_A + 22,
404
405   EL_CHAR_A + 23,
406   EL_CHAR_A + 24,
407   EL_CHAR_A + 25,
408   EL_CHAR_AE,
409
410   EL_CHAR_OE,
411   EL_CHAR_UE,
412   EL_CHAR_COPY
413 };
414 int elements_in_list = sizeof(editor_element)/sizeof(int);
415
416 void ScrollMiniLevel(int from_x, int from_y, int scroll)
417 {
418   int x,y;
419   int dx = (scroll==ED_SCROLL_LEFT ? -1 : scroll==ED_SCROLL_RIGHT ? 1 : 0);
420   int dy = (scroll==ED_SCROLL_UP   ? -1 : scroll==ED_SCROLL_DOWN  ? 1 : 0);
421
422   XCopyArea(display,drawto,drawto,gc,
423             SX+MINI_TILEX*(dx==-1),SY+MINI_TILEY*(dy==-1),
424             SXSIZE-MINI_TILEX*ABS(dx),SYSIZE-MINI_TILEY*ABS(dy),
425             SX+MINI_TILEX*(dx==+1),SY+MINI_TILEY*(dy==+1));
426   if (dx)
427   {
428     x = (dx==1 ? 0 : 2*SCR_FIELDX-1);
429     for(y=0;y<2*SCR_FIELDY;y++)
430       DrawMiniElementOrWall(x,y,from_x,from_y);
431   }
432   else if (dy)
433   {
434     y = (dy==1 ? 0 : 2*SCR_FIELDY-1);
435     for(x=0;x<2*SCR_FIELDX;x++)
436       DrawMiniElementOrWall(x,y,from_x,from_y);
437   }
438
439   redraw_mask |= REDRAW_FIELD;
440   BackToFront();
441 }
442
443 void CreateLevelEditorControlButtons()
444 {
445   int i;
446
447   if (control_button_gadgets_created)
448     return;
449
450   for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
451   {
452     Pixmap gd_pixmap = pix[PIX_DOOR];
453     struct GadgetInfo *gi;
454     int gd_xoffset, gd_yoffset;
455     int gd_x1, gd_x2, gd_y;
456     int width, height;
457     unsigned long event_mask;
458
459     if (i < ED_NUM_CTRL1_BUTTONS)
460     {
461       int x = i % ED_CTRL1_BUTTONS_HORIZ;
462       int y = i / ED_CTRL1_BUTTONS_HORIZ;
463
464       gd_xoffset = ED_CTRL1_BUTTONS_XPOS + x * ED_CTRL1_BUTTON_XSIZE;
465       gd_yoffset = ED_CTRL1_BUTTONS_YPOS + y * ED_CTRL1_BUTTON_YSIZE;
466       width = ED_CTRL1_BUTTON_XSIZE;
467       height = ED_CTRL1_BUTTON_YSIZE;
468     }
469     else
470     {
471       int x = (i - ED_NUM_CTRL1_BUTTONS) % ED_CTRL2_BUTTONS_HORIZ;
472       int y = (i - ED_NUM_CTRL1_BUTTONS) / ED_CTRL2_BUTTONS_HORIZ;
473
474       gd_xoffset = ED_CTRL2_BUTTONS_XPOS + x * ED_CTRL2_BUTTON_XSIZE;
475       gd_yoffset = ED_CTRL2_BUTTONS_YPOS + y * ED_CTRL2_BUTTON_YSIZE;
476       width = ED_CTRL2_BUTTON_XSIZE;
477       height = ED_CTRL2_BUTTON_YSIZE;
478     }
479
480     gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
481     gd_x2 = DOOR_GFX_PAGEX7 + gd_xoffset;
482     gd_y  = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_GFX_YPOS + gd_yoffset;
483
484     if (i == ED_CTRL_ID_WRAP_LEFT ||
485         i == ED_CTRL_ID_WRAP_RIGHT ||
486         i == ED_CTRL_ID_WRAP_UP ||
487         i == ED_CTRL_ID_WRAP_DOWN)
488       event_mask = GD_EVENT_PRESSED;
489     else
490       event_mask = GD_EVENT_RELEASED;
491
492     gi = CreateGadget(GDI_X, EX + gd_xoffset,
493                       GDI_Y, EY + gd_yoffset,
494                       GDI_WIDTH, width,
495                       GDI_HEIGHT, height,
496                       GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
497                       GDI_STATE, GD_BUTTON_UNPRESSED,
498                       GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
499                       GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
500                       GDI_EVENT_MASK, event_mask,
501                       GDI_CALLBACK, HandleControlButtons,
502                       GDI_END);
503
504     if (gi == NULL)
505       Error(ERR_EXIT, "cannot create gadget");
506
507     control_button_gadget[i] = gi;
508   }
509
510   control_button_gadgets_created = TRUE;
511 }
512
513 void MapLevelEditorControlButtons()
514 {
515   int i;
516
517   if (!control_button_gadgets_created)
518     CreateLevelEditorControlButtons();
519
520   for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
521     MapGadget(control_button_gadget[i]);
522
523   control_button_gadgets_mapped = TRUE;
524 }
525
526 void UnmapLevelEditorControlButtons()
527 {
528   int i;
529
530   if (!control_button_gadgets_created || !control_button_gadgets_mapped)
531     return;
532
533   for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
534     UnmapGadget(control_button_gadget[i]);
535
536   control_button_gadgets_mapped = FALSE;
537 }
538
539 void DrawLevelEd()
540 {
541   int i, x, y, graphic;
542
543   level_xpos=-1;
544   level_ypos=-1;
545   edit_mode = TRUE;
546   name_typing = FALSE;
547   element_shift = 0;
548
549   CloseDoor(DOOR_CLOSE_ALL);
550
551   if (level_editor_test_game)
552   {
553     for(x=0; x<lev_fieldx; x++)
554       for(y=0; y<lev_fieldy; y++)
555         Feld[x][y] = Ur[x][y];
556
557     for(x=0; x<lev_fieldx; x++)
558       for(y=0; y<lev_fieldy; y++)
559         Ur[x][y] = OrigBackup[x][y];
560
561     level_editor_test_game = FALSE;
562   }
563   else
564   {
565     undo_buffer_position = 0;
566     undo_buffer_steps = 0;
567     for(x=0; x<lev_fieldx; x++)
568       for(y=0; y<lev_fieldy; y++)
569         UndoBuffer[0][x][y] = Ur[x][y];
570   }
571
572   DrawMiniLevel(level_xpos,level_ypos);
573   FadeToFront();
574
575   XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
576             DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY1,
577             DXSIZE,DYSIZE,
578             DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
579   XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
580             DOOR_GFX_PAGEX6+ED_BUTTON_ELEM_XPOS,
581             DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS,
582             4*ED_BUTTON_ELEM_XSIZE,5*ED_BUTTON_ELEM_YSIZE,
583             DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS,
584             DOOR_GFX_PAGEY1+ED_BUTTON_EUP_Y2POS);
585
586   for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
587   {
588     if (i < elements_in_list)
589       graphic = el2gfx(editor_element[i]);
590     else
591       graphic = GFX_LEERRAUM;
592
593     DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
594                        DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS+3 + 
595                        (i%MAX_ELEM_X)*ED_BUTTON_ELEM_XSIZE,
596                        DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS+3 +
597                        (i/MAX_ELEM_X)*ED_BUTTON_ELEM_YSIZE,
598                        graphic);
599   }
600
601   DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
602                      DOOR_GFX_PAGEX1+ED_WIN_MB_LEFT_XPOS,
603                      DOOR_GFX_PAGEY1+ED_WIN_MB_LEFT_YPOS,
604                      el2gfx(new_element1));
605   DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
606                      DOOR_GFX_PAGEX1+ED_WIN_MB_MIDDLE_XPOS,
607                      DOOR_GFX_PAGEY1+ED_WIN_MB_MIDDLE_YPOS,
608                      el2gfx(new_element2));
609   DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
610                      DOOR_GFX_PAGEX1+ED_WIN_MB_RIGHT_XPOS,
611                      DOOR_GFX_PAGEY1+ED_WIN_MB_RIGHT_YPOS,
612                      el2gfx(new_element3));
613   DrawTextExt(pix[PIX_DB_DOOR],gc,
614               DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS,
615               DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
616               int2str(level_nr,2),FS_SMALL,FC_SPECIAL1);
617   XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
618             DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+3,
619             DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
620             7,FONT3_YSIZE,
621             DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS,
622             DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
623   XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
624             DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+14,
625             DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
626             7,FONT3_YSIZE,
627             DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS+9,
628             DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
629
630   XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
631             DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
632             VXSIZE,VYSIZE,
633             DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
634
635   /* draw bigger door */
636   XCopyArea(display, pix[PIX_DOOR], drawto, gc,
637             DOOR_GFX_PAGEX7, 0,
638             108, 64,
639             EX - 4, EY - 12);
640
641   /* draw new control window */
642   XCopyArea(display, pix[PIX_DOOR], drawto, gc,
643             DOOR_GFX_PAGEX8, 236,
644             EXSIZE, EYSIZE,
645             EX, EY);
646
647   redraw_mask |= REDRAW_ALL;
648
649   OpenDoor(DOOR_OPEN_1);
650
651   MapLevelEditorControlButtons();
652
653   /*
654   OpenDoor(DOOR_OPEN_1 | DOOR_OPEN_2);
655   */
656 }
657
658 void DrawControlWindow()
659 {
660   int i,x,y;
661
662   ClearWindow();
663
664   /* Inhalt der Mampfer */
665   DrawText(ED_COUNT_GADGET_XPOS+1,SY+6,
666            "Contents of a smashed cruncher:",FS_SMALL,FC_YELLOW);
667   for(i=0;i<4;i++) for(y=0;y<4;y++) for(x=0;x<4;x++)
668   {
669     DrawMiniElement(1+5*i+x,2+y,EL_ERDREICH);
670     XFillRectangle(display,drawto,gc,
671                    SX+(1+5*i)*MINI_TILEX+MINI_TILEX/2-1,
672                    SY+(2)*MINI_TILEY+MINI_TILEY/2-1,
673                    3*MINI_TILEX+2,3*MINI_TILEY+2);
674   }
675   XCopyArea(display,drawto,drawto,gc,
676             SX+1*MINI_TILEX,SY+2*MINI_TILEY,
677             4*5*MINI_TILEX,5*MINI_TILEY,
678             SX+1*MINI_TILEX-MINI_TILEX/2,SY+2*MINI_TILEY-MINI_TILEY/2);
679   for(i=0;i<4;i++)
680   {
681     for(y=0;y<3;y++) for(x=0;x<3;x++)
682       DrawMiniElement(1+5*i+x,2+y,level.mampfer_inhalt[i][x][y]);
683
684     DrawText(SX+MINI_TILEX+(5*i+1)*MINI_TILEX+1,
685              SY+2*MINI_TILEY+(4)*MINI_TILEY-4,
686              int2str(i+1,1),FS_SMALL,FC_YELLOW);
687   }
688
689   /* Inhalt der Amöbe */
690   for(y=0;y<2;y++) for(x=0;x<2;x++)
691   {
692     DrawMiniElement(29+x,26+y,EL_ERDREICH);
693     XFillRectangle(display,drawto,gc,
694                    SX+29*MINI_TILEX+MINI_TILEX/2-1,
695                    SY+26*MINI_TILEY+MINI_TILEY/2-1,
696                    MINI_TILEX+2,MINI_TILEY+2);
697   }
698   XCopyArea(display,drawto,drawto,gc,
699             SX+29*MINI_TILEX,SY+26*MINI_TILEY,
700             3*MINI_TILEX,3*MINI_TILEY,
701             SX+29*MINI_TILEX-MINI_TILEX/2,SY+26*MINI_TILEY-MINI_TILEY/2);
702   DrawMiniElement(29,26,level.amoebe_inhalt);
703
704   for(i=0;i<11+3+2;i++)
705   {
706     XCopyArea(display,pix[PIX_DOOR],drawto,gc,
707               DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
708               DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
709               DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
710               ED_COUNT_GADGET_XPOS,
711               ED_COUNT_GADGET_YPOS+i*ED_COUNT_GADGET_YSIZE);
712
713     if (i<11)
714       DrawText(ED_COUNT_VALUE_XPOS,
715                ED_COUNT_VALUE_YPOS+i*ED_COUNT_GADGET_YSIZE,
716                int2str(level.score[i],3),FS_SMALL,FC_YELLOW);
717     else if (i==11)
718       DrawText(ED_COUNT_VALUE_XPOS,
719                ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
720                int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
721     else if (i==12)
722       DrawText(ED_COUNT_VALUE_XPOS,
723                ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
724                int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
725     else if (i==13)
726       DrawText(ED_COUNT_VALUE_XPOS,
727                ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
728                int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
729     else if (i==14)
730       DrawText(ED_COUNT_VALUE_XPOS,
731                ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
732                int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
733     else if (i==15)
734       DrawText(ED_COUNT_VALUE_XPOS,
735                ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
736                int2str(level.time,3),FS_SMALL,FC_YELLOW);
737   }
738
739   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+0*ED_COUNT_TEXT_YSIZE,
740            "Score for Emerald",FS_SMALL,FC_YELLOW);
741   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+1*ED_COUNT_TEXT_YSIZE,
742            "Score for Diamond",FS_SMALL,FC_YELLOW);
743   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+2*ED_COUNT_TEXT_YSIZE,
744            "Score for smashing a Bug",FS_SMALL,FC_YELLOW);
745   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+3*ED_COUNT_TEXT_YSIZE,
746            "Score for smashing a Spaceship",FS_SMALL,FC_YELLOW);
747   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+4*ED_COUNT_TEXT_YSIZE,
748            "Score for smashing a Cruncher",FS_SMALL,FC_YELLOW);
749   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+5*ED_COUNT_TEXT_YSIZE,
750            "Score for smashing an Alien",FS_SMALL,FC_YELLOW);
751   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+6*ED_COUNT_TEXT_YSIZE,
752            "Score for smashing a Pacman",FS_SMALL,FC_YELLOW);
753   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+7*ED_COUNT_TEXT_YSIZE,
754            "Score for cracking a nut",FS_SMALL,FC_YELLOW);
755   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+8*ED_COUNT_TEXT_YSIZE,
756            "Score for dynamite",FS_SMALL,FC_YELLOW);
757   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+9*ED_COUNT_TEXT_YSIZE,
758            "Score for key",FS_SMALL,FC_YELLOW);
759   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+10*ED_COUNT_TEXT_YSIZE,
760            "Score for each 10 seconds left",FS_SMALL,FC_YELLOW);
761   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+11*ED_COUNT_TEXT_YSIZE,
762            "Speed of the amoeba / Content",FS_SMALL,FC_YELLOW);
763   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+12*ED_COUNT_TEXT_YSIZE,
764            "Time for magic wall",FS_SMALL,FC_YELLOW);
765   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+13*ED_COUNT_TEXT_YSIZE,
766            "Time for wheel",FS_SMALL,FC_YELLOW);
767   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+14*ED_COUNT_TEXT_YSIZE,
768            "Emeralds needed in this level",FS_SMALL,FC_YELLOW);
769   DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+15*ED_COUNT_TEXT_YSIZE,
770            "Time available for this level",FS_SMALL,FC_YELLOW);
771
772   XCopyArea(display,pix[PIX_DOOR],drawto,gc,
773             DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS,
774             DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
775             ED_WIN_COUNT_XSIZE,ED_WIN_COUNT_YSIZE,
776             ED_COUNT_GADGET_XPOS,
777             ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
778   for(i=1;i<31;i++)
779     XCopyArea(display,pix[PIX_DOOR],drawto,gc,
780               DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS+3+2*FONT2_XSIZE,
781               DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
782               ED_WIN_COUNT_XSIZE-3-2*FONT2_XSIZE,ED_WIN_COUNT_YSIZE,
783               ED_COUNT_GADGET_XPOS+3+i*FONT2_XSIZE,
784               ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
785   DrawText(ED_COUNT_GADGET_XPOS+5,
786            ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
787            level.name,FS_SMALL,FC_YELLOW);
788   DrawText(ED_COUNT_GADGET_XPOS+(30+3)*FONT2_XSIZE-5,
789            ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
790            "Title",FS_SMALL,FC_YELLOW);
791
792   DrawText(ED_SIZE_GADGET_XPOS,ED_SIZE_GADGET_YPOS-18,
793            "Playfield size:",FS_SMALL,FC_YELLOW);
794   XCopyArea(display,pix[PIX_DOOR],drawto,gc,
795             DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
796             DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
797             DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
798             ED_SIZE_GADGET_XPOS,
799             ED_SIZE_GADGET_YPOS+0*ED_COUNT_GADGET_YSIZE);
800   XCopyArea(display,pix[PIX_DOOR],drawto,gc,
801             DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
802             DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
803             DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
804             ED_SIZE_GADGET_XPOS,
805             ED_SIZE_GADGET_YPOS+1*ED_COUNT_GADGET_YSIZE);
806   DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+0*ED_SIZE_TEXT_YSIZE,
807            "Width",FS_SMALL,FC_YELLOW);
808   DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+1*ED_SIZE_TEXT_YSIZE,
809            "Height",FS_SMALL,FC_YELLOW);
810   DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
811            int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
812   DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
813            int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
814 }
815
816 void AdjustLevelScrollPosition()
817 {
818   if (level_xpos < -1)
819     level_xpos = -1;
820   if (level_xpos > lev_fieldx - 2*SCR_FIELDX + 1)
821     level_xpos = lev_fieldx - 2*SCR_FIELDX + 1;
822   if (lev_fieldx < 2*SCR_FIELDX - 2)
823     level_xpos = -1;
824
825   if (level_ypos < -1)
826     level_ypos = -1;
827   if (level_ypos > lev_fieldy - 2*SCR_FIELDY + 1)
828     level_ypos = lev_fieldy - 2*SCR_FIELDY + 1;
829   if (lev_fieldy < 2*SCR_FIELDY - 2)
830     level_ypos = -1;
831 }
832
833 void LevelEd(int mx, int my, int button)
834 {
835   static int last_button = 0;
836   static int in_field_pressed = FALSE;
837   static boolean use_floodfill = FALSE;
838
839
840   /*
841   int x = (mx-SX)/MINI_TILEX; 
842   int y = (my-SY)/MINI_TILEY; 
843   */
844
845
846   HandlePressedControlButtons();
847   HandleDrawingFunctions(mx, my, button);
848
849   if (use_floodfill)            /********** FLOOD FILL **********/
850   {
851
852
853 #if 0
854
855     if (button)
856     {
857       if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
858       {
859         int from_x, from_y;
860         int fill_element;
861
862         if (x>lev_fieldx || y>lev_fieldy ||
863             (x==0 && level_xpos<0) ||
864             (x==2*SCR_FIELDX-1 && level_xpos>lev_fieldx-2*SCR_FIELDX) ||
865             (y==0 && level_ypos<0) ||
866             (y==2*SCR_FIELDY-1 && level_ypos>lev_fieldy-2*SCR_FIELDY))
867           return;
868
869         from_x = x+level_xpos;
870         from_y = y+level_ypos;
871         fill_element = (button==1 ? new_element1 :
872                         button==2 ? new_element2 :
873                         button==3 ? new_element3 : 0);
874
875         FloodFill(from_x,from_y,fill_element);
876         DrawMiniLevel(level_xpos,level_ypos);
877       }
878
879       use_floodfill = FALSE;
880       CloseDoor(DOOR_CLOSE_1);
881       OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
882     }
883     return;
884
885 #endif
886
887
888
889   }
890   else                          /********** EDIT/CTRL-FENSTER **********/
891   {
892     static unsigned long choice_delay = 0;
893     int choice = CheckElemButtons(mx,my,button);
894     int elem_pos = choice-ED_BUTTON_ELEM;
895
896     if (((choice == ED_BUTTON_EUP && element_shift>0) ||
897          (choice == ED_BUTTON_EDOWN &&
898           element_shift<elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)) &&
899         DelayReached(&choice_delay, CHOICE_DELAY_VALUE))
900     {
901       int i, step;
902
903       step = (button==1 ? MAX_ELEM_X : button==2 ? 5*MAX_ELEM_X :
904               elements_in_list);
905       element_shift += (choice==ED_BUTTON_EUP ? -step : step);
906       if (element_shift<0)
907         element_shift = 0;
908       if (element_shift>elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)
909         element_shift = elements_in_list-MAX_ELEM_X*MAX_ELEM_Y;
910       if (element_shift % MAX_ELEM_X)
911         element_shift += MAX_ELEM_X-(element_shift % MAX_ELEM_X);
912
913       for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
914         DrawElemButton(i+2,ED_BUTTON_RELEASED);
915     }
916     else if (elem_pos>=0 && elem_pos<MAX_ELEM_X*MAX_ELEM_Y)
917     {
918       int new_element;
919
920       if (elem_pos+element_shift < elements_in_list)
921         new_element = editor_element[elem_pos+element_shift];
922       else
923         new_element = EL_LEERRAUM;
924
925       if (last_button==1)
926         new_element1 = new_element;
927       else if (last_button==2)
928         new_element2 = new_element;
929       else if (last_button==3)
930         new_element3 = new_element;
931
932       DrawMiniGraphicExt(drawto,gc,
933                          DX+ED_WIN_MB_LEFT_XPOS,
934                          DY+ED_WIN_MB_LEFT_YPOS,
935                          el2gfx(new_element1));
936       DrawMiniGraphicExt(drawto,gc,
937                          DX+ED_WIN_MB_MIDDLE_XPOS,
938                          DY+ED_WIN_MB_MIDDLE_YPOS,
939                          el2gfx(new_element2));
940       DrawMiniGraphicExt(drawto,gc,
941                          DX+ED_WIN_MB_RIGHT_XPOS,
942                          DY+ED_WIN_MB_RIGHT_YPOS,
943                          el2gfx(new_element3));
944       redraw_mask |= REDRAW_DOOR_1;
945     }
946   
947     if (edit_mode)              /********** EDIT-FENSTER **********/
948     {
949
950
951
952 #if 0
953
954       switch(CheckEditButtons(mx,my,button))
955       {
956         case ED_BUTTON_CTRL:
957           CloseDoor(DOOR_CLOSE_2);
958           DrawControlWindow();
959           XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
960                     DOOR_GFX_PAGEX4,DOOR_GFX_PAGEY1+80,
961                     VXSIZE,VYSIZE,
962                     DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
963           OpenDoor(DOOR_OPEN_2);
964           edit_mode = FALSE;
965           break;
966         case ED_BUTTON_FILL:
967           Request("Caution ! Flood fill mode ! Choose area !",REQ_OPEN);
968           use_floodfill = TRUE;
969           return;
970           break;
971         case ED_BUTTON_LEFT:
972           if (level_xpos>=0)
973           {
974             if (!DelayReached(&choice_delay, CHOICE_DELAY_VALUE))
975               break;
976             if (lev_fieldx<2*SCR_FIELDX-2)
977               break;
978
979             level_xpos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
980             if (level_xpos<-1)
981               level_xpos = -1;
982             if (button==1)
983               ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_RIGHT);
984             else
985               DrawMiniLevel(level_xpos,level_ypos);
986           }
987           break;
988         case ED_BUTTON_RIGHT:
989           if (level_xpos<=lev_fieldx-2*SCR_FIELDX)
990           {
991             if (!DelayReached(&choice_delay, CHOICE_DELAY_VALUE))
992               break;
993             if (lev_fieldx<2*SCR_FIELDX-2)
994               break;
995
996             level_xpos += (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
997             if (level_xpos>lev_fieldx-2*SCR_FIELDX+1)
998               level_xpos = lev_fieldx-2*SCR_FIELDX+1;
999             if (button==1)
1000               ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_LEFT);
1001             else
1002               DrawMiniLevel(level_xpos,level_ypos);
1003           }
1004           break;
1005         case ED_BUTTON_UP:
1006           if (level_ypos>=0)
1007           {
1008             if (!DelayReached(&choice_delay, CHOICE_DELAY_VALUE))
1009               break;
1010             if (lev_fieldy<2*SCR_FIELDY-2)
1011               break;
1012
1013             level_ypos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1014             if (level_ypos<-1)
1015               level_ypos = -1;
1016             if (button==1)
1017               ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_DOWN);
1018             else
1019               DrawMiniLevel(level_xpos,level_ypos);
1020           }
1021           break;
1022         case ED_BUTTON_DOWN:
1023           if (level_ypos<=lev_fieldy-2*SCR_FIELDY)
1024           {
1025             if (!DelayReached(&choice_delay, CHOICE_DELAY_VALUE))
1026               break;
1027             if (lev_fieldy<2*SCR_FIELDY-2)
1028               break;
1029
1030             level_ypos += (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1031             if (level_ypos>lev_fieldy-2*SCR_FIELDY+1)
1032               level_ypos = lev_fieldy-2*SCR_FIELDY+1;
1033             if (button==1)
1034               ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_UP);
1035             else
1036               DrawMiniLevel(level_xpos,level_ypos);
1037           }
1038           break;
1039         default:
1040           break;
1041       }
1042
1043 #endif
1044
1045
1046
1047 #if 0
1048
1049       if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1050       {
1051         int new_element;
1052
1053         if (button && !motion_status)
1054           in_field_pressed = TRUE;
1055
1056         if (!button || !in_field_pressed || button<1 || button>3 ||
1057             (y==0 && level_ypos<0) ||
1058             (y==2*SCR_FIELDY-1 && level_ypos>lev_fieldy-2*SCR_FIELDY) ||
1059             (x==0 && level_xpos<0) ||
1060             (x==2*SCR_FIELDX-1 && level_xpos>lev_fieldx-2*SCR_FIELDX) ||
1061             x>lev_fieldx || y>lev_fieldy)
1062           return;
1063
1064         new_element = (button==1 ? new_element1 :
1065                        button==2 ? new_element2 :
1066                        button==3 ? new_element3 : 0);
1067
1068         if (new_element != Feld[x+level_xpos][y+level_ypos])
1069         {
1070           if (new_element==EL_SPIELFIGUR) /* Jeder nur EINE Figur bitte... */
1071           {
1072             int x,y;
1073
1074             for(x=0;x<lev_fieldx;x++) for(y=0;y<lev_fieldy;y++)
1075             {
1076               if (Feld[x][y]==EL_SPIELFIGUR || Feld[x][y]==EL_SPIELER1)
1077               {
1078                 Feld[x][y] = EL_LEERRAUM;
1079                 if (x-level_xpos>=0 && x-level_xpos<2*SCR_FIELDX &&
1080                     y-level_ypos>=0 && y-level_ypos<2*SCR_FIELDY)
1081                   DrawMiniElement(x-level_xpos,y-level_ypos,EL_LEERRAUM);
1082               }
1083             }
1084           }
1085
1086           Feld[x+level_xpos][y+level_ypos] = new_element;
1087           DrawMiniElement(x,y,new_element);
1088         }
1089       }
1090       else if (!motion_status)  /* Mauszeiger nicht im Level-Feld */
1091         in_field_pressed = FALSE;
1092
1093 #endif
1094
1095
1096
1097     }
1098     else                        /********** KONTROLL-FENSTER **********/
1099     {
1100       int choice = CheckCountButtons(mx,my,button);
1101       int step = (button==1 ? 1 : button==2 ? 5 : button==3 ? 10 : 0);
1102
1103       if (choice >= 0 && choice < 36 &&
1104           DelayReached(&choice_delay, CHOICE_DELAY_VALUE))
1105       {
1106         if (!(choice % 2))
1107           step = -step;
1108
1109         choice /= 2;
1110
1111         if (choice<11)
1112         {
1113           level.score[choice] += step;
1114           if (level.score[choice]<0)
1115             level.score[choice] = 0;
1116           else if (level.score[choice]>255)
1117             level.score[choice] = 255;
1118         }
1119         else if (choice==11)
1120         {
1121           level.tempo_amoebe += step;
1122           if (level.tempo_amoebe<0)
1123             level.tempo_amoebe = 0;
1124           else if (level.tempo_amoebe>255)
1125             level.tempo_amoebe = 255;
1126         }
1127         else if (choice==12)
1128         {
1129           level.dauer_sieb += step;
1130           if (level.dauer_sieb<0)
1131             level.dauer_sieb = 0;
1132           else if (level.dauer_sieb>255)
1133             level.dauer_sieb = 255;
1134         }
1135         else if (choice==13)
1136         {
1137           level.dauer_ablenk += step;
1138           if (level.dauer_ablenk<0)
1139             level.dauer_ablenk = 0;
1140           else if (level.dauer_ablenk>255)
1141             level.dauer_ablenk = 255;
1142         }
1143         else if (choice==14)
1144         {
1145           level.edelsteine += step;
1146           if (level.edelsteine<0)
1147             level.edelsteine = 0;
1148           else if (level.edelsteine>999)
1149             level.edelsteine = 999;
1150         }
1151         else if (choice==15)
1152         {
1153           level.time += step;
1154           if (level.time<0)
1155             level.time = 0;
1156           else if (level.time>999)
1157             level.time = 999;
1158         }
1159         else if (choice==16)
1160         {
1161           lev_fieldx += step;
1162           if (lev_fieldx<MIN_LEV_FIELDX)
1163             lev_fieldx = MIN_LEV_FIELDX;
1164           else if (lev_fieldx>MAX_LEV_FIELDX)
1165             lev_fieldx = MAX_LEV_FIELDX;
1166           level.fieldx = lev_fieldx;
1167         }
1168         else if (choice==17)
1169         {
1170           lev_fieldy += step;
1171           if (lev_fieldy<MIN_LEV_FIELDY)
1172             lev_fieldy = MIN_LEV_FIELDY;
1173           else if (lev_fieldy>MAX_LEV_FIELDY)
1174             lev_fieldy = MAX_LEV_FIELDY;
1175           level.fieldy = lev_fieldy;
1176         }
1177
1178         if (choice<11)
1179           DrawText(ED_COUNT_VALUE_XPOS,
1180                    ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
1181                    int2str(level.score[choice],3),FS_SMALL,FC_YELLOW);
1182         else if (choice==11)
1183           DrawText(ED_COUNT_VALUE_XPOS,
1184                    ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
1185                    int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
1186         else if (choice==12)
1187           DrawText(ED_COUNT_VALUE_XPOS,
1188                    ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
1189                    int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
1190         else if (choice==13)
1191           DrawText(ED_COUNT_VALUE_XPOS,
1192                    ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
1193                    int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
1194         else if (choice==14)
1195           DrawText(ED_COUNT_VALUE_XPOS,
1196                    ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
1197                    int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
1198         else if (choice==15)
1199           DrawText(ED_COUNT_VALUE_XPOS,
1200                    ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
1201                    int2str(level.time,3),FS_SMALL,FC_YELLOW);
1202         else if (choice==16)
1203           DrawText(ED_SIZE_VALUE_XPOS,
1204                    ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
1205                    int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
1206         else if (choice==17)
1207           DrawText(ED_SIZE_VALUE_XPOS,
1208                    ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
1209                    int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
1210
1211         redraw_mask &= ~REDRAW_FIELD;
1212         if (choice<16)
1213           XCopyArea(display,drawto,window,gc,
1214                     ED_COUNT_VALUE_XPOS,
1215                     ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
1216                     3*FONT2_XSIZE,FONT2_YSIZE,
1217                     ED_COUNT_VALUE_XPOS,
1218                     ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE);
1219         else
1220           XCopyArea(display,drawto,window,gc,
1221                     ED_SIZE_VALUE_XPOS,
1222                     ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE,
1223                     3*FONT2_XSIZE,FONT2_YSIZE,
1224                     ED_SIZE_VALUE_XPOS,
1225                     ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE);
1226         XFlush(display);
1227       }
1228
1229
1230
1231 #if 0
1232
1233       switch(CheckCtrlButtons(mx,my,button))
1234       {
1235         case ED_BUTTON_EDIT:
1236           CloseDoor(DOOR_CLOSE_2);
1237           AdjustLevelScrollPosition();
1238           DrawMiniLevel(level_xpos,level_ypos);
1239           XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1240                     DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
1241                     VXSIZE,VYSIZE,
1242                     DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1243           OpenDoor(DOOR_OPEN_2);
1244           edit_mode = TRUE;
1245           break;
1246         case ED_BUTTON_CLEAR:
1247           if (Request("Are you sure to clear this level ?",REQ_ASK))
1248           {
1249             for(x=0;x<MAX_LEV_FIELDX;x++) 
1250               for(y=0;y<MAX_LEV_FIELDY;y++) 
1251                 Feld[x][y] = EL_ERDREICH;
1252             DrawMiniLevel(level_xpos,level_ypos);
1253           }
1254           break;
1255         case ED_BUTTON_UNDO:
1256           if (leveldir[leveldir_nr].readonly ||
1257               Request("Exit without saving ?",REQ_ASK | REQ_STAY_OPEN))
1258           {
1259             CloseDoor(DOOR_CLOSE_ALL);
1260             game_status=MAINMENU;
1261             DrawMainMenu();
1262           }
1263           else
1264           {
1265             CloseDoor(DOOR_CLOSE_1);
1266             OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
1267           }
1268           break;
1269         case ED_BUTTON_EXIT:
1270           {
1271             int figur_vorhanden = FALSE;
1272
1273             if (leveldir[leveldir_nr].readonly)
1274             {
1275               Request("This level is read only !",REQ_CONFIRM);
1276               break;
1277             }
1278
1279             for(y=0;y<lev_fieldy;y++) 
1280               for(x=0;x<lev_fieldx;x++)
1281                 if (Feld[x][y]==EL_SPIELFIGUR || Feld[x][y]==EL_SPIELER1) 
1282                   figur_vorhanden = TRUE;
1283
1284             if (!figur_vorhanden)
1285               Request("No Level without Gregor Mc Duffin please !",
1286                          REQ_CONFIRM);
1287             else
1288             {
1289               if (Request("Save this level and kill the old ?",
1290                              REQ_ASK | REQ_STAY_OPEN))
1291               {
1292                 for(x=0;x<lev_fieldx;x++)
1293                   for(y=0;y<lev_fieldy;y++) 
1294                     Ur[x][y]=Feld[x][y];
1295                 SaveLevel(level_nr);
1296               }
1297               CloseDoor(DOOR_CLOSE_ALL);
1298               game_status=MAINMENU;
1299               DrawMainMenu();
1300             }
1301           }
1302           break;
1303         default:
1304           break;
1305       }
1306
1307 #endif
1308
1309
1310
1311       if (mx>=ED_COUNT_GADGET_XPOS &&
1312           mx<ED_COUNT_GADGET_XPOS+31*FONT2_XSIZE+10 &&
1313           my>=ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE &&
1314           my<ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE+ED_WIN_COUNT_YSIZE)
1315       {
1316         if (!name_typing)
1317         {
1318           name_typing = TRUE;
1319           DrawText(ED_COUNT_GADGET_XPOS+5,
1320                    ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1321                    level.name,FS_SMALL,FC_GREEN);
1322           DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
1323                    ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1324                    "<",FS_SMALL,FC_RED);
1325         }
1326       }
1327       else
1328       {
1329         if (name_typing)
1330         {
1331           name_typing = FALSE;
1332           DrawText(ED_COUNT_GADGET_XPOS+5,
1333                    ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1334                    level.name,FS_SMALL,FC_YELLOW);
1335           DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
1336                    ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1337                    " ",FS_SMALL,FC_RED);
1338         }
1339       }
1340
1341       if (mx>=SX+29*MINI_TILEX && mx<SX+30*MINI_TILEX &&
1342           my>=SY+26*MINI_TILEY && my<SY+27*MINI_TILEY)
1343       {
1344         int new_element;
1345
1346         if (!button || button<1 || button>3)
1347           return;
1348
1349         new_element = (button==1 ? new_element1 :
1350                        button==2 ? new_element2 :
1351                        button==3 ? new_element3 : 0);
1352
1353         if (new_element != level.amoebe_inhalt)
1354         {
1355           level.amoebe_inhalt = new_element;
1356           DrawMiniElement(29,26,new_element);
1357         }
1358       }
1359
1360       if (mx>=SX+1*MINI_TILEX && mx<SX+(1+4*5)*MINI_TILEX &&
1361           my>=SY+2*MINI_TILEY && my<SY+(2+3)*MINI_TILEY)
1362       {
1363         int x = (mx-SX-1*MINI_TILEX)/MINI_TILEX;
1364         int y = (my-SY-2*MINI_TILEY)/MINI_TILEY;
1365         int i = x/5;
1366         int new_element;
1367
1368         x = x-i*5;
1369         if (i>=0 && i<43 && x>=0 && x<3 && y>=0 && y<3)
1370         {
1371           if (button && !motion_status)
1372             in_field_pressed = TRUE;
1373
1374           if (!button || !in_field_pressed || button<1 || button>3)
1375             return;
1376
1377           new_element = (button==1 ? new_element1 :
1378                          button==2 ? new_element2 :
1379                          button==3 ? new_element3 : 0);
1380
1381           if (new_element != level.mampfer_inhalt[i][x][y])
1382           {
1383             level.mampfer_inhalt[i][x][y] = new_element;
1384             DrawMiniElement(1+5*i+x,2+y,new_element);
1385           }
1386         }
1387         else if (!motion_status)/* Mauszeiger nicht im Cruncher-Feld */
1388           in_field_pressed = FALSE;
1389       }
1390       else if (!motion_status)  /* Mauszeiger nicht im Cruncher-Feld */
1391         in_field_pressed = FALSE;
1392     }
1393   }
1394
1395   last_button = button;
1396
1397   BackToFront();
1398 }
1399
1400 void LevelNameTyping(KeySym key)
1401 {
1402   unsigned char ascii = 0;
1403   int len = strlen(level.name);
1404
1405   if (!name_typing)
1406     return;
1407
1408   if (key>=XK_A && key<=XK_Z)
1409     ascii = 'A'+(char)(key-XK_A);
1410   else if (key>=XK_a && key<=XK_z)
1411     ascii = 'a'+(char)(key-XK_a);
1412   else if (key>=XK_0 && key<=XK_9)
1413     ascii = '0'+(char)(key-XK_0);
1414 #ifdef XK_LATIN1
1415   else if (key>=XK_space && key<=XK_at)
1416     ascii = ' '+(char)(key-XK_space);
1417   else if (key==XK_Adiaeresis)
1418     ascii = 'Ä';
1419   else if (key==XK_Odiaeresis)
1420     ascii = 'Ö';
1421   else if (key==XK_Udiaeresis)
1422     ascii = 'Ãœ';
1423   else if (key==XK_adiaeresis)
1424     ascii = 'ä';
1425   else if (key==XK_odiaeresis)
1426     ascii = 'ö';
1427   else if (key==XK_udiaeresis)
1428     ascii = 'ü';
1429   else if (key==XK_underscore)
1430     ascii = '_';
1431 #endif
1432
1433   if (ascii && len<MAX_LEVNAMLEN-2)
1434   {
1435     level.name[len] = ascii;
1436     level.name[len+1] = 0;
1437     len++;
1438
1439     DrawTextExt(drawto,gc,
1440                 ED_COUNT_GADGET_XPOS+5,
1441                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1442                 level.name,FS_SMALL,FC_GREEN);
1443     DrawTextExt(window,gc,
1444                 ED_COUNT_GADGET_XPOS+5,
1445                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1446                 level.name,FS_SMALL,FC_GREEN);
1447     DrawTextExt(drawto,gc,
1448                 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1449                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1450                 "<",FS_SMALL,FC_RED);
1451     DrawTextExt(window,gc,
1452                 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1453                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1454                 "<",FS_SMALL,FC_RED);
1455   }
1456   else if ((key==XK_Delete || key==XK_BackSpace) && len>0)
1457   {
1458     level.name[len-1] = 0;
1459     len--;
1460
1461     DrawTextExt(drawto,gc,
1462                 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1463                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1464                 "< ",FS_SMALL,FC_GREEN);
1465     DrawTextExt(window,gc,
1466                 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1467                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1468                 "< ",FS_SMALL,FC_GREEN);
1469   }
1470   else if (key==XK_Return)
1471   {
1472     DrawTextExt(drawto,gc,
1473                 ED_COUNT_GADGET_XPOS+5,
1474                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1475                 level.name,FS_SMALL,FC_YELLOW);
1476     DrawTextExt(window,gc,
1477                 ED_COUNT_GADGET_XPOS+5,
1478                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1479                 level.name,FS_SMALL,FC_YELLOW);
1480     DrawTextExt(drawto,gc,
1481                 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1482                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1483                 " ",FS_SMALL,FC_YELLOW);
1484     DrawTextExt(window,gc,
1485                 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
1486                 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1487                 " ",FS_SMALL,FC_YELLOW);
1488
1489     name_typing = FALSE;
1490   }
1491 }
1492
1493 static void swap_numbers(int *i1, int *i2)
1494 {
1495   int help = *i1;
1496
1497   *i1 = *i2;
1498   *i2 = help;
1499 }
1500
1501 static void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
1502 {
1503   int help_x = *x1;
1504   int help_y = *y1;
1505
1506   *x1 = *x2;
1507   *x2 = help_x;
1508
1509   *y1 = *y2;
1510   *y2 = help_y;
1511 }
1512
1513 static void DrawLineElement(int sx, int sy, int element, boolean change_level)
1514 {
1515   int lx = sx + level_xpos;
1516   int ly = sy + level_ypos;
1517
1518   DrawMiniElement(sx, sy, (element < 0 ? Feld[lx][ly] : element));
1519
1520   if (change_level)
1521     Feld[lx][ly] = element;
1522 }
1523
1524 void DrawLine(int from_x, int from_y, int to_x, int to_y, int element,
1525               boolean change_level)
1526 {
1527   if (from_y == to_y)                   /* horizontal line */
1528   {
1529     int x;
1530     int y = from_y;
1531
1532     if (from_x > to_x)
1533       swap_numbers(&from_x, &to_x);
1534
1535     for (x=from_x; x<=to_x; x++)
1536       DrawLineElement(x, y, element, change_level);
1537   }
1538   else if (from_x == to_x)              /* vertical line */
1539   {
1540     int x = from_x;
1541     int y;
1542
1543     if (from_y > to_y)
1544       swap_numbers(&from_y, &to_y);
1545
1546     for (y=from_y; y<=to_y; y++)
1547       DrawLineElement(x, y, element, change_level);
1548   }
1549   else                                  /* diagonal line */
1550   {
1551     int len_x = ABS(to_x - from_x);
1552     int len_y = ABS(to_y - from_y);
1553     int x, y;
1554
1555     if (len_y < len_x)                  /* a < 1 */
1556     {
1557       float a = (float)len_y / (float)len_x;
1558
1559       if (from_x > to_x)
1560         swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
1561
1562       for (x=0; x<=len_x; x++)
1563       {
1564         int y = (int)(a * x + 0.5) * (to_y < from_y ? -1 : +1);
1565
1566         DrawLineElement(from_x + x, from_y + y, element, change_level);
1567       }
1568     }
1569     else                                /* a >= 1 */
1570     {
1571       float a = (float)len_x / (float)len_y;
1572
1573       if (from_y > to_y)
1574         swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
1575
1576       for (y=0; y<=len_y; y++)
1577       {
1578         int x = (int)(a * y + 0.5) * (to_x < from_x ? -1 : +1);
1579
1580         DrawLineElement(from_x + x, from_y + y, element, change_level);
1581       }
1582     }
1583   }
1584 }
1585
1586 void DrawRectangle(int from_x, int from_y, int to_x, int to_y, int element,
1587                    boolean change_level)
1588 {
1589   DrawLine(from_x, from_y, from_x, to_y, element, change_level);
1590   DrawLine(from_x, to_y, to_x, to_y, element, change_level);
1591   DrawLine(to_x, to_y, to_x, from_y, element, change_level);
1592   DrawLine(to_x, from_y, from_x, from_y, element, change_level);
1593 }
1594
1595 void DrawFilledBox(int from_x, int from_y, int to_x, int to_y, int element,
1596                    boolean change_level)
1597 {
1598   int y;
1599
1600   if (from_y > to_y)
1601     swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
1602
1603   for (y=from_y; y<=to_y; y++)
1604     DrawLine(from_x, y, to_x, y, element, change_level);
1605 }
1606
1607 void FloodFill(int from_x, int from_y, int fill_element)
1608 {
1609   int i,x,y;
1610   int old_element;
1611   static int check[4][2] = { {-1,0}, {0,-1}, {1,0}, {0,1} };
1612   static int safety = 0;
1613
1614   /* check if starting field still has the desired content */
1615   if (Feld[from_x][from_y] == fill_element)
1616     return;
1617
1618   safety++;
1619
1620   if (safety > lev_fieldx*lev_fieldy)
1621     Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
1622
1623   old_element = Feld[from_x][from_y];
1624   Feld[from_x][from_y] = fill_element;
1625
1626   for(i=0;i<4;i++)
1627   {
1628     x = from_x + check[i][0];
1629     y = from_y + check[i][1];
1630
1631     if (IN_LEV_FIELD(x,y) && Feld[x][y] == old_element)
1632       FloodFill(x, y, fill_element);
1633   }
1634
1635   safety--;
1636 }
1637
1638 void CopyLevelToUndoBuffer()
1639 {
1640   int x, y;
1641
1642   undo_buffer_position = (undo_buffer_position + 1) % NUM_UNDO_STEPS;
1643
1644   if (undo_buffer_steps < NUM_UNDO_STEPS - 1)
1645     undo_buffer_steps++;
1646
1647   for(x=0; x<lev_fieldx; x++)
1648     for(y=0; y<lev_fieldy; y++)
1649       UndoBuffer[undo_buffer_position][x][y] = Feld[x][y];
1650
1651
1652
1653   /*
1654     printf("state saved to undo buffer %d\n", undo_buffer_position);
1655   */
1656 }
1657
1658 void RandomPlacement(int button)
1659 {
1660   int new_element;
1661   int x, y;
1662
1663   new_element = (button == 1 ? new_element1 :
1664                  button == 2 ? new_element2 :
1665                  button == 3 ? new_element3 : 0);
1666
1667   CopyLevelToUndoBuffer();
1668
1669   if (random_placement_method == RANDOM_USE_PERCENTAGE)
1670   {
1671     for(x=0; x<lev_fieldx; x++)
1672       for(y=0; y<lev_fieldy; y++)
1673         if (RND(100) < random_placement_percentage)
1674           Feld[x][y] = new_element;
1675   }
1676   else
1677   {
1678     int elements_left = random_placement_num_objects;
1679
1680     while (elements_left > 0)
1681     {
1682       x = RND(lev_fieldx);
1683       y = RND(lev_fieldy);
1684
1685       if (Feld[x][y] != new_element)
1686       {
1687         Feld[x][y] = new_element;
1688         elements_left--;
1689       }
1690     }
1691   }
1692
1693   DrawMiniLevel(level_xpos, level_ypos);
1694 }
1695
1696 void HandleDrawingFunctions(int mx, int my, int button)
1697 {
1698   static int last_button = 0;
1699   static int last_element = 0;
1700   boolean button_press_event;
1701   boolean button_release_event;
1702   boolean copy_to_undo_buffer = FALSE;
1703   int new_element;
1704   int sx = (mx - SX) / MINI_TILEX; 
1705   int sy = (my - SY) / MINI_TILEY; 
1706   int lx = sx + level_xpos;
1707   int ly = sy + level_ypos;
1708   int x, y;
1709
1710   if (!edit_mode)
1711     return;
1712
1713   button_press_event = (last_button == 0 && button != 0);
1714   button_release_event = (last_button != 0 && button == 0);
1715   last_button = button;
1716
1717   if (mx < SX || mx >= SX + SXSIZE || my < SY || my >= SY + SYSIZE)
1718     return;
1719
1720   if ((!button && !button_release_event) ||
1721       sx > lev_fieldx || sy > lev_fieldy ||
1722       (sx == 0 && level_xpos<0) ||
1723       (sx == 2*SCR_FIELDX - 1 && level_xpos > lev_fieldx - 2*SCR_FIELDX) ||
1724       (sy == 0 && level_ypos < 0) ||
1725       (sy == 2*SCR_FIELDY - 1 && level_ypos > lev_fieldy - 2*SCR_FIELDY))
1726     return;
1727
1728   new_element = (button == 1 ? new_element1 :
1729                  button == 2 ? new_element2 :
1730                  button == 3 ? new_element3 : 0);
1731
1732   switch (drawing_function)
1733   {
1734     case ED_CTRL_ID_SINGLE_ITEMS:
1735       if (button_release_event)
1736         copy_to_undo_buffer = TRUE;
1737
1738       if (!button)
1739         break;
1740
1741       if (new_element != Feld[lx][ly])
1742       {
1743         if (new_element == EL_SPIELFIGUR)
1744         {
1745           /* remove player at old position */
1746           for(y=0; y<lev_fieldy; y++)
1747           {
1748             for(x=0; x<lev_fieldx; x++)
1749             {
1750               if (Feld[x][y] == EL_SPIELFIGUR || Feld[x][y] == EL_SPIELER1)
1751               {
1752                 Feld[x][y] = EL_LEERRAUM;
1753                 if (x - level_xpos >= 0 && x - level_xpos < 2*SCR_FIELDX &&
1754                     y - level_ypos >= 0 && y - level_ypos < 2*SCR_FIELDY)
1755                   DrawMiniElement(x - level_xpos, y - level_ypos, EL_LEERRAUM);
1756               }
1757             }
1758           }
1759         }
1760
1761         Feld[lx][ly] = new_element;
1762         DrawMiniElement(sx, sy, new_element);
1763       }
1764       break;
1765
1766     case ED_CTRL_ID_CONNECTED_ITEMS:
1767       {
1768         static int last_sx = -1;
1769         static int last_sy = -1;
1770
1771         if (button_release_event)
1772           copy_to_undo_buffer = TRUE;
1773
1774         if (button)
1775         {
1776           if (!button_press_event)
1777             DrawLine(last_sx, last_sy, sx, sy, new_element, TRUE);
1778
1779           last_sx = sx;
1780           last_sy = sy;
1781         }
1782       }
1783       break;
1784
1785     case ED_CTRL_ID_LINE:
1786     case ED_CTRL_ID_RECTANGLE:
1787     case ED_CTRL_ID_FILLED_BOX:
1788       {
1789         static int last_sx = -1;
1790         static int last_sy = -1;
1791         static int start_sx = -1;
1792         static int start_sy = -1;
1793         void (*draw_func)(int, int, int, int, int, boolean);
1794
1795         if (drawing_function == ED_CTRL_ID_LINE)
1796           draw_func = DrawLine;
1797         else if (drawing_function == ED_CTRL_ID_RECTANGLE)
1798           draw_func = DrawRectangle;
1799         else
1800           draw_func = DrawFilledBox;
1801
1802         if (button_press_event)
1803         {
1804           last_sx = start_sx = sx;
1805           last_sy = start_sy = sy;
1806         }
1807         else if (button_release_event)
1808         {
1809           draw_func(start_sx, start_sy, sx, sy, last_element, TRUE);
1810           copy_to_undo_buffer = TRUE;
1811         }
1812         else if (last_sx != sx || last_sy != sy)
1813         {
1814           draw_func(start_sx, start_sy, last_sx, last_sy, -1, FALSE);
1815           draw_func(start_sx, start_sy, sx, sy, new_element, FALSE);
1816           last_sx = sx;
1817           last_sy = sy;
1818         }
1819       }
1820       break;
1821
1822     case ED_CTRL_ID_FLOOD_FILL:
1823       if (button_press_event && Feld[lx][ly] != new_element)
1824       {
1825         FloodFill(lx, ly, new_element);
1826         DrawMiniLevel(level_xpos, level_ypos);
1827         copy_to_undo_buffer = TRUE;
1828       }
1829       break;
1830
1831     default:
1832       break;
1833   }
1834
1835   last_element = new_element;
1836
1837   if (copy_to_undo_buffer)
1838     CopyLevelToUndoBuffer();
1839   copy_to_undo_buffer = FALSE;
1840 }
1841
1842 void HandlePressedControlButtons()
1843 {
1844   static unsigned long button_delay = 0;
1845   int i = 0;
1846
1847   /* buttons with action when held pressed */
1848   int gadget_id[] =
1849   {
1850     ED_CTRL_ID_WRAP_UP,
1851     ED_CTRL_ID_WRAP_LEFT,
1852     ED_CTRL_ID_WRAP_RIGHT,
1853     ED_CTRL_ID_WRAP_DOWN,
1854     -1
1855   };
1856
1857   if (!DelayReached(&button_delay, CHOICE_DELAY_VALUE))
1858     return;
1859
1860   while (gadget_id[i] != -1)
1861   {
1862     int id = gadget_id[i++];
1863     int state = control_button_gadget[id]->state;
1864     int button = control_button_gadget[id]->event.button;
1865     int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
1866
1867     if (state != GD_BUTTON_PRESSED)
1868       continue;
1869   
1870     switch (id)
1871     {
1872       case ED_CTRL_ID_WRAP_LEFT:
1873         if (level_xpos >= 0)
1874         {
1875           if (lev_fieldx < 2*SCR_FIELDX - 2)
1876             break;
1877   
1878           level_xpos -= step;
1879           if (level_xpos <- 1)
1880             level_xpos = -1;
1881           if (button == 1)
1882             ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_RIGHT);
1883           else
1884             DrawMiniLevel(level_xpos, level_ypos);
1885         }
1886         break;
1887   
1888       case ED_CTRL_ID_WRAP_RIGHT:
1889         if (level_xpos <= lev_fieldx - 2*SCR_FIELDX)
1890         {
1891           if (lev_fieldx < 2*SCR_FIELDX - 2)
1892             break;
1893   
1894           level_xpos += step;
1895           if (level_xpos > lev_fieldx - 2*SCR_FIELDX + 1)
1896             level_xpos = lev_fieldx - 2*SCR_FIELDX + 1;
1897           if (button == 1)
1898             ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_LEFT);
1899           else
1900             DrawMiniLevel(level_xpos, level_ypos);
1901         }
1902         break;
1903   
1904       case ED_CTRL_ID_WRAP_UP:
1905         if (level_ypos >= 0)
1906         {
1907           if (lev_fieldy < 2*SCR_FIELDY - 2)
1908             break;
1909   
1910           level_ypos -= step;
1911           if (level_ypos < -1)
1912             level_ypos = -1;
1913           if (button == 1)
1914             ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_DOWN);
1915           else
1916             DrawMiniLevel(level_xpos, level_ypos);
1917         }
1918         break;
1919   
1920       case ED_CTRL_ID_WRAP_DOWN:
1921         if (level_ypos <= lev_fieldy - 2*SCR_FIELDY)
1922         {
1923           if (lev_fieldy < 2*SCR_FIELDY - 2)
1924             break;
1925   
1926           level_ypos += step;
1927           if (level_ypos > lev_fieldy - 2*SCR_FIELDY + 1)
1928             level_ypos = lev_fieldy - 2*SCR_FIELDY + 1;
1929           if (button == 1)
1930             ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_UP);
1931           else
1932             DrawMiniLevel(level_xpos, level_ypos);
1933         }
1934         break;
1935   
1936       default:
1937         break;
1938     }
1939   }
1940 }
1941
1942 void HandleControlButtons(struct GadgetInfo *gi)
1943 {
1944   int event_type = gi->event.type;
1945   int button = gi->event.button;
1946   int player_present = FALSE;
1947   int level_changed = FALSE;
1948   int id;
1949   int i, x, y;
1950
1951   /* get the button id */
1952   for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
1953     if (gi->id == control_button_gadget[i]->id)
1954       id = i;
1955
1956   if (id < ED_NUM_CTRL1_BUTTONS && !edit_mode)
1957   {
1958     AdjustLevelScrollPosition();
1959     DrawMiniLevel(level_xpos, level_ypos);
1960     edit_mode = TRUE;
1961   }
1962
1963   switch (id)
1964   {
1965     case ED_CTRL_ID_SINGLE_ITEMS:
1966     case ED_CTRL_ID_CONNECTED_ITEMS:
1967     case ED_CTRL_ID_LINE:
1968     case ED_CTRL_ID_TEXT:
1969     case ED_CTRL_ID_RECTANGLE:
1970     case ED_CTRL_ID_FILLED_BOX:
1971     case ED_CTRL_ID_FLOOD_FILL:
1972     case ED_CTRL_ID_BRUSH:
1973       drawing_function = id;
1974       break;
1975
1976     case ED_CTRL_ID_RANDOM_PLACEMENT:
1977       RandomPlacement(button);
1978       break;
1979
1980     case ED_CTRL_ID_UNDO:
1981       if (undo_buffer_steps == 0)
1982       {
1983         Request("Undo buffer empty !", REQ_CONFIRM);
1984         break;
1985       }
1986
1987       undo_buffer_position =
1988         (undo_buffer_position - 1 + NUM_UNDO_STEPS) % NUM_UNDO_STEPS;
1989       undo_buffer_steps--;
1990
1991       for(x=0; x<lev_fieldx; x++)
1992         for(y=0; y<lev_fieldy; y++)
1993           Feld[x][y] = UndoBuffer[undo_buffer_position][x][y];
1994       DrawMiniLevel(level_xpos,level_ypos);
1995       break;
1996
1997     case ED_CTRL_ID_INFO:
1998       if (edit_mode)
1999       {
2000         DrawControlWindow();
2001         edit_mode = FALSE;
2002       }
2003       else
2004       {
2005         AdjustLevelScrollPosition();
2006         DrawMiniLevel(level_xpos, level_ypos);
2007         edit_mode = TRUE;
2008       }
2009       break;
2010
2011     case ED_CTRL_ID_CLEAR:
2012       CopyLevelToUndoBuffer();
2013
2014       for(x=0; x<MAX_LEV_FIELDX; x++) 
2015         for(y=0; y<MAX_LEV_FIELDY; y++) 
2016           Feld[x][y] = new_element3;
2017
2018       DrawMiniLevel(level_xpos, level_ypos);
2019       break;
2020
2021     case ED_CTRL_ID_SAVE:
2022       if (leveldir[leveldir_nr].readonly)
2023       {
2024         Request("This level is read only !", REQ_CONFIRM);
2025         break;
2026       }
2027
2028       for(y=0; y<lev_fieldy; y++) 
2029         for(x=0; x<lev_fieldx; x++)
2030           if (Feld[x][y] != Ur[x][y])
2031             level_changed = TRUE;
2032
2033       if (!level_changed)
2034       {
2035         Request("Level has not changed !", REQ_CONFIRM);
2036         break;
2037       }
2038
2039       for(y=0; y<lev_fieldy; y++) 
2040         for(x=0; x<lev_fieldx; x++)
2041           if (Feld[x][y] == EL_SPIELFIGUR || Feld[x][y] == EL_SPIELER1) 
2042             player_present = TRUE;
2043
2044       if (!player_present)
2045         Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
2046       else
2047       {
2048         if (Request("Save this level and kill the old ?", REQ_ASK))
2049         {
2050           for(x=0; x<lev_fieldx; x++)
2051             for(y=0; y<lev_fieldy; y++) 
2052               Ur[x][y] = Feld[x][y];
2053           SaveLevel(level_nr);
2054         }
2055       }
2056       break;
2057
2058     case ED_CTRL_ID_TEST:
2059       for(y=0; y<lev_fieldy; y++) 
2060         for(x=0; x<lev_fieldx; x++)
2061           if (Feld[x][y] == EL_SPIELFIGUR || Feld[x][y] == EL_SPIELER1) 
2062             player_present = TRUE;
2063
2064       if (!player_present)
2065         Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
2066       else
2067       {
2068         for(x=0; x<lev_fieldx; x++)
2069           for(y=0; y<lev_fieldy; y++)
2070             OrigBackup[x][y] = Ur[x][y];
2071
2072         for(x=0; x<lev_fieldx; x++)
2073           for(y=0; y<lev_fieldy; y++)
2074             Ur[x][y] = Feld[x][y];
2075
2076         level_editor_test_game = TRUE;
2077         game_status = PLAYING;
2078         InitGame();
2079       }
2080       break;
2081
2082     case ED_CTRL_ID_EXIT:
2083       for(y=0; y<lev_fieldy; y++) 
2084         for(x=0; x<lev_fieldx; x++)
2085           if (Feld[x][y] != Ur[x][y])
2086             level_changed = TRUE;
2087
2088       if (!level_changed ||
2089           Request("Level has changed! Exit without saving ?",
2090                   REQ_ASK | REQ_STAY_OPEN))
2091       {
2092         CloseDoor(DOOR_CLOSE_1);
2093
2094         /*
2095         CloseDoor(DOOR_CLOSE_ALL);
2096         */
2097
2098         /* draw smaller door */
2099         XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2100                   DOOR_GFX_PAGEX7, 64,
2101                   108, 64,
2102                   EX - 4, EY - 12);
2103         redraw_mask |= REDRAW_ALL;
2104
2105         game_status = MAINMENU;
2106         DrawMainMenu();
2107       }
2108       else
2109       {
2110         CloseDoor(DOOR_CLOSE_1);
2111         XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
2112                   DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2113                   DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2114         OpenDoor(DOOR_OPEN_1);
2115       }
2116       break;
2117
2118     default:
2119       if (event_type == GD_EVENT_PRESSED)
2120         printf("HandleControlButtons: GD_EVENT_PRESSED\n");
2121       else if (event_type == GD_EVENT_RELEASED)
2122         printf("HandleControlButtons: GD_EVENT_RELEASED\n");
2123       else
2124         printf("HandleControlButtons: ?\n");
2125       break;
2126   }
2127 }