rnd-19990125-1
[rocksndiamonds.git] / src / tools.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 *  tools.c                                                 *
12 ***********************************************************/
13
14 #include <stdarg.h>
15
16 #ifdef __FreeBSD__
17 #include <machine/joystick.h>
18 #endif
19
20 #include "tools.h"
21 #include "game.h"
22 #include "events.h"
23 #include "sound.h"
24 #include "misc.h"
25 #include "buttons.h"
26 #include "joystick.h"
27 #include "cartoons.h"
28 #include "network.h"
29
30 #ifdef MSDOS
31 extern boolean wait_for_vsync;
32 #endif
33
34 /* tool button identifiers */
35 #define TOOL_CTRL_ID_YES        0
36 #define TOOL_CTRL_ID_NO         1
37 #define TOOL_CTRL_ID_CONFIRM    2
38 #define TOOL_CTRL_ID_PLAYER_1   3
39 #define TOOL_CTRL_ID_PLAYER_2   4
40 #define TOOL_CTRL_ID_PLAYER_3   5
41 #define TOOL_CTRL_ID_PLAYER_4   6
42
43 #define NUM_TOOL_BUTTONS        7
44
45 /* forward declaration for internal use */
46 static void UnmapToolButtons();
47 static void HandleToolButtons(struct GadgetInfo *);
48
49 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
50 static int request_gadget_id = -1;
51
52 void SetDrawtoField(int mode)
53 {
54   if (mode == DRAW_BUFFERED && setup.soft_scrolling)
55   {
56     FX = TILEX;
57     FY = TILEY;
58     BX1 = -1;
59     BY1 = -1;
60     BX2 = SCR_FIELDX;
61     BY2 = SCR_FIELDY;
62     redraw_x1 = 1;
63     redraw_y1 = 1;
64
65     drawto_field = fieldbuffer;
66   }
67   else  /* DRAW_DIRECT, DRAW_BACKBUFFER */
68   {
69     FX = SX;
70     FY = SY;
71     BX1 = 0;
72     BY1 = 0;
73     BX2 = SCR_FIELDX - 1;
74     BY2 = SCR_FIELDY - 1;
75     redraw_x1 = 0;
76     redraw_y1 = 0;
77
78     drawto_field = (mode == DRAW_DIRECT ? window :  backbuffer);
79   }
80 }
81
82 void BackToFront()
83 {
84   int x,y;
85   Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
86
87   if (setup.direct_draw && game_status == PLAYING)
88     redraw_mask &= ~REDRAW_MAIN;
89
90   if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
91     redraw_mask |= REDRAW_FIELD;
92
93   if (redraw_mask & REDRAW_FIELD)
94     redraw_mask &= ~REDRAW_TILES;
95
96   /*
97   if (redraw_mask & REDRAW_FIELD ||
98       (ScreenGfxPos && setup.soft_scrolling && game_status == PLAYING))
99     redraw_mask &= ~REDRAW_TILES;
100   */
101
102   if (!redraw_mask)
103     return;
104
105   /* synchronize X11 graphics at this point; if we would synchronize the
106      display immediately after the buffer switching (after the XFlush),
107      this could mean that we have to wait for the graphics to complete,
108      although we could go on doing calculations for the next frame */
109
110   XSync(display, FALSE);
111
112   /*
113 #ifdef MSDOS
114   wait_for_vsync = TRUE;
115 #endif
116   */
117
118   if (redraw_mask & REDRAW_ALL)
119   {
120     XCopyArea(display,backbuffer,window,gc,
121               0,0, WIN_XSIZE,WIN_YSIZE,
122               0,0);
123     redraw_mask = 0;
124   }
125
126   if (redraw_mask & REDRAW_FIELD)
127   {
128     if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
129       XCopyArea(display,backbuffer,window,gc,
130                 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
131                 REAL_SX,REAL_SY);
132     else
133     {
134       int fx = FX, fy = FY;
135
136       if (setup.soft_scrolling)
137       {
138         fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
139         fy += (ScreenMovDir & (MV_UP | MV_DOWN)    ? ScreenGfxPos : 0);
140       }
141
142       if (setup.soft_scrolling ||
143           ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
144           ABS(ScreenMovPos) == ScrollStepSize ||
145           redraw_tiles > REDRAWTILES_THRESHOLD)
146       {
147         XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
148
149 #ifdef DEBUG
150 #if 0
151         printf("redrawing all (ScreenGfxPos == %d) because %s\n",
152                ScreenGfxPos,
153                (setup.soft_scrolling ?
154                 "setup.soft_scrolling" :
155                 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
156                 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
157                 ABS(ScreenGfxPos) == ScrollStepSize ?
158                 "ABS(ScreenGfxPos) == ScrollStepSize" :
159                 "redraw_tiles > REDRAWTILES_THRESHOLD"));
160 #endif
161 #endif
162       }
163     }
164     redraw_mask &= ~REDRAW_MAIN;
165   }
166
167   if (redraw_mask & REDRAW_DOORS)
168   {
169     if (redraw_mask & REDRAW_DOOR_1)
170       XCopyArea(display,backbuffer,window,gc,
171                 DX,DY, DXSIZE,DYSIZE,
172                 DX,DY);
173     if (redraw_mask & REDRAW_DOOR_2)
174     {
175       if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
176         XCopyArea(display,backbuffer,window,gc,
177                   VX,VY, VXSIZE,VYSIZE,
178                   VX,VY);
179       else
180       {
181         if (redraw_mask & REDRAW_VIDEO_1)
182           XCopyArea(display,backbuffer,window,gc,
183                     VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
184                     VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
185                     VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
186         if (redraw_mask & REDRAW_VIDEO_2)
187           XCopyArea(display,backbuffer,window,gc,
188                     VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
189                     VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
190                     VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
191         if (redraw_mask & REDRAW_VIDEO_3)
192           XCopyArea(display,backbuffer,window,gc,
193                     VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
194                     VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
195                     VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
196       }
197     }
198     if (redraw_mask & REDRAW_DOOR_3)
199       XCopyArea(display, backbuffer, window, gc,
200                 EX, EY, EXSIZE, EYSIZE,
201                 EX, EY);
202     redraw_mask &= ~REDRAW_DOORS;
203   }
204
205   if (redraw_mask & REDRAW_MICROLEVEL)
206   {
207     XCopyArea(display,backbuffer,window,gc,
208               MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
209               MICROLEV_XPOS, MICROLEV_YPOS);
210     XCopyArea(display,backbuffer,window,gc,
211               SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
212               SX, MICROLABEL_YPOS);
213     redraw_mask &= ~REDRAW_MICROLEVEL;
214   }
215
216   if (redraw_mask & REDRAW_TILES)
217   {
218     for(x=0; x<SCR_FIELDX; x++)
219       for(y=0; y<SCR_FIELDY; y++)
220         if (redraw[redraw_x1 + x][redraw_y1 + y])
221           XCopyArea(display,buffer,window,gc,
222                     FX+x*TILEX,FX+y*TILEY, TILEX,TILEY,
223                     SX+x*TILEX,SY+y*TILEY);
224   }
225
226   XFlush(display);
227
228   for(x=0; x<MAX_BUF_XSIZE; x++)
229     for(y=0; y<MAX_BUF_YSIZE; y++)
230       redraw[x][y] = 0;
231   redraw_tiles = 0;
232   redraw_mask = 0;
233 }
234
235 void FadeToFront()
236 {
237 /*
238   long fading_delay = 300;
239
240   if (setup.fading && (redraw_mask & REDRAW_FIELD))
241   {
242 */
243
244 /*
245     int x,y;
246
247     XFillRectangle(display,window,gc,
248                    REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
249     XFlush(display);
250
251     for(i=0;i<2*FULL_SYSIZE;i++)
252     {
253       for(y=0;y<FULL_SYSIZE;y++)
254       {
255         XCopyArea(display,backbuffer,window,gc,
256                   REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
257       }
258       XFlush(display);
259       Delay(10);
260     }
261 */
262
263 /*
264     for(i=1;i<FULL_SYSIZE;i+=2)
265       XCopyArea(display,backbuffer,window,gc,
266                 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
267     XFlush(display);
268     Delay(fading_delay);
269 */
270
271 /*
272     XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
273     XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
274               REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
275     XFlush(display);
276     Delay(fading_delay);
277
278     XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
279     XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
280               REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
281     XFlush(display);
282     Delay(fading_delay);
283
284     XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
285     XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
286               REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
287     XFlush(display);
288     Delay(fading_delay);
289
290     XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
291     XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
292               REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
293     XFlush(display);
294     Delay(fading_delay);
295
296     redraw_mask &= ~REDRAW_MAIN;
297   }
298 */
299
300   BackToFront();
301 }
302
303 void ClearWindow()
304 {
305   XFillRectangle(display, backbuffer, gc,
306                  REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
307
308   if (setup.soft_scrolling && game_status == PLAYING)
309   {
310     XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
311     SetDrawtoField(DRAW_BUFFERED);
312   }
313   else
314     SetDrawtoField(DRAW_BACKBUFFER);
315
316   if (setup.direct_draw && game_status == PLAYING)
317   {
318     XFillRectangle(display, window, gc,
319                    REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
320     SetDrawtoField(DRAW_DIRECT);
321   }
322
323   redraw_mask |= REDRAW_FIELD;
324 }
325
326 void DrawTextFCentered(int y, int font_type, char *format, ...)
327 {
328   char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
329   int font_xsize;
330   va_list ap;
331
332   font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
333                 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
334
335   va_start(ap, format);
336   vsprintf(buffer, format, ap);
337   va_end(ap);
338
339   DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
340            buffer, FS_SMALL, font_type);
341 }
342
343 void DrawTextF(int x, int y, int font_type, char *format, ...)
344 {
345   char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
346   va_list ap;
347
348   va_start(ap, format);
349   vsprintf(buffer, format, ap);
350   va_end(ap);
351
352   DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
353 }
354
355 void DrawText(int x, int y, char *text, int font_size, int font_type)
356 {
357   DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
358
359   if (x < DX)
360     redraw_mask |= REDRAW_FIELD;
361   else if (y < VY)
362     redraw_mask |= REDRAW_DOOR_1;
363 }
364
365 void DrawTextExt(Drawable d, GC gc, int x, int y,
366                  char *text, int font_size, int font_type)
367 {
368   int font_width, font_height, font_start;
369   int font_pixmap;
370   boolean print_inverse = FALSE;
371
372   if (font_size != FS_SMALL && font_size != FS_BIG)
373     font_size = FS_SMALL;
374   if (font_type < FC_RED || font_type > FC_SPECIAL2)
375     font_type = FC_RED;
376
377   font_width = (font_size == FS_BIG ? FONT1_XSIZE :
378                 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
379                 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
380   font_height = (font_size == FS_BIG ? FONT1_XSIZE :
381                  font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
382   font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
383   font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
384                 FONT_LINES_PER_FONT);
385
386   while (*text)
387   {
388     char c = *text++;
389
390     if (c == '~' && font_size == FS_SMALL && font_type <= FC_YELLOW)
391     {
392       print_inverse = TRUE;
393       continue;
394     }
395
396     if (c >= 'a' && c <= 'z')
397       c = 'A' + (c - 'a');
398     else if (c == 'ä' || c == 'Ä')
399       c = 91;
400     else if (c == 'ö' || c == 'Ö')
401       c = 92;
402     else if (c == 'ü' || c == 'Ãœ')
403       c = 93;
404
405     if (c >= 32 && c <= 95)
406     {
407       int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
408       int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
409       int dest_x = x, dest_y = y;
410
411       if (print_inverse)
412       {
413         XCopyArea(display, pix[font_pixmap], d, gc,
414                   FONT_CHARS_PER_LINE * font_width,
415                   3 * font_height + font_start,
416                   font_width, font_height, x, y);
417
418         XSetClipOrigin(display, clip_gc[font_pixmap],
419                        dest_x - src_x, dest_y - src_y);
420         XCopyArea(display, pix[font_pixmap], drawto, clip_gc[font_pixmap],
421                   0, 0, font_width, font_height, dest_x, dest_y);
422       }
423       else
424         XCopyArea(display, pix[font_pixmap], d, gc,
425                   src_x, src_y, font_width, font_height, dest_x, dest_y);
426     }
427
428     x += font_width;
429   }
430 }
431
432 void DrawAllPlayers()
433 {
434   int i;
435
436   for(i=0; i<MAX_PLAYERS; i++)
437     if (stored_player[i].active)
438       DrawPlayer(&stored_player[i]);
439 }
440
441 void DrawPlayerField(int x, int y)
442 {
443   if (!IS_PLAYER(x,y))
444     return;
445
446   DrawPlayer(PLAYERINFO(x,y));
447 }
448
449 void DrawPlayer(struct PlayerInfo *player)
450 {
451   int jx = player->jx, jy = player->jy;
452   int last_jx = player->last_jx, last_jy = player->last_jy;
453   int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
454   int sx = SCREENX(jx), sy = SCREENY(jy);
455   int sxx = 0, syy = 0;
456   int element = Feld[jx][jy];
457   int graphic, phase;
458
459   if (!player->active || player->gone ||
460       !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
461     return;
462
463 #if DEBUG
464   if (!IN_LEV_FIELD(jx,jy))
465   {
466     printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
467     printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
468     printf("DrawPlayerField(): This should never happen!\n");
469     return;
470   }
471 #endif
472
473   if (element == EL_EXPLODING)
474     return;
475
476   /* draw things in the field the player is leaving, if needed */
477
478   if (last_jx != jx || last_jy != jy)
479   {
480     if (Store[last_jx][last_jy])
481     {
482       DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
483       DrawLevelFieldThruMask(last_jx, last_jy);
484     }
485     else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
486       DrawDynamite(last_jx, last_jy);
487     else
488       DrawLevelField(last_jx, last_jy);
489
490     if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
491     {
492       if (player->GfxPos)
493       {
494         if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
495           DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
496         else
497           DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
498       }
499       else
500         DrawLevelField(next_jx, next_jy);
501     }
502   }
503
504   if (!IN_SCR_FIELD(sx, sy))
505     return;
506
507   if (setup.direct_draw)
508     SetDrawtoField(DRAW_BUFFERED);
509
510   /* draw things behind the player, if needed */
511
512   if (Store[jx][jy])
513     DrawLevelElement(jx, jy, Store[jx][jy]);
514   else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
515     DrawLevelField(jx, jy);
516
517   /* draw player himself */
518
519   if (player->MovDir == MV_LEFT)
520     graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
521   else if (player->MovDir == MV_RIGHT)
522     graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
523   else if (player->MovDir == MV_UP)
524     graphic = GFX_SPIELER1_UP;
525   else  /* MV_DOWN || MV_NO_MOVING */
526     graphic = GFX_SPIELER1_DOWN;
527
528   graphic += player->index_nr * 3*HEROES_PER_LINE;
529   graphic += player->Frame;
530
531   if (player->GfxPos)
532   {
533     if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
534       sxx = player->GfxPos;
535     else
536       syy = player->GfxPos;
537   }
538
539   if (!setup.soft_scrolling && ScreenMovPos)
540     sxx = syy = 0;
541
542   DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
543
544   if (player->Pushing && player->GfxPos)
545   {
546     int px = SCREENX(next_jx), py = SCREENY(next_jy);
547
548     if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
549         Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
550       DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
551                                  NO_CUTTING);
552     else
553     {
554       int element = Feld[next_jx][next_jy];
555       int graphic = el2gfx(element);
556
557       if (element == EL_FELSBROCKEN && sxx)
558       {
559         int phase = (player->GfxPos / (TILEX/4));
560
561         if (player->MovDir == MV_LEFT)
562           graphic += phase;
563         else
564           graphic += (phase+4)%4;
565       }
566
567       DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
568     }
569   }
570
571   /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
572
573   if (element == EL_DYNAMIT || element == EL_DYNABOMB)
574   {
575     graphic = el2gfx(element);
576
577     if (element == EL_DYNAMIT)
578     {
579       if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
580         phase = 6;
581     }
582     else
583     {
584       if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
585         phase = 7 - phase;
586     }
587
588     if (game_emulation == EMU_SUPAPLEX)
589       DrawGraphic(sx, sy, GFX_SP_DISK_RED);
590     else
591       DrawGraphicThruMask(sx, sy, graphic + phase);
592   }
593
594   if ((last_jx != jx || last_jy != jy) &&
595       Feld[last_jx][last_jy] == EL_EXPLODING)
596   {
597     int phase = Frame[last_jx][last_jy];
598     int delay = 2;
599
600     if (phase > 2)
601       DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
602                           GFX_EXPLOSION + ((phase - 1) / delay - 1));
603   }
604
605   if (setup.direct_draw)
606   {
607     int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
608     int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
609     int x_size = TILEX * (1 + ABS(jx - last_jx));
610     int y_size = TILEY * (1 + ABS(jy - last_jy));
611
612     XCopyArea(display, drawto_field, window, gc,
613               dest_x, dest_y, x_size, y_size, dest_x, dest_y);
614     SetDrawtoField(DRAW_DIRECT);
615   }
616
617   MarkTileDirty(sx,sy);
618 }
619
620 static int getGraphicAnimationPhase(int frames, int delay, int mode)
621 {
622   int phase;
623
624   if (mode == ANIM_OSCILLATE)
625   {
626     int max_anim_frames = 2 * frames - 2;
627     phase = (FrameCounter % (delay * max_anim_frames)) / delay;
628     phase = (phase < frames ? phase : max_anim_frames - phase);
629   }
630   else
631     phase = (FrameCounter % (delay * frames)) / delay;
632
633   if (mode == ANIM_REVERSE)
634     phase = -phase;
635
636   return(phase);
637 }
638
639 void DrawGraphicAnimationExt(int x, int y, int graphic,
640                              int frames, int delay, int mode, int mask_mode)
641 {
642   int phase = getGraphicAnimationPhase(frames, delay, mode);
643
644   if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
645   {
646     if (mask_mode == USE_MASKING)
647       DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
648     else
649       DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
650   }
651 }
652
653 void DrawGraphicAnimation(int x, int y, int graphic,
654                           int frames, int delay, int mode)
655 {
656   DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
657 }
658
659 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
660                                   int frames, int delay, int mode)
661 {
662   DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
663 }
664
665 void DrawGraphic(int x, int y, int graphic)
666 {
667 #if DEBUG
668   if (!IN_SCR_FIELD(x,y))
669   {
670     printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
671     printf("DrawGraphic(): This should never happen!\n");
672     return;
673   }
674 #endif
675
676   DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
677   MarkTileDirty(x,y);
678 }
679
680 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
681 {
682   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
683   {
684     graphic -= GFX_START_ROCKSSCREEN;
685     XCopyArea(display, pix[PIX_BACK], d, gc,
686               SX + (graphic % GFX_PER_LINE) * TILEX,
687               SY + (graphic / GFX_PER_LINE) * TILEY,
688               TILEX, TILEY, x, y);
689   }
690   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
691   {
692     graphic -= GFX_START_ROCKSMORE;
693     XCopyArea(display, pix[PIX_MORE], d, gc,
694               (graphic % MORE_PER_LINE) * TILEX,
695               (graphic / MORE_PER_LINE) * TILEY,
696               TILEX, TILEY, x, y);
697   }
698   else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
699   {
700     graphic -= GFX_START_ROCKSHEROES;
701     XCopyArea(display, pix[PIX_HEROES], d, gc,
702               (graphic % HEROES_PER_LINE) * TILEX,
703               (graphic / HEROES_PER_LINE) * TILEY,
704               TILEX, TILEY, x, y);
705   }
706   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
707   {
708     graphic -= GFX_START_ROCKSFONT;
709     XCopyArea(display, pix[PIX_BIGFONT], d, gc,
710               (graphic % FONT_CHARS_PER_LINE) * TILEX,
711               (graphic / FONT_CHARS_PER_LINE) * TILEY +
712               FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
713               TILEX, TILEY, x, y);
714   }
715   else
716     XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
717 }
718
719 void DrawGraphicThruMask(int x, int y, int graphic)
720 {
721 #if DEBUG
722   if (!IN_SCR_FIELD(x,y))
723   {
724     printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
725     printf("DrawGraphicThruMask(): This should never happen!\n");
726     return;
727   }
728 #endif
729
730   DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
731   MarkTileDirty(x,y);
732 }
733
734 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
735 {
736   int src_x, src_y;
737   int tile = graphic;
738   Pixmap src_pixmap;
739   GC drawing_gc;
740
741   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
742   {
743     src_pixmap = pix[PIX_BACK];
744     drawing_gc = clip_gc[PIX_BACK];
745     graphic -= GFX_START_ROCKSSCREEN;
746     src_x  = SX + (graphic % GFX_PER_LINE) * TILEX;
747     src_y  = SY + (graphic / GFX_PER_LINE) * TILEY;
748   }
749   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
750   {
751     src_pixmap = pix[PIX_MORE];
752     drawing_gc = clip_gc[PIX_MORE];
753     graphic -= GFX_START_ROCKSMORE;
754     src_x  = (graphic % MORE_PER_LINE) * TILEX;
755     src_y  = (graphic / MORE_PER_LINE) * TILEY;
756   }
757   else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
758   {
759     src_pixmap = pix[PIX_HEROES];
760     drawing_gc = clip_gc[PIX_HEROES];
761     graphic -= GFX_START_ROCKSHEROES;
762     src_x  = (graphic % HEROES_PER_LINE) * TILEX;
763     src_y  = (graphic / HEROES_PER_LINE) * TILEY;
764   }
765   else
766   {
767     DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
768     return;
769   }
770
771   if (tile_clipmask[tile] != None)
772   {
773     XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
774     XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
775     XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
776               src_x, src_y, TILEX, TILEY, dest_x, dest_y);
777   }
778   else
779   {
780 #if DEBUG
781     printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
782 #endif
783
784     XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
785     XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
786               src_x, src_y, TILEX, TILEY, dest_x, dest_y);
787   }
788 }
789
790 void DrawMiniGraphic(int x, int y, int graphic)
791 {
792   DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
793   MarkTileDirty(x/2, y/2);
794 }
795
796 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
797 {
798   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
799   {
800     graphic -= GFX_START_ROCKSSCREEN;
801     *pixmap = pix[PIX_BACK];
802     *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
803     *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
804   }
805   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
806   {
807     graphic -= GFX_START_ROCKSMORE;
808     *pixmap = pix[PIX_MORE];
809     *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
810     *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
811   }
812   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
813   {
814     graphic -= GFX_START_ROCKSFONT;
815     *pixmap = pix[PIX_SMALLFONT];
816     *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
817     *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
818           FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
819   }
820   else
821   {
822     *pixmap = pix[PIX_MORE];
823     *x = MINI_MORE_STARTX;
824     *y = MINI_MORE_STARTY;
825   }
826 }
827
828 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
829 {
830   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
831   {
832     graphic -= GFX_START_ROCKSSCREEN;
833     XCopyArea(display, pix[PIX_BACK], d, gc,
834               MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
835               MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
836               MINI_TILEX, MINI_TILEY, x, y);
837   }
838   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
839   {
840     graphic -= GFX_START_ROCKSMORE;
841     XCopyArea(display, pix[PIX_MORE], d, gc,
842               MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX,
843               MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY,
844               MINI_TILEX, MINI_TILEY, x, y);
845   }
846   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
847   {
848     graphic -= GFX_START_ROCKSFONT;
849     XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
850               (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
851               (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
852               FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
853               MINI_TILEX, MINI_TILEY, x, y);
854   }
855   else
856     XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
857 }
858
859 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
860                         int cut_mode, int mask_mode)
861 {
862   int width = TILEX, height = TILEY;
863   int cx = 0, cy = 0;
864   int src_x, src_y, dest_x, dest_y;
865   int tile = graphic;
866   Pixmap src_pixmap;
867   GC drawing_gc;
868
869   if (graphic < 0)
870   {
871     DrawGraphic(x, y, graphic);
872     return;
873   }
874
875   if (dx || dy)                 /* Verschiebung der Grafik? */
876   {
877     if (x < BX1)                /* Element kommt von links ins Bild */
878     {
879       x = BX1;
880       width = dx;
881       cx = TILEX - dx;
882       dx = 0;
883     }
884     else if (x > BX2)           /* Element kommt von rechts ins Bild */
885     {
886       x = BX2;
887       width = -dx;
888       dx = TILEX + dx;
889     }
890     else if (x==BX1 && dx < 0)  /* Element verläßt links das Bild */
891     {
892       width += dx;
893       cx = -dx;
894       dx = 0;
895     }
896     else if (x==BX2 && dx > 0)  /* Element verläßt rechts das Bild */
897       width -= dx;
898     else if (dx)                /* allg. Bewegung in x-Richtung */
899       MarkTileDirty(x + SIGN(dx), y);
900
901     if (y < BY1)                /* Element kommt von oben ins Bild */
902     {
903       if (cut_mode==CUT_BELOW)  /* Element oberhalb des Bildes */
904         return;
905
906       y = BY1;
907       height = dy;
908       cy = TILEY - dy;
909       dy = 0;
910     }
911     else if (y > BY2)           /* Element kommt von unten ins Bild */
912     {
913       y = BY2;
914       height = -dy;
915       dy = TILEY + dy;
916     }
917     else if (y==BY1 && dy < 0)  /* Element verläßt oben das Bild */
918     {
919       height += dy;
920       cy = -dy;
921       dy = 0;
922     }
923     else if (dy > 0 && cut_mode == CUT_ABOVE)
924     {
925       if (y == BY2)             /* Element unterhalb des Bildes */
926         return;
927
928       height = dy;
929       cy = TILEY - dy;
930       dy = TILEY;
931       MarkTileDirty(x, y + 1);
932     }                           /* Element verläßt unten das Bild */
933     else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
934       height -= dy;
935     else if (dy)                /* allg. Bewegung in y-Richtung */
936       MarkTileDirty(x, y + SIGN(dy));
937   }
938
939   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
940   {
941     src_pixmap = pix[PIX_BACK];
942     drawing_gc = clip_gc[PIX_BACK];
943     graphic -= GFX_START_ROCKSSCREEN;
944     src_x  = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
945     src_y  = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
946   }
947   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
948   {
949     src_pixmap = pix[PIX_MORE];
950     drawing_gc = clip_gc[PIX_MORE];
951     graphic -= GFX_START_ROCKSMORE;
952     src_x  = (graphic % MORE_PER_LINE) * TILEX + cx;
953     src_y  = (graphic / MORE_PER_LINE) * TILEY + cy;
954   }
955   else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
956   {
957     src_pixmap = pix[PIX_HEROES];
958     drawing_gc = clip_gc[PIX_HEROES];
959     graphic -= GFX_START_ROCKSHEROES;
960     src_x  = (graphic % HEROES_PER_LINE) * TILEX + cx;
961     src_y  = (graphic / HEROES_PER_LINE) * TILEY + cy;
962   }
963   else  /* big font graphics currently not allowed (and not needed) */
964     return;
965
966   dest_x = FX + x * TILEX + dx;
967   dest_y = FY + y * TILEY + dy;
968
969 #if DEBUG
970   if (!IN_SCR_FIELD(x,y))
971   {
972     printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
973     printf("DrawGraphicShifted(): This should never happen!\n");
974     return;
975   }
976 #endif
977
978   if (mask_mode == USE_MASKING)
979   {
980     if (tile_clipmask[tile] != None)
981     {
982       XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
983       XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
984       XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
985                 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
986     }
987     else
988     {
989 #if DEBUG
990       printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
991 #endif
992
993       XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
994       XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
995                 src_x, src_y, width, height, dest_x, dest_y);
996     }
997   }
998   else
999     XCopyArea(display, src_pixmap, drawto_field, gc,
1000               src_x, src_y, width, height, dest_x, dest_y);
1001
1002   MarkTileDirty(x,y);
1003 }
1004
1005 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1006                                 int cut_mode)
1007 {
1008   DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1009 }
1010
1011 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1012                           int cut_mode, int mask_mode)
1013 {
1014   int ux = LEVELX(x), uy = LEVELY(y);
1015   int graphic = el2gfx(element);
1016   int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1017   int phase4 = phase8 / 2;
1018   int phase2  = phase8 / 4;
1019   int dir = MovDir[ux][uy];
1020
1021   if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1022   {
1023     graphic += 4 * !phase2;
1024
1025     if (dir == MV_UP)
1026       graphic += 1;
1027     else if (dir == MV_LEFT)
1028       graphic += 2;
1029     else if (dir == MV_DOWN)
1030       graphic += 3;
1031   }
1032   else if (element == EL_SP_SNIKSNAK)
1033   {
1034     if (dir == MV_LEFT)
1035       graphic = GFX_SP_SNIKSNAK_LEFT;
1036     else if (dir == MV_RIGHT)
1037       graphic = GFX_SP_SNIKSNAK_RIGHT;
1038     else if (dir == MV_UP)
1039       graphic = GFX_SP_SNIKSNAK_UP;
1040     else
1041       graphic = GFX_SP_SNIKSNAK_DOWN;
1042
1043     graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1044   }
1045   else if (element == EL_SP_ELECTRON)
1046   {
1047     graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1048   }
1049   else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1050            element == EL_SCHWEIN || element == EL_DRACHE)
1051   {
1052     if (dir == MV_LEFT)
1053       graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1054                  element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1055                  element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1056     else if (dir == MV_RIGHT)
1057       graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1058                  element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1059                  element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1060     else if (dir == MV_UP)
1061       graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1062                  element == EL_PINGUIN ? GFX_PINGUIN_UP :
1063                  element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1064     else
1065       graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1066                  element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1067                  element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1068
1069     graphic += phase4;
1070   }
1071   else if (element == EL_SONDE)
1072   {
1073     graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1074   }
1075   else if (element == EL_SALZSAEURE)
1076   {
1077     graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1078   }
1079   else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1080   {
1081     graphic += !phase2;
1082   }
1083   else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
1084   {
1085     if (element != EL_SP_INFOTRON)
1086       graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
1087   }
1088   else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1089            element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1090   {
1091     graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1092   }
1093   else if (IS_AMOEBOID(element))
1094   {
1095     graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1096     graphic += (x + 2 * y + 4) % 4;
1097   }
1098   else if (element == EL_MAUER_LEBT)
1099   {
1100     boolean links_massiv = FALSE, rechts_massiv = FALSE;
1101
1102     if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1103       links_massiv = TRUE;
1104     if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1105       rechts_massiv = TRUE;
1106
1107     if (links_massiv && rechts_massiv)
1108       graphic = GFX_MAUERWERK;
1109     else if (links_massiv)
1110       graphic = GFX_MAUER_R;
1111     else if (rechts_massiv)
1112       graphic = GFX_MAUER_L;
1113   }
1114
1115   if (dx || dy)
1116     DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1117   else if (mask_mode == USE_MASKING)
1118     DrawGraphicThruMask(x, y, graphic);
1119   else
1120     DrawGraphic(x, y, graphic);
1121 }
1122
1123 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1124                          int cut_mode, int mask_mode)
1125 {
1126   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1127     DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1128                          cut_mode, mask_mode);
1129 }
1130
1131 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1132                               int cut_mode)
1133 {
1134   DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1135 }
1136
1137 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1138                              int cut_mode)
1139 {
1140   DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1141 }
1142
1143 void DrawScreenElementThruMask(int x, int y, int element)
1144 {
1145   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1146 }
1147
1148 void DrawLevelElementThruMask(int x, int y, int element)
1149 {
1150   DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1151 }
1152
1153 void DrawLevelFieldThruMask(int x, int y)
1154 {
1155   DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1156 }
1157
1158 void ErdreichAnbroeckeln(int x, int y)
1159 {
1160   int i, width, height, cx,cy;
1161   int ux = LEVELX(x), uy = LEVELY(y);
1162   int element, graphic;
1163   int snip = 4;
1164   static int xy[4][2] =
1165   {
1166     { 0, -1 },
1167     { -1, 0 },
1168     { +1, 0 },
1169     { 0, +1 }
1170   };
1171
1172   if (!IN_LEV_FIELD(ux, uy))
1173     return;
1174
1175   element = Feld[ux][uy];
1176
1177   if (element == EL_ERDREICH)
1178   {
1179     if (!IN_SCR_FIELD(x, y))
1180       return;
1181
1182     graphic = GFX_ERDENRAND;
1183
1184     for(i=0; i<4; i++)
1185     {
1186       int uxx, uyy;
1187
1188       uxx = ux + xy[i][0];
1189       uyy = uy + xy[i][1];
1190       if (!IN_LEV_FIELD(uxx, uyy))
1191         element = EL_BETON;
1192       else
1193         element = Feld[uxx][uyy];
1194
1195       if (element == EL_ERDREICH)
1196         continue;
1197
1198       if (i == 1 || i == 2)
1199       {
1200         width = snip;
1201         height = TILEY;
1202         cx = (i == 2 ? TILEX - snip : 0);
1203         cy = 0;
1204       }
1205       else
1206       {
1207         width = TILEX;
1208         height = snip;
1209         cx = 0;
1210         cy = (i == 3 ? TILEY - snip : 0);
1211       }
1212
1213       XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1214                 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1215                 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1216                 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1217     }
1218
1219     MarkTileDirty(x, y);
1220   }
1221   else
1222   {
1223     graphic = GFX_ERDENRAND;
1224
1225     for(i=0; i<4; i++)
1226     {
1227       int xx, yy, uxx, uyy;
1228
1229       xx = x + xy[i][0];
1230       yy = y + xy[i][1];
1231       uxx = ux + xy[i][0];
1232       uyy = uy + xy[i][1];
1233
1234       if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1235           !IN_SCR_FIELD(xx, yy))
1236         continue;
1237
1238       if (i == 1 || i == 2)
1239       {
1240         width = snip;
1241         height = TILEY;
1242         cx = (i == 1 ? TILEX - snip : 0);
1243         cy = 0;
1244       }
1245       else
1246       {
1247         width = TILEX;
1248         height = snip;
1249         cx = 0;
1250         cy = (i==0 ? TILEY-snip : 0);
1251       }
1252
1253       XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1254                 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1255                 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1256                 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1257
1258       MarkTileDirty(xx, yy);
1259     }
1260   }
1261 }
1262
1263 void DrawScreenElement(int x, int y, int element)
1264 {
1265   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1266   ErdreichAnbroeckeln(x, y);
1267 }
1268
1269 void DrawLevelElement(int x, int y, int element)
1270 {
1271   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1272     DrawScreenElement(SCREENX(x), SCREENY(y), element);
1273 }
1274
1275 void DrawScreenField(int x, int y)
1276 {
1277   int ux = LEVELX(x), uy = LEVELY(y);
1278   int element;
1279
1280   if (!IN_LEV_FIELD(ux, uy))
1281   {
1282     if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1283       element = EL_LEERRAUM;
1284     else
1285       element = BorderElement;
1286
1287     DrawScreenElement(x, y, element);
1288     return;
1289   }
1290
1291   element = Feld[ux][uy];
1292
1293   if (IS_MOVING(ux, uy))
1294   {
1295     int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1296     boolean cut_mode = NO_CUTTING;
1297
1298     if (Store[ux][uy] == EL_MORAST_LEER ||
1299         Store[ux][uy] == EL_SIEB_LEER ||
1300         Store[ux][uy] == EL_SIEB2_LEER ||
1301         Store[ux][uy] == EL_AMOEBE_NASS)
1302       cut_mode = CUT_ABOVE;
1303     else if (Store[ux][uy] == EL_MORAST_VOLL ||
1304              Store[ux][uy] == EL_SIEB_VOLL ||
1305              Store[ux][uy] == EL_SIEB2_VOLL)
1306       cut_mode = CUT_BELOW;
1307
1308     if (cut_mode == CUT_ABOVE)
1309       DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1310     else
1311       DrawScreenElement(x, y, EL_LEERRAUM);
1312
1313     if (horiz_move)
1314       DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1315     else
1316       DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1317
1318     if (Store[ux][uy] == EL_SALZSAEURE)
1319       DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1320   }
1321   else if (IS_BLOCKED(ux, uy))
1322   {
1323     int oldx, oldy;
1324     int sx, sy;
1325     int horiz_move;
1326     boolean cut_mode = NO_CUTTING;
1327
1328     Blocked2Moving(ux, uy, &oldx, &oldy);
1329     sx = SCREENX(oldx);
1330     sy = SCREENY(oldy);
1331     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1332                   MovDir[oldx][oldy] == MV_RIGHT);
1333
1334     if (Store[oldx][oldy] == EL_MORAST_LEER ||
1335         Store[oldx][oldy] == EL_SIEB_LEER ||
1336         Store[oldx][oldy] == EL_SIEB2_LEER ||
1337         Store[oldx][oldy] == EL_AMOEBE_NASS)
1338       cut_mode = CUT_ABOVE;
1339
1340     DrawScreenElement(x, y, EL_LEERRAUM);
1341     element = Feld[oldx][oldy];
1342
1343     if (horiz_move)
1344       DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1345     else
1346       DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1347   }
1348   else if (IS_DRAWABLE(element))
1349     DrawScreenElement(x, y, element);
1350   else
1351     DrawScreenElement(x, y, EL_LEERRAUM);
1352 }
1353
1354 void DrawLevelField(int x, int y)
1355 {
1356   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1357     DrawScreenField(SCREENX(x), SCREENY(y));
1358   else if (IS_MOVING(x, y))
1359   {
1360     int newx,newy;
1361
1362     Moving2Blocked(x, y, &newx, &newy);
1363     if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1364       DrawScreenField(SCREENX(newx), SCREENY(newy));
1365   }
1366   else if (IS_BLOCKED(x, y))
1367   {
1368     int oldx, oldy;
1369
1370     Blocked2Moving(x, y, &oldx, &oldy);
1371     if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1372       DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1373   }
1374 }
1375
1376 void DrawMiniElement(int x, int y, int element)
1377 {
1378   int graphic;
1379
1380   if (!element)
1381   {
1382     DrawMiniGraphic(x, y, -1);
1383     return;
1384   }
1385
1386   graphic = el2gfx(element);
1387   DrawMiniGraphic(x, y, graphic);
1388 }
1389
1390 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1391 {
1392   int x = sx + scroll_x, y = sy + scroll_y;
1393
1394   if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1395     DrawMiniElement(sx, sy, EL_LEERRAUM);
1396   else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1397     DrawMiniElement(sx, sy, Feld[x][y]);
1398   else if (x == -1 && y == -1)
1399     DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_LEFT);
1400   else if (x == lev_fieldx && y == -1)
1401     DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_RIGHT);
1402   else if (x == -1 && y == lev_fieldy)
1403     DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_LEFT);
1404   else if (x == lev_fieldx && y == lev_fieldy)
1405     DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_RIGHT);
1406   else if (x == -1 || x == lev_fieldx)
1407     DrawMiniGraphic(sx, sy, GFX_STEEL_VERTICAL);
1408   else if (y == -1 || y == lev_fieldy)
1409     DrawMiniGraphic(sx, sy, GFX_STEEL_HORIZONTAL);
1410 }
1411
1412 void DrawMicroElement(int xpos, int ypos, int element)
1413 {
1414   int graphic;
1415
1416   if (element == EL_LEERRAUM)
1417     return;
1418
1419   graphic = el2gfx(element);
1420
1421   if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1422   {
1423     graphic -= GFX_START_ROCKSMORE;
1424     XCopyArea(display, pix[PIX_MORE], drawto, gc,
1425               MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1426               MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1427               MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1428   }
1429   else
1430     XCopyArea(display, pix[PIX_BACK], drawto, gc,
1431               MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1432               MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1433               MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1434 }
1435
1436 void DrawLevel()
1437 {
1438   int x,y;
1439
1440   ClearWindow();
1441
1442   for(x=BX1; x<=BX2; x++)
1443     for(y=BY1; y<=BY2; y++)
1444       DrawScreenField(x, y);
1445
1446   if (setup.soft_scrolling)
1447     XCopyArea(display, fieldbuffer, backbuffer, gc,
1448               FX, FY, SXSIZE, SYSIZE, SX, SY);
1449
1450   redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1451 }
1452
1453 void DrawMiniLevel(int scroll_x, int scroll_y)
1454 {
1455   int x,y;
1456
1457   for(x=0; x<ED_FIELDX; x++)
1458     for(y=0; y<ED_FIELDY; y++)
1459       DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1460
1461   redraw_mask |= REDRAW_FIELD;
1462 }
1463
1464 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1465 {
1466   int x, y;
1467
1468   /* determine border element for this level */
1469   SetBorderElement();
1470
1471   XFillRectangle(display, drawto, gc,
1472                  xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1473
1474   if (lev_fieldx < STD_LEV_FIELDX)
1475     xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1476   if (lev_fieldy < STD_LEV_FIELDY)
1477     ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1478
1479   xpos += MICRO_TILEX;
1480   ypos += MICRO_TILEY;
1481
1482   for(x=-1; x<=STD_LEV_FIELDX; x++)
1483   {
1484     for(y=-1; y<=STD_LEV_FIELDY; y++)
1485     {
1486       int lx = from_x + x, ly = from_y + y;
1487
1488       if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1489         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1490                          Ur[lx][ly]);
1491       else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1492         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1493                          BorderElement);
1494     }
1495   }
1496
1497   redraw_mask |= REDRAW_MICROLEVEL;
1498 }
1499
1500 static void DrawMicroLevelLabelExt(int mode)
1501 {
1502   char label_text[100];
1503
1504   XFillRectangle(display, drawto,gc,
1505                  SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1506
1507   strcpy(label_text, (mode == 1 ? level.name :
1508                       mode == 2 ? "created by" :
1509                       mode == 3 ? level.author : ""));
1510
1511   if (strlen(label_text) > 0)
1512   {
1513     int size, lxpos, lypos;
1514
1515     label_text[SXSIZE / FONT4_XSIZE] = '\0';
1516
1517     size = strlen(label_text);
1518     lxpos = SX + (SXSIZE - size * FONT4_XSIZE) / 2;
1519     lypos = MICROLABEL_YPOS;
1520
1521     DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1522   }
1523
1524   redraw_mask |= REDRAW_MICROLEVEL;
1525 }
1526
1527 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1528 {
1529   static unsigned long scroll_delay = 0;
1530   static unsigned long label_delay = 0;
1531   static int from_x, from_y, scroll_direction;
1532   static int label_state, label_counter;
1533
1534   if (restart)
1535   {
1536     from_x = from_y = 0;
1537     scroll_direction = MV_RIGHT;
1538     label_state = 1;
1539     label_counter = 0;
1540
1541     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1542     DrawMicroLevelLabelExt(label_state);
1543
1544     /* initialize delay counters */
1545     DelayReached(&scroll_delay, 0);
1546     DelayReached(&label_delay, 0);
1547
1548     return;
1549   }
1550
1551   /* scroll micro level, if needed */
1552   if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1553       DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1554   {
1555     switch (scroll_direction)
1556     {
1557       case MV_LEFT:
1558         if (from_x > 0)
1559           from_x--;
1560         else
1561           scroll_direction = MV_UP;
1562         break;
1563
1564       case MV_RIGHT:
1565         if (from_x < lev_fieldx - STD_LEV_FIELDX)
1566           from_x++;
1567         else
1568           scroll_direction = MV_DOWN;
1569         break;
1570
1571       case MV_UP:
1572         if (from_y > 0)
1573           from_y--;
1574         else
1575           scroll_direction = MV_RIGHT;
1576         break;
1577
1578       case MV_DOWN:
1579         if (from_y < lev_fieldy - STD_LEV_FIELDY)
1580           from_y++;
1581         else
1582           scroll_direction = MV_LEFT;
1583         break;
1584
1585       default:
1586         break;
1587     }
1588
1589     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1590   }
1591
1592   /* redraw micro level label, if needed */
1593   if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1594       strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1595       strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1596       DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1597   {
1598     label_counter = (label_counter + 1) % 23;
1599     label_state = (label_counter >= 0 && label_counter <= 7 ? 1 :
1600                    label_counter >= 9 && label_counter <= 12 ? 2 :
1601                    label_counter >= 14 && label_counter <= 21 ? 3 : 0);
1602     DrawMicroLevelLabelExt(label_state);
1603   }
1604 }
1605
1606 int REQ_in_range(int x, int y)
1607 {
1608   if (y > DY+249 && y < DY+278)
1609   {
1610     if (x > DX+1 && x < DX+48)
1611       return 1;
1612     else if (x > DX+51 && x < DX+98) 
1613       return 2;
1614   }
1615   return 0;
1616 }
1617
1618 boolean Request(char *text, unsigned int req_state)
1619 {
1620   int mx, my, ty, result = -1;
1621   unsigned int old_door_state;
1622
1623 #ifndef MSDOS
1624   /* pause network game while waiting for request to answer */
1625   if (options.network &&
1626       game_status == PLAYING &&
1627       req_state & REQUEST_WAIT_FOR)
1628     SendToServer_PausePlaying();
1629 #endif
1630
1631   old_door_state = GetDoorState();
1632
1633   UnmapAllGadgets();
1634
1635   CloseDoor(DOOR_CLOSE_1);
1636
1637   /* save old door content */
1638   XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1639             DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1640             DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1641
1642   /* clear door drawing field */
1643 #if 0
1644   XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1645                  DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1646 #else
1647   XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1648 #endif
1649
1650   /* write text for request */
1651   for(ty=0; ty<13; ty++)
1652   {
1653     int tx, tl, tc;
1654     char txt[256];
1655
1656     if (!*text)
1657       break;
1658
1659     for(tl=0,tx=0; tx<7; tl++,tx++)
1660     {
1661       tc = *(text + tx);
1662       if (!tc || tc == 32)
1663         break;
1664     }
1665     if (!tl)
1666     { 
1667       text++; 
1668       ty--; 
1669       continue; 
1670     }
1671     sprintf(txt, text); 
1672     txt[tl] = 0;
1673 #if 0
1674     DrawTextExt(pix[PIX_DB_DOOR], gc,
1675                 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1676                 txt, FS_SMALL, FC_YELLOW);
1677 #else
1678     DrawTextExt(drawto, gc,
1679                 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1680                 txt, FS_SMALL, FC_YELLOW);
1681 #endif
1682     text += tl + (tc == 32 ? 1 : 0);
1683   }
1684
1685
1686
1687 #if 0
1688   if (req_state & REQ_ASK)
1689   {
1690     DrawYesNoButton(BUTTON_OK, DB_INIT);
1691     DrawYesNoButton(BUTTON_NO, DB_INIT);
1692   }
1693   else if (req_state & REQ_CONFIRM)
1694   {
1695     DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1696   }
1697   else if (req_state & REQ_PLAYER)
1698   {
1699     DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1700     DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1701     DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1702     DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1703   }
1704 #else
1705
1706   if (req_state & REQ_ASK)
1707   {
1708     MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1709     MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1710   }
1711   else if (req_state & REQ_CONFIRM)
1712   {
1713     MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1714   }
1715   else if (req_state & REQ_PLAYER)
1716   {
1717     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1718     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1719     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1720     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1721   }
1722
1723   /* copy request gadgets to door backbuffer */
1724   XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1725             DX, DY, DXSIZE, DYSIZE,
1726             DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1727
1728 #endif
1729
1730
1731
1732   OpenDoor(DOOR_OPEN_1);
1733   ClearEventQueue();
1734
1735   if (!(req_state & REQUEST_WAIT_FOR))
1736     return(FALSE);
1737
1738   if (game_status != MAINMENU)
1739     InitAnimation();
1740
1741   button_status = MB_RELEASED;
1742
1743   request_gadget_id = -1;
1744
1745   while(result < 0)
1746   {
1747     if (XPending(display))
1748     {
1749       XEvent event;
1750
1751       XNextEvent(display, &event);
1752
1753       switch(event.type)
1754       {
1755         case ButtonPress:
1756         case ButtonRelease:
1757         case MotionNotify:
1758         {
1759           int choice;
1760
1761           if (event.type == MotionNotify)
1762           {
1763             Window root, child;
1764             int root_x, root_y;
1765             int win_x, win_y;
1766             unsigned int mask;
1767
1768             if (!XQueryPointer(display, window, &root, &child,
1769                                &root_x, &root_y, &win_x, &win_y, &mask))
1770               continue;
1771
1772             if (!button_status)
1773               continue;
1774
1775             motion_status = TRUE;
1776             mx = ((XMotionEvent *) &event)->x;
1777             my = ((XMotionEvent *) &event)->y;
1778           }
1779           else
1780           {
1781             motion_status = FALSE;
1782             mx = ((XButtonEvent *) &event)->x;
1783             my = ((XButtonEvent *) &event)->y;
1784             if (event.type==ButtonPress)
1785               button_status = ((XButtonEvent *) &event)->button;
1786             else
1787               button_status = MB_RELEASED;
1788           }
1789
1790
1791
1792 #if 0
1793           if (req_state & REQ_ASK)
1794             choice = CheckYesNoButtons(mx,my,button_status);
1795           else if (req_state & REQ_CONFIRM)
1796             choice = CheckConfirmButton(mx,my,button_status);
1797           else
1798             choice = CheckPlayerButtons(mx,my,button_status);
1799
1800           switch(choice)
1801           {
1802             case BUTTON_OK:
1803               result = TRUE;
1804               break;
1805             case BUTTON_NO:
1806               result = FALSE;
1807               break;
1808             case BUTTON_CONFIRM:
1809               result = TRUE | FALSE;
1810               break;
1811
1812             case BUTTON_PLAYER_1:
1813               result = 1;
1814               break;
1815             case BUTTON_PLAYER_2:
1816               result = 2;
1817               break;
1818             case BUTTON_PLAYER_3:
1819               result = 3;
1820               break;
1821             case BUTTON_PLAYER_4:
1822               result = 4;
1823               break;
1824
1825             default:
1826               break;
1827           }
1828 #else
1829
1830           /* this sets 'request_gadget_id' */
1831           HandleGadgets(mx, my, button_status);
1832
1833           switch(request_gadget_id)
1834           {
1835             case TOOL_CTRL_ID_YES:
1836               result = TRUE;
1837               break;
1838             case TOOL_CTRL_ID_NO:
1839               result = FALSE;
1840               break;
1841             case TOOL_CTRL_ID_CONFIRM:
1842               result = TRUE | FALSE;
1843               break;
1844
1845             case TOOL_CTRL_ID_PLAYER_1:
1846               result = 1;
1847               break;
1848             case TOOL_CTRL_ID_PLAYER_2:
1849               result = 2;
1850               break;
1851             case TOOL_CTRL_ID_PLAYER_3:
1852               result = 3;
1853               break;
1854             case TOOL_CTRL_ID_PLAYER_4:
1855               result = 4;
1856               break;
1857
1858             default:
1859               break;
1860           }
1861 #endif
1862
1863           break;
1864         }
1865
1866         case KeyPress:
1867           switch(XLookupKeysym((XKeyEvent *)&event,
1868                                ((XKeyEvent *)&event)->state))
1869           {
1870             case XK_Return:
1871               result = 1;
1872               break;
1873
1874             case XK_Escape:
1875               result = 0;
1876               break;
1877
1878             default:
1879               break;
1880           }
1881           if (req_state & REQ_PLAYER)
1882             result = 0;
1883           break;
1884
1885         case KeyRelease:
1886           key_joystick_mapping = 0;
1887           break;
1888
1889         default:
1890           HandleOtherEvents(&event);
1891           break;
1892       }
1893     }
1894     else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1895     {
1896       int joy = AnyJoystick();
1897
1898       if (joy & JOY_BUTTON_1)
1899         result = 1;
1900       else if (joy & JOY_BUTTON_2)
1901         result = 0;
1902     }
1903
1904     DoAnimation();
1905
1906     /* don't eat all CPU time */
1907     Delay(10);
1908   }
1909
1910   if (game_status != MAINMENU)
1911     StopAnimation();
1912
1913   UnmapToolButtons();
1914
1915   if (!(req_state & REQ_STAY_OPEN))
1916   {
1917     CloseDoor(DOOR_CLOSE_1);
1918
1919     if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1920     {
1921       XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1922                 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1923                 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1924       OpenDoor(DOOR_OPEN_1);
1925     }
1926   }
1927
1928   RemapAllGadgets();
1929
1930 #ifndef MSDOS
1931   /* continue network game after request */
1932   if (options.network &&
1933       game_status == PLAYING &&
1934       req_state & REQUEST_WAIT_FOR)
1935     SendToServer_ContinuePlaying();
1936 #endif
1937
1938   return(result);
1939 }
1940
1941 unsigned int OpenDoor(unsigned int door_state)
1942 {
1943   unsigned int new_door_state;
1944
1945   if (door_state & DOOR_COPY_BACK)
1946   {
1947     XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1948               DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1949               DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1950     door_state &= ~DOOR_COPY_BACK;
1951   }
1952
1953   new_door_state = MoveDoor(door_state);
1954
1955   return(new_door_state);
1956 }
1957
1958 unsigned int CloseDoor(unsigned int door_state)
1959 {
1960   unsigned int new_door_state;
1961
1962   XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1963             DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1964   XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1965             VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1966
1967   new_door_state = MoveDoor(door_state);
1968
1969   return(new_door_state);
1970 }
1971
1972 unsigned int GetDoorState()
1973 {
1974   return(MoveDoor(DOOR_GET_STATE));
1975 }
1976
1977 unsigned int MoveDoor(unsigned int door_state)
1978 {
1979   static int door1 = DOOR_OPEN_1;
1980   static int door2 = DOOR_CLOSE_2;
1981   static unsigned long door_delay = 0;
1982   int x, start, stepsize = 2;
1983   unsigned long door_delay_value = stepsize * 5;
1984
1985   if (door_state == DOOR_GET_STATE)
1986     return(door1 | door2);
1987
1988   if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1989     door_state &= ~DOOR_OPEN_1;
1990   else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1991     door_state &= ~DOOR_CLOSE_1;
1992   if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1993     door_state &= ~DOOR_OPEN_2;
1994   else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1995     door_state &= ~DOOR_CLOSE_2;
1996
1997   if (setup.quick_doors)
1998   {
1999     stepsize = 20;
2000     door_delay_value = 0;
2001     StopSound(SND_OEFFNEN);
2002   }
2003
2004   if (door_state & DOOR_ACTION)
2005   {
2006     if (!(door_state & DOOR_NO_DELAY))
2007       PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
2008
2009     start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2010
2011     for(x=start; x<=DXSIZE; x+=stepsize)
2012     {
2013       WaitUntilDelayReached(&door_delay, door_delay_value);
2014
2015       if (door_state & DOOR_ACTION_1)
2016       {
2017         int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2018         int j = (DXSIZE - i) / 3;
2019
2020         XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2021                   DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2022                   DXSIZE,DYSIZE - i/2, DX, DY);
2023
2024         XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2025
2026         XSetClipOrigin(display, clip_gc[PIX_DOOR],
2027                        DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2028         XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2029                   DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2030         XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2031                   DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2032                   DY + 140 + j);
2033         XSetClipOrigin(display, clip_gc[PIX_DOOR],
2034                        DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2035         XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2036                   DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2037         XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2038                   DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2039
2040         XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2041                   DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2042                   DX, DY + 77 - j);
2043         XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2044                   DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2045                   DX, DY + 203 - j);
2046         XSetClipOrigin(display, clip_gc[PIX_DOOR],
2047                        DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2048         XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2049                   DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2050                   DX + DXSIZE - i, DY + 77 + j);
2051         XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2052                   DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2053                   DX + DXSIZE - i, DY + 203 + j);
2054
2055         redraw_mask |= REDRAW_DOOR_1;
2056       }
2057
2058       if (door_state & DOOR_ACTION_2)
2059       {
2060         int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2061         int j = (VXSIZE - i) / 3;
2062
2063         XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2064                   DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2065                   VXSIZE, VYSIZE - i/2, VX, VY);
2066
2067         XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2068
2069         XSetClipOrigin(display, clip_gc[PIX_DOOR],
2070                        VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2071         XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2072                   VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2073         XSetClipOrigin(display, clip_gc[PIX_DOOR],
2074                        VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2075         XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2076                   VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2077
2078         XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2079                   VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2080                   VX, VY + VYSIZE / 2 - j);
2081         XSetClipOrigin(display, clip_gc[PIX_DOOR],
2082                        VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2083         XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2084                   VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2085                   VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2086
2087         redraw_mask |= REDRAW_DOOR_2;
2088       }
2089
2090       BackToFront();
2091
2092       if (game_status == MAINMENU)
2093         DoAnimation();
2094     }
2095   }
2096
2097   if (setup.quick_doors)
2098     StopSound(SND_OEFFNEN);
2099
2100   if (door_state & DOOR_ACTION_1)
2101     door1 = door_state & DOOR_ACTION_1;
2102   if (door_state & DOOR_ACTION_2)
2103     door2 = door_state & DOOR_ACTION_2;
2104
2105   return(door1 | door2);
2106 }
2107
2108 int ReadPixel(Drawable d, int x, int y)
2109 {
2110   XImage *pixel_image;
2111   unsigned long pixel_value;
2112
2113   pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2114   pixel_value = XGetPixel(pixel_image, 0, 0);
2115
2116   XDestroyImage(pixel_image);
2117
2118   return pixel_value;
2119 }
2120
2121 /* ---------- new tool button stuff ---------------------------------------- */
2122
2123 /* graphic position values for tool buttons */
2124 #define TOOL_BUTTON_YES_XPOS            2
2125 #define TOOL_BUTTON_YES_YPOS            250
2126 #define TOOL_BUTTON_YES_GFX_YPOS        0
2127 #define TOOL_BUTTON_YES_XSIZE           46
2128 #define TOOL_BUTTON_YES_YSIZE           28
2129 #define TOOL_BUTTON_NO_XPOS             52
2130 #define TOOL_BUTTON_NO_YPOS             TOOL_BUTTON_YES_YPOS
2131 #define TOOL_BUTTON_NO_GFX_YPOS         TOOL_BUTTON_YES_GFX_YPOS
2132 #define TOOL_BUTTON_NO_XSIZE            TOOL_BUTTON_YES_XSIZE
2133 #define TOOL_BUTTON_NO_YSIZE            TOOL_BUTTON_YES_YSIZE
2134 #define TOOL_BUTTON_CONFIRM_XPOS        TOOL_BUTTON_YES_XPOS
2135 #define TOOL_BUTTON_CONFIRM_YPOS        TOOL_BUTTON_YES_YPOS
2136 #define TOOL_BUTTON_CONFIRM_GFX_YPOS    30
2137 #define TOOL_BUTTON_CONFIRM_XSIZE       96
2138 #define TOOL_BUTTON_CONFIRM_YSIZE       TOOL_BUTTON_YES_YSIZE
2139 #define TOOL_BUTTON_PLAYER_XSIZE        30
2140 #define TOOL_BUTTON_PLAYER_YSIZE        30
2141 #define TOOL_BUTTON_PLAYER_GFX_XPOS     5
2142 #define TOOL_BUTTON_PLAYER_GFX_YPOS     185
2143 #define TOOL_BUTTON_PLAYER_XPOS         (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2144 #define TOOL_BUTTON_PLAYER_YPOS         (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2145 #define TOOL_BUTTON_PLAYER1_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2146                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2147 #define TOOL_BUTTON_PLAYER2_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2148                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2149 #define TOOL_BUTTON_PLAYER3_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2150                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2151 #define TOOL_BUTTON_PLAYER4_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2152                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2153 #define TOOL_BUTTON_PLAYER1_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2154                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2155 #define TOOL_BUTTON_PLAYER2_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2156                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2157 #define TOOL_BUTTON_PLAYER3_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2158                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2159 #define TOOL_BUTTON_PLAYER4_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2160                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2161
2162 static struct
2163 {
2164   int xpos, ypos;
2165   int x, y;
2166   int width, height;
2167   int gadget_id;
2168   char *infotext;
2169 } toolbutton_info[NUM_TOOL_BUTTONS] =
2170 {
2171   {
2172     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_GFX_YPOS,
2173     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_YPOS,
2174     TOOL_BUTTON_YES_XSIZE,      TOOL_BUTTON_YES_YSIZE,
2175     TOOL_CTRL_ID_YES,
2176     "yes"
2177   },
2178   {
2179     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_GFX_YPOS,
2180     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_YPOS,
2181     TOOL_BUTTON_NO_XSIZE,       TOOL_BUTTON_NO_YSIZE,
2182     TOOL_CTRL_ID_NO,
2183     "no"
2184   },
2185   {
2186     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_GFX_YPOS,
2187     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_YPOS,
2188     TOOL_BUTTON_CONFIRM_XSIZE,  TOOL_BUTTON_CONFIRM_YSIZE,
2189     TOOL_CTRL_ID_CONFIRM,
2190     "confirm"
2191   },
2192   {
2193     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2194     TOOL_BUTTON_PLAYER1_XPOS,   TOOL_BUTTON_PLAYER1_YPOS,
2195     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2196     TOOL_CTRL_ID_PLAYER_1,
2197     "player 1"
2198   },
2199   {
2200     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2201     TOOL_BUTTON_PLAYER2_XPOS,   TOOL_BUTTON_PLAYER2_YPOS,
2202     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2203     TOOL_CTRL_ID_PLAYER_2,
2204     "player 2"
2205   },
2206   {
2207     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2208     TOOL_BUTTON_PLAYER3_XPOS,   TOOL_BUTTON_PLAYER3_YPOS,
2209     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2210     TOOL_CTRL_ID_PLAYER_3,
2211     "player 3"
2212   },
2213   {
2214     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2215     TOOL_BUTTON_PLAYER4_XPOS,   TOOL_BUTTON_PLAYER4_YPOS,
2216     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2217     TOOL_CTRL_ID_PLAYER_4,
2218     "player 4"
2219   }
2220 };
2221
2222 void CreateToolButtons()
2223 {
2224   int i;
2225
2226   for (i=0; i<NUM_TOOL_BUTTONS; i++)
2227   {
2228     Pixmap gd_pixmap = pix[PIX_DOOR];
2229     Pixmap deco_pixmap = 0;
2230     int deco_x, deco_y, deco_xpos, deco_ypos;
2231     struct GadgetInfo *gi;
2232     unsigned long event_mask;
2233     int gd_xoffset, gd_yoffset;
2234     int gd_x1, gd_x2, gd_y;
2235     int id = i;
2236
2237     event_mask = GD_EVENT_RELEASED;
2238
2239     gd_xoffset = toolbutton_info[i].xpos;
2240     gd_yoffset = toolbutton_info[i].ypos;
2241     gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2242     gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2243     gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2244
2245     if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2246     {
2247       getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2248                            &deco_pixmap, &deco_x, &deco_y);
2249       deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2250       deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2251     }
2252
2253     gi = CreateGadget(GDI_CUSTOM_ID, id,
2254                       GDI_INFO_TEXT, toolbutton_info[i].infotext,
2255                       GDI_X, DX + toolbutton_info[i].x,
2256                       GDI_Y, DY + toolbutton_info[i].y,
2257                       GDI_WIDTH, toolbutton_info[i].width,
2258                       GDI_HEIGHT, toolbutton_info[i].height,
2259                       GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2260                       GDI_STATE, GD_BUTTON_UNPRESSED,
2261                       GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2262                       GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2263                       GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2264                       GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2265                       GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2266                       GDI_DECORATION_SHIFTING, 1, 1,
2267                       GDI_EVENT_MASK, event_mask,
2268                       GDI_CALLBACK_ACTION, HandleToolButtons,
2269                       GDI_END);
2270
2271     if (gi == NULL)
2272       Error(ERR_EXIT, "cannot create gadget");
2273
2274     tool_gadget[id] = gi;
2275   }
2276 }
2277
2278 static void UnmapToolButtons()
2279 {
2280   int i;
2281
2282   for (i=0; i<NUM_TOOL_BUTTONS; i++)
2283     UnmapGadget(tool_gadget[i]);
2284 }
2285
2286 static void HandleToolButtons(struct GadgetInfo *gi)
2287 {
2288   request_gadget_id = gi->custom_id;
2289
2290
2291 #if 0
2292   int id = gi->custom_id;
2293
2294   if (game_status != PLAYING)
2295     return;
2296
2297   switch (id)
2298   {
2299     case GAME_CTRL_ID_STOP:
2300       if (AllPlayersGone)
2301       {
2302         CloseDoor(DOOR_CLOSE_1);
2303         game_status = MAINMENU;
2304         DrawMainMenu();
2305         break;
2306       }
2307
2308       if (Request("Do you really want to quit the game ?",
2309                   REQ_ASK | REQ_STAY_CLOSED))
2310       { 
2311 #ifndef MSDOS
2312         if (options.network)
2313           SendToServer_StopPlaying();
2314         else
2315 #endif
2316         {
2317           game_status = MAINMENU;
2318           DrawMainMenu();
2319         }
2320       }
2321       else
2322         OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2323       break;
2324
2325     case GAME_CTRL_ID_PAUSE:
2326       if (options.network)
2327       {
2328 #ifndef MSDOS
2329         if (tape.pausing)
2330           SendToServer_ContinuePlaying();
2331         else
2332           SendToServer_PausePlaying();
2333 #endif
2334       }
2335       else
2336         TapeTogglePause();
2337       break;
2338
2339     case GAME_CTRL_ID_PLAY:
2340       if (tape.pausing)
2341       {
2342 #ifndef MSDOS
2343         if (options.network)
2344           SendToServer_ContinuePlaying();
2345         else
2346 #endif
2347         {
2348           tape.pausing = FALSE;
2349           DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
2350         }
2351       }
2352       break;
2353
2354     case SOUND_CTRL_ID_MUSIC:
2355       if (setup.sound_music)
2356       { 
2357         setup.sound_music = FALSE;
2358         FadeSound(background_loop[level_nr % num_bg_loops]);
2359       }
2360       else if (sound_loops_allowed)
2361       { 
2362         setup.sound = setup.sound_music = TRUE;
2363         PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
2364       }
2365       break;
2366
2367     case SOUND_CTRL_ID_LOOPS:
2368       if (setup.sound_loops)
2369         setup.sound_loops = FALSE;
2370       else if (sound_loops_allowed)
2371         setup.sound = setup.sound_loops = TRUE;
2372       break;
2373
2374     case SOUND_CTRL_ID_SIMPLE:
2375       if (setup.sound_simple)
2376         setup.sound_simple = FALSE;
2377       else if (sound_status==SOUND_AVAILABLE)
2378         setup.sound = setup.sound_simple = TRUE;
2379       break;
2380
2381     default:
2382       break;
2383   }
2384 #endif
2385
2386
2387
2388 }
2389
2390 int el2gfx(int element)
2391 {
2392   switch(element)
2393   {
2394     case EL_LEERRAUM:           return -1;
2395     case EL_ERDREICH:           return GFX_ERDREICH;
2396     case EL_MAUERWERK:          return GFX_MAUERWERK;
2397     case EL_FELSBODEN:          return GFX_FELSBODEN;
2398     case EL_FELSBROCKEN:        return GFX_FELSBROCKEN;
2399     case EL_SCHLUESSEL:         return GFX_SCHLUESSEL;
2400     case EL_EDELSTEIN:          return GFX_EDELSTEIN;
2401     case EL_AUSGANG_ZU:         return GFX_AUSGANG_ZU;
2402     case EL_AUSGANG_ACT:        return GFX_AUSGANG_ACT;
2403     case EL_AUSGANG_AUF:        return GFX_AUSGANG_AUF;
2404     case EL_SPIELFIGUR:         return GFX_SPIELFIGUR;
2405     case EL_SPIELER1:           return GFX_SPIELER1;
2406     case EL_SPIELER2:           return GFX_SPIELER2;
2407     case EL_SPIELER3:           return GFX_SPIELER3;
2408     case EL_SPIELER4:           return GFX_SPIELER4;
2409     case EL_KAEFER:             return GFX_KAEFER;
2410     case EL_KAEFER_R:           return GFX_KAEFER_R;
2411     case EL_KAEFER_O:           return GFX_KAEFER_O;
2412     case EL_KAEFER_L:           return GFX_KAEFER_L;
2413     case EL_KAEFER_U:           return GFX_KAEFER_U;
2414     case EL_FLIEGER:            return GFX_FLIEGER;
2415     case EL_FLIEGER_R:          return GFX_FLIEGER_R;
2416     case EL_FLIEGER_O:          return GFX_FLIEGER_O;
2417     case EL_FLIEGER_L:          return GFX_FLIEGER_L;
2418     case EL_FLIEGER_U:          return GFX_FLIEGER_U;
2419     case EL_BUTTERFLY:          return GFX_BUTTERFLY;
2420     case EL_BUTTERFLY_R:        return GFX_BUTTERFLY_R;
2421     case EL_BUTTERFLY_O:        return GFX_BUTTERFLY_O;
2422     case EL_BUTTERFLY_L:        return GFX_BUTTERFLY_L;
2423     case EL_BUTTERFLY_U:        return GFX_BUTTERFLY_U;
2424     case EL_FIREFLY:            return GFX_FIREFLY;
2425     case EL_FIREFLY_R:          return GFX_FIREFLY_R;
2426     case EL_FIREFLY_O:          return GFX_FIREFLY_O;
2427     case EL_FIREFLY_L:          return GFX_FIREFLY_L;
2428     case EL_FIREFLY_U:          return GFX_FIREFLY_U;
2429     case EL_MAMPFER:            return GFX_MAMPFER;
2430     case EL_ROBOT:              return GFX_ROBOT;
2431     case EL_BETON:              return GFX_BETON;
2432     case EL_DIAMANT:            return GFX_DIAMANT;
2433     case EL_MORAST_LEER:        return GFX_MORAST_LEER;
2434     case EL_MORAST_VOLL:        return GFX_MORAST_VOLL;
2435     case EL_TROPFEN:            return GFX_TROPFEN;
2436     case EL_BOMBE:              return GFX_BOMBE;
2437     case EL_SIEB_INAKTIV:       return GFX_SIEB_INAKTIV;
2438     case EL_SIEB_LEER:          return GFX_SIEB_LEER;
2439     case EL_SIEB_VOLL:          return GFX_SIEB_VOLL;
2440     case EL_SIEB_TOT:           return GFX_SIEB_TOT;
2441     case EL_SALZSAEURE:         return GFX_SALZSAEURE;
2442     case EL_AMOEBE_TOT:         return GFX_AMOEBE_TOT;
2443     case EL_AMOEBE_NASS:        return GFX_AMOEBE_NASS;
2444     case EL_AMOEBE_NORM:        return GFX_AMOEBE_NORM;
2445     case EL_AMOEBE_VOLL:        return GFX_AMOEBE_VOLL;
2446     case EL_AMOEBE_BD:          return GFX_AMOEBE_BD;
2447     case EL_AMOEBA2DIAM:        return GFX_AMOEBA2DIAM;
2448     case EL_KOKOSNUSS:          return GFX_KOKOSNUSS;
2449     case EL_LIFE:               return GFX_LIFE;
2450     case EL_LIFE_ASYNC:         return GFX_LIFE_ASYNC;
2451     case EL_DYNAMIT:            return GFX_DYNAMIT;
2452     case EL_BADEWANNE:          return GFX_BADEWANNE;
2453     case EL_BADEWANNE1:         return GFX_BADEWANNE1;
2454     case EL_BADEWANNE2:         return GFX_BADEWANNE2;
2455     case EL_BADEWANNE3:         return GFX_BADEWANNE3;
2456     case EL_BADEWANNE4:         return GFX_BADEWANNE4;
2457     case EL_BADEWANNE5:         return GFX_BADEWANNE5;
2458     case EL_ABLENK_AUS:         return GFX_ABLENK_AUS;
2459     case EL_ABLENK_EIN:         return GFX_ABLENK_EIN;
2460     case EL_SCHLUESSEL1:        return GFX_SCHLUESSEL1;
2461     case EL_SCHLUESSEL2:        return GFX_SCHLUESSEL2;
2462     case EL_SCHLUESSEL3:        return GFX_SCHLUESSEL3;
2463     case EL_SCHLUESSEL4:        return GFX_SCHLUESSEL4;
2464     case EL_PFORTE1:            return GFX_PFORTE1;
2465     case EL_PFORTE2:            return GFX_PFORTE2;
2466     case EL_PFORTE3:            return GFX_PFORTE3;
2467     case EL_PFORTE4:            return GFX_PFORTE4;
2468     case EL_PFORTE1X:           return GFX_PFORTE1X;
2469     case EL_PFORTE2X:           return GFX_PFORTE2X;
2470     case EL_PFORTE3X:           return GFX_PFORTE3X;
2471     case EL_PFORTE4X:           return GFX_PFORTE4X;
2472     case EL_DYNAMIT_AUS:        return GFX_DYNAMIT_AUS;
2473     case EL_PACMAN:             return GFX_PACMAN;
2474     case EL_PACMAN_R:           return GFX_PACMAN_R;
2475     case EL_PACMAN_O:           return GFX_PACMAN_O;
2476     case EL_PACMAN_L:           return GFX_PACMAN_L;
2477     case EL_PACMAN_U:           return GFX_PACMAN_U;
2478     case EL_UNSICHTBAR:         return GFX_UNSICHTBAR;
2479     case EL_ERZ_EDEL:           return GFX_ERZ_EDEL;
2480     case EL_ERZ_DIAM:           return GFX_ERZ_DIAM;
2481     case EL_BIRNE_AUS:          return GFX_BIRNE_AUS;
2482     case EL_BIRNE_EIN:          return GFX_BIRNE_EIN;
2483     case EL_ZEIT_VOLL:          return GFX_ZEIT_VOLL;
2484     case EL_ZEIT_LEER:          return GFX_ZEIT_LEER;
2485     case EL_MAUER_LEBT:         return GFX_MAUER_LEBT;
2486     case EL_MAUER_X:            return GFX_MAUER_X;
2487     case EL_MAUER_Y:            return GFX_MAUER_Y;
2488     case EL_MAUER_XY:           return GFX_MAUER_XY;
2489     case EL_EDELSTEIN_BD:       return GFX_EDELSTEIN_BD;
2490     case EL_EDELSTEIN_GELB:     return GFX_EDELSTEIN_GELB;
2491     case EL_EDELSTEIN_ROT:      return GFX_EDELSTEIN_ROT;
2492     case EL_EDELSTEIN_LILA:     return GFX_EDELSTEIN_LILA;
2493     case EL_ERZ_EDEL_BD:        return GFX_ERZ_EDEL_BD;
2494     case EL_ERZ_EDEL_GELB:      return GFX_ERZ_EDEL_GELB;
2495     case EL_ERZ_EDEL_ROT:       return GFX_ERZ_EDEL_ROT;
2496     case EL_ERZ_EDEL_LILA:      return GFX_ERZ_EDEL_LILA;
2497     case EL_MAMPFER2:           return GFX_MAMPFER2;
2498     case EL_SIEB2_INAKTIV:      return GFX_SIEB2_INAKTIV;
2499     case EL_SIEB2_LEER:         return GFX_SIEB2_LEER;
2500     case EL_SIEB2_VOLL:         return GFX_SIEB2_VOLL;
2501     case EL_SIEB2_TOT:          return GFX_SIEB2_TOT;
2502     case EL_DYNABOMB:           return GFX_DYNABOMB;
2503     case EL_DYNABOMB_NR:        return GFX_DYNABOMB_NR;
2504     case EL_DYNABOMB_SZ:        return GFX_DYNABOMB_SZ;
2505     case EL_DYNABOMB_XL:        return GFX_DYNABOMB_XL;
2506     case EL_SOKOBAN_OBJEKT:     return GFX_SOKOBAN_OBJEKT;
2507     case EL_SOKOBAN_FELD_LEER:  return GFX_SOKOBAN_FELD_LEER;
2508     case EL_SOKOBAN_FELD_VOLL:  return GFX_SOKOBAN_FELD_VOLL;
2509     case EL_MAULWURF:           return GFX_MAULWURF;
2510     case EL_PINGUIN:            return GFX_PINGUIN;
2511     case EL_SCHWEIN:            return GFX_SCHWEIN;
2512     case EL_DRACHE:             return GFX_DRACHE;
2513     case EL_SONDE:              return GFX_SONDE;
2514     case EL_PFEIL_L:            return GFX_PFEIL_L;
2515     case EL_PFEIL_R:            return GFX_PFEIL_R;
2516     case EL_PFEIL_O:            return GFX_PFEIL_O;
2517     case EL_PFEIL_U:            return GFX_PFEIL_U;
2518     case EL_SPEED_PILL:         return GFX_SPEED_PILL;
2519     case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2520     case EL_SP_BUG_ACTIVE:      return GFX_SP_BUG_ACTIVE;
2521     case EL_INVISIBLE_STEEL:    return GFX_INVISIBLE_STEEL;
2522
2523     default:
2524     {
2525       if (IS_CHAR(element))
2526         return GFX_CHAR_START + (element - EL_CHAR_START);
2527       else if (element >= EL_SP_START && element <= EL_SP_END)
2528       {
2529         int nr_element = element - EL_SP_START;
2530         int gfx_per_line = 8;
2531         int nr_graphic =
2532           (nr_element / gfx_per_line) * MORE_PER_LINE +
2533           (nr_element % gfx_per_line);
2534
2535         return GFX_START_ROCKSMORE + nr_graphic;
2536       }
2537       else
2538         return -1;
2539     }
2540   }
2541 }