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