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