rnd-20020917-1-src
[rocksndiamonds.git] / src / tools.c
1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back!               *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment                      *
5 *               Holger Schemel                             *
6 *               Detmolder Strasse 189                      *
7 *               33604 Bielefeld                            *
8 *               Germany                                    *
9 *               e-mail: info@artsoft.org                   *
10 *----------------------------------------------------------*
11 * tools.c                                                  *
12 ***********************************************************/
13
14 #include "libgame/libgame.h"
15
16 #include "tools.h"
17 #include "game.h"
18 #include "events.h"
19 #include "cartoons.h"
20 #include "network.h"
21 #include "tape.h"
22
23 /* tool button identifiers */
24 #define TOOL_CTRL_ID_YES        0
25 #define TOOL_CTRL_ID_NO         1
26 #define TOOL_CTRL_ID_CONFIRM    2
27 #define TOOL_CTRL_ID_PLAYER_1   3
28 #define TOOL_CTRL_ID_PLAYER_2   4
29 #define TOOL_CTRL_ID_PLAYER_3   5
30 #define TOOL_CTRL_ID_PLAYER_4   6
31
32 #define NUM_TOOL_BUTTONS        7
33
34 /* forward declaration for internal use */
35 static int getGraphicAnimationPhase(int, int, int);
36 static void DrawGraphicAnimationShiftedThruMask(int, int, int, int, int,
37                                                 int, int, int);
38 static void UnmapToolButtons();
39 static void HandleToolButtons(struct GadgetInfo *);
40
41 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
42 static int request_gadget_id = -1;
43
44 void SetDrawtoField(int mode)
45 {
46   if (mode == DRAW_BUFFERED && setup.soft_scrolling)
47   {
48     FX = TILEX;
49     FY = TILEY;
50     BX1 = -1;
51     BY1 = -1;
52     BX2 = SCR_FIELDX;
53     BY2 = SCR_FIELDY;
54     redraw_x1 = 1;
55     redraw_y1 = 1;
56
57     drawto_field = fieldbuffer;
58   }
59   else  /* DRAW_DIRECT, DRAW_BACKBUFFER */
60   {
61     FX = SX;
62     FY = SY;
63     BX1 = 0;
64     BY1 = 0;
65     BX2 = SCR_FIELDX - 1;
66     BY2 = SCR_FIELDY - 1;
67     redraw_x1 = 0;
68     redraw_y1 = 0;
69
70     drawto_field = (mode == DRAW_DIRECT ? window :  backbuffer);
71   }
72 }
73
74 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
75 {
76   if (game_status == PLAYING)
77   {
78     if (force_redraw)
79     {
80       x = gfx.sx - TILEX;
81       y = gfx.sy - TILEY;
82       width = gfx.sxsize + 2 * TILEX;
83       height = gfx.sysize + 2 * TILEY;
84     }
85
86     if (force_redraw || setup.direct_draw)
87     {
88       int xx, yy;
89       int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
90       int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
91
92       if (setup.direct_draw)
93         SetDrawtoField(DRAW_BACKBUFFER);
94
95       for(xx=BX1; xx<=BX2; xx++)
96         for(yy=BY1; yy<=BY2; yy++)
97           if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
98             DrawScreenField(xx, yy);
99       DrawAllPlayers();
100
101       if (setup.direct_draw)
102         SetDrawtoField(DRAW_DIRECT);
103     }
104
105     if (setup.soft_scrolling)
106     {
107       int fx = FX, fy = FY;
108
109       fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
110       fy += (ScreenMovDir & (MV_UP|MV_DOWN)    ? ScreenGfxPos : 0);
111
112       BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
113     }
114   }
115
116   BlitBitmap(drawto, window, x, y, width, height, x, y);
117 }
118
119 void BackToFront()
120 {
121   int x,y;
122   DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
123
124   if (setup.direct_draw && game_status == PLAYING)
125     redraw_mask &= ~REDRAW_MAIN;
126
127   if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
128     redraw_mask |= REDRAW_FIELD;
129
130   if (redraw_mask & REDRAW_FIELD)
131     redraw_mask &= ~REDRAW_TILES;
132
133   if (redraw_mask == REDRAW_NONE)
134     return;
135
136   if (global.fps_slowdown && game_status == PLAYING)
137   {
138     static boolean last_frame_skipped = FALSE;
139     boolean skip_even_when_not_scrolling = TRUE;
140     boolean just_scrolling = (ScreenMovDir != 0);
141     boolean verbose = FALSE;
142
143     if (global.fps_slowdown_factor > 1 &&
144         (FrameCounter % global.fps_slowdown_factor) &&
145         (just_scrolling || skip_even_when_not_scrolling))
146     {
147       redraw_mask &= ~REDRAW_MAIN;
148
149       last_frame_skipped = TRUE;
150
151       if (verbose)
152         printf("FRAME SKIPPED\n");
153     }
154     else
155     {
156       if (last_frame_skipped)
157         redraw_mask |= REDRAW_FIELD;
158
159       last_frame_skipped = FALSE;
160
161       if (verbose)
162         printf("frame not skipped\n");
163     }
164   }
165
166   /* synchronize X11 graphics at this point; if we would synchronize the
167      display immediately after the buffer switching (after the XFlush),
168      this could mean that we have to wait for the graphics to complete,
169      although we could go on doing calculations for the next frame */
170
171   SyncDisplay();
172
173   if (redraw_mask & REDRAW_ALL)
174   {
175     BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
176     redraw_mask = 0;
177   }
178
179   if (redraw_mask & REDRAW_FIELD)
180   {
181     if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
182     {
183       BlitBitmap(backbuffer, window,
184                  REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
185     }
186     else
187     {
188       int fx = FX, fy = FY;
189
190       if (setup.soft_scrolling)
191       {
192         fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
193         fy += (ScreenMovDir & (MV_UP | MV_DOWN)    ? ScreenGfxPos : 0);
194       }
195
196       if (setup.soft_scrolling ||
197           ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
198           ABS(ScreenMovPos) == ScrollStepSize ||
199           redraw_tiles > REDRAWTILES_THRESHOLD)
200       {
201         BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
202
203 #ifdef DEBUG
204 #if 0
205         printf("redrawing all (ScreenGfxPos == %d) because %s\n",
206                ScreenGfxPos,
207                (setup.soft_scrolling ?
208                 "setup.soft_scrolling" :
209                 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
210                 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
211                 ABS(ScreenGfxPos) == ScrollStepSize ?
212                 "ABS(ScreenGfxPos) == ScrollStepSize" :
213                 "redraw_tiles > REDRAWTILES_THRESHOLD"));
214 #endif
215 #endif
216       }
217     }
218
219     redraw_mask &= ~REDRAW_MAIN;
220   }
221
222   if (redraw_mask & REDRAW_DOORS)
223   {
224     if (redraw_mask & REDRAW_DOOR_1)
225       BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
226     if (redraw_mask & REDRAW_DOOR_2)
227     {
228       if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
229         BlitBitmap(backbuffer, window, VX,VY, VXSIZE,VYSIZE, VX,VY);
230       else
231       {
232         if (redraw_mask & REDRAW_VIDEO_1)
233           BlitBitmap(backbuffer, window,
234                      VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
235                      VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
236                      VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
237         if (redraw_mask & REDRAW_VIDEO_2)
238           BlitBitmap(backbuffer, window,
239                      VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
240                      VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
241                      VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
242         if (redraw_mask & REDRAW_VIDEO_3)
243           BlitBitmap(backbuffer, window,
244                      VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
245                      VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
246                      VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
247       }
248     }
249     if (redraw_mask & REDRAW_DOOR_3)
250       BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
251     redraw_mask &= ~REDRAW_DOORS;
252   }
253
254   if (redraw_mask & REDRAW_MICROLEVEL)
255   {
256     BlitBitmap(backbuffer, window,
257                MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
258                MICROLEV_XPOS, MICROLEV_YPOS);
259     BlitBitmap(backbuffer, window,
260                SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
261                SX, MICROLABEL_YPOS);
262     redraw_mask &= ~REDRAW_MICROLEVEL;
263   }
264
265   if (redraw_mask & REDRAW_TILES)
266   {
267     for(x=0; x<SCR_FIELDX; x++)
268       for(y=0; y<SCR_FIELDY; y++)
269         if (redraw[redraw_x1 + x][redraw_y1 + y])
270           BlitBitmap(buffer, window,
271                      FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
272                      SX + x * TILEX, SY + y * TILEY);
273   }
274
275   if (redraw_mask & REDRAW_FPS)         /* display frames per second */
276   {
277     char text[100];
278     char info1[100];
279
280     sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
281     if (!global.fps_slowdown)
282       info1[0] = '\0';
283
284     sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
285     DrawTextExt(window, SX, SY, text, FS_SMALL, FC_YELLOW);
286   }
287
288   FlushDisplay();
289
290   for(x=0; x<MAX_BUF_XSIZE; x++)
291     for(y=0; y<MAX_BUF_YSIZE; y++)
292       redraw[x][y] = 0;
293   redraw_tiles = 0;
294   redraw_mask = REDRAW_NONE;
295 }
296
297 void FadeToFront()
298 {
299 #if 0
300   long fading_delay = 300;
301
302   if (setup.fading && (redraw_mask & REDRAW_FIELD))
303   {
304 #endif
305
306 #if 0
307     int x,y;
308
309     ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
310     FlushDisplay();
311
312     for(i=0;i<2*FULL_SYSIZE;i++)
313     {
314       for(y=0;y<FULL_SYSIZE;y++)
315       {
316         BlitBitmap(backbuffer, window,
317                    REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
318       }
319       FlushDisplay();
320       Delay(10);
321     }
322 #endif
323
324 #if 0
325     for(i=1;i<FULL_SYSIZE;i+=2)
326       BlitBitmap(backbuffer, window,
327                  REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
328     FlushDisplay();
329     Delay(fading_delay);
330 #endif
331
332 #if 0
333     SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
334     BlitBitmapMasked(backbuffer, window,
335                      REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
336                      REAL_SX,REAL_SY);
337     FlushDisplay();
338     Delay(fading_delay);
339
340     SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
341     BlitBitmapMasked(backbuffer, window,
342                      REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
343                      REAL_SX,REAL_SY);
344     FlushDisplay();
345     Delay(fading_delay);
346
347     SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
348     BlitBitmapMasked(backbuffer, window,
349                      REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
350                      REAL_SX,REAL_SY);
351     FlushDisplay();
352     Delay(fading_delay);
353
354     SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
355     BlitBitmapMasked(backbuffer, window,
356                      REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
357                      REAL_SX,REAL_SY);
358     FlushDisplay();
359     Delay(fading_delay);
360
361     redraw_mask &= ~REDRAW_MAIN;
362   }
363 #endif
364
365   BackToFront();
366 }
367
368 void ClearWindow()
369 {
370   ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
371
372   if (setup.soft_scrolling && game_status == PLAYING)
373   {
374     ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
375     SetDrawtoField(DRAW_BUFFERED);
376   }
377   else
378     SetDrawtoField(DRAW_BACKBUFFER);
379
380   if (setup.direct_draw && game_status == PLAYING)
381   {
382     ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
383     SetDrawtoField(DRAW_DIRECT);
384   }
385
386   redraw_mask |= REDRAW_FIELD;
387 }
388
389 void MarkTileDirty(int x, int y)
390 {
391   int xx = redraw_x1 + x;
392   int yy = redraw_y1 + y;
393
394   if (!redraw[xx][yy])
395     redraw_tiles++;
396
397   redraw[xx][yy] = TRUE;
398   redraw_mask |= REDRAW_TILES;
399 }
400
401 void SetBorderElement()
402 {
403   int x, y;
404
405   BorderElement = EL_LEERRAUM;
406
407   for(y=0; y<lev_fieldy && BorderElement == EL_LEERRAUM; y++)
408   {
409     for(x=0; x<lev_fieldx; x++)
410     {
411       if (!IS_MASSIVE(Feld[x][y]))
412         BorderElement = EL_BETON;
413
414       if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
415         x = lev_fieldx - 2;
416     }
417   }
418 }
419
420 void DrawAllPlayers()
421 {
422   int i;
423
424   for(i=0; i<MAX_PLAYERS; i++)
425     if (stored_player[i].active)
426       DrawPlayer(&stored_player[i]);
427 }
428
429 void DrawPlayerField(int x, int y)
430 {
431   if (!IS_PLAYER(x, y))
432     return;
433
434   DrawPlayer(PLAYERINFO(x, y));
435 }
436
437 void DrawPlayer(struct PlayerInfo *player)
438 {
439   int jx = player->jx, jy = player->jy;
440   int last_jx = player->last_jx, last_jy = player->last_jy;
441   int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
442   int sx = SCREENX(jx), sy = SCREENY(jy);
443   int sxx = 0, syy = 0;
444   int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
445   int graphic, phase;
446   boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
447
448   if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
449     return;
450
451 #if DEBUG
452   if (!IN_LEV_FIELD(jx,jy))
453   {
454     printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
455     printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
456     printf("DrawPlayerField(): This should never happen!\n");
457     return;
458   }
459 #endif
460
461   if (element == EL_EXPLODING)
462     return;
463
464   /* draw things in the field the player is leaving, if needed */
465
466   if (player_is_moving)
467   {
468     if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
469     {
470       DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
471       if (last_element == EL_DYNAMITE_ACTIVE)
472         DrawDynamite(last_jx, last_jy);
473       else
474         DrawLevelFieldThruMask(last_jx, last_jy);
475     }
476     else if (last_element == EL_DYNAMITE_ACTIVE)
477       DrawDynamite(last_jx, last_jy);
478     else
479       DrawLevelField(last_jx, last_jy);
480
481     if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
482     {
483       if (player->GfxPos)
484       {
485         if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
486           DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
487         else
488           DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
489       }
490       else
491         DrawLevelField(next_jx, next_jy);
492     }
493   }
494
495   if (!IN_SCR_FIELD(sx, sy))
496     return;
497
498   if (setup.direct_draw)
499     SetDrawtoField(DRAW_BUFFERED);
500
501   /* draw things behind the player, if needed */
502
503   if (Store[jx][jy])
504     DrawLevelElement(jx, jy, Store[jx][jy]);
505   else if (!IS_ACTIVE_BOMB(element))
506     DrawLevelField(jx, jy);
507   else
508     DrawLevelElement(jx, jy, EL_LEERRAUM);
509
510   /* draw player himself */
511
512   if (game.emulation == EMU_SUPAPLEX)
513   {
514     static int last_dir = MV_LEFT;
515     int action = (player->programmed_action ? player->programmed_action :
516                   player->action);
517     boolean action_moving =
518       (player_is_moving ||
519        ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
520         !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
521
522     graphic = GFX_SP_MURPHY;
523
524     if (player->Pushing)
525     {
526       if (player->MovDir == MV_LEFT)
527         graphic = GFX_MURPHY_PUSH_LEFT;
528       else if (player->MovDir == MV_RIGHT)
529         graphic = GFX_MURPHY_PUSH_RIGHT;
530       else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
531         graphic = GFX_MURPHY_PUSH_LEFT;
532       else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
533         graphic = GFX_MURPHY_PUSH_RIGHT;
534     }
535     else if (player->snapped)
536     {
537       if (player->MovDir == MV_LEFT)
538         graphic = GFX_MURPHY_SNAP_LEFT;
539       else if (player->MovDir == MV_RIGHT)
540         graphic = GFX_MURPHY_SNAP_RIGHT;
541       else if (player->MovDir == MV_UP)
542         graphic = GFX_MURPHY_SNAP_UP;
543       else if (player->MovDir == MV_DOWN)
544         graphic = GFX_MURPHY_SNAP_DOWN;
545     }
546     else if (action_moving)
547     {
548       if (player->MovDir == MV_LEFT)
549         graphic = GFX_MURPHY_GO_LEFT;
550       else if (player->MovDir == MV_RIGHT)
551         graphic = GFX_MURPHY_GO_RIGHT;
552       else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
553         graphic = GFX_MURPHY_GO_LEFT;
554       else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
555         graphic = GFX_MURPHY_GO_RIGHT;
556       else
557         graphic = GFX_MURPHY_GO_LEFT;
558
559       graphic += getGraphicAnimationPhase(3, 2, ANIM_PINGPONG);
560     }
561
562     if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
563       last_dir = player->MovDir;
564   }
565   else
566   {
567     if (player->MovDir == MV_LEFT)
568       graphic =
569         (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
570     else if (player->MovDir == MV_RIGHT)
571       graphic =
572         (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
573     else if (player->MovDir == MV_UP)
574       graphic = GFX_SPIELER1_UP;
575     else        /* MV_DOWN || MV_NO_MOVING */
576       graphic = GFX_SPIELER1_DOWN;
577
578     graphic += player->index_nr * 3 * HEROES_PER_LINE;
579     graphic += player->Frame;
580   }
581
582   if (player->GfxPos)
583   {
584     if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
585       sxx = player->GfxPos;
586     else
587       syy = player->GfxPos;
588   }
589
590   if (!setup.soft_scrolling && ScreenMovPos)
591     sxx = syy = 0;
592
593   DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
594
595   if (SHIELD_ON(player))
596   {
597     int graphic = (player->shield_active_time_left ? GFX2_SHIELD_ACTIVE :
598                    GFX2_SHIELD_PASSIVE);
599
600     DrawGraphicAnimationShiftedThruMask(sx, sy, sxx, syy, graphic,
601                                         3, 8, ANIM_PINGPONG);
602   }
603
604   if (player->Pushing && player->GfxPos)
605   {
606     int px = SCREENX(next_jx), py = SCREENY(next_jy);
607
608     if (element == EL_SOKOBAN_FELD_LEER ||
609         Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
610       DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
611                                  NO_CUTTING);
612     else
613     {
614       int element = Feld[next_jx][next_jy];
615       int graphic = el2gfx(element);
616
617       if ((element == EL_FELSBROCKEN ||
618            element == EL_SP_ZONK ||
619            element == EL_BD_ROCK) && sxx)
620       {
621         int phase = (player->GfxPos / (TILEX / 4));
622
623         if (player->MovDir == MV_LEFT)
624           graphic += phase;
625         else
626           graphic += (phase + 4) % 4;
627       }
628
629       DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
630     }
631   }
632
633   /* draw things in front of player (active dynamite or dynabombs) */
634
635   if (IS_ACTIVE_BOMB(element))
636   {
637     graphic = el2gfx(element);
638
639     if (element == EL_DYNAMITE_ACTIVE)
640     {
641       if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
642         phase = 6;
643     }
644     else
645     {
646       if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
647         phase = 7 - phase;
648     }
649
650     if (game.emulation == EMU_SUPAPLEX)
651       DrawGraphic(sx, sy, GFX_SP_DISK_RED);
652     else
653       DrawGraphicThruMask(sx, sy, graphic + phase);
654   }
655
656   if (player_is_moving && last_element == EL_EXPLODING)
657   {
658     int phase = Frame[last_jx][last_jy];
659     int delay = 2;
660
661     if (phase > 2)
662       DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
663                           GFX_EXPLOSION + ((phase - 1) / delay - 1));
664   }
665
666   /* draw elements that stay over the player */
667   /* handle the field the player is leaving ... */
668   if (player_is_moving && IS_OVER_PLAYER(last_element))
669     DrawLevelField(last_jx, last_jy);
670   /* ... and the field the player is entering */
671   if (IS_OVER_PLAYER(element))
672     DrawLevelField(jx, jy);
673
674   if (setup.direct_draw)
675   {
676     int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
677     int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
678     int x_size = TILEX * (1 + ABS(jx - last_jx));
679     int y_size = TILEY * (1 + ABS(jy - last_jy));
680
681     BlitBitmap(drawto_field, window,
682                dest_x, dest_y, x_size, y_size, dest_x, dest_y);
683     SetDrawtoField(DRAW_DIRECT);
684   }
685
686   MarkTileDirty(sx,sy);
687 }
688
689 static int getGraphicAnimationPhase(int frames, int delay, int mode)
690 {
691   int phase;
692
693   if (mode == ANIM_PINGPONG)
694   {
695     int max_anim_frames = 2 * frames - 2;
696
697     phase = (FrameCounter % (delay * max_anim_frames)) / delay;
698     phase = (phase < frames ? phase : max_anim_frames - phase);
699   }
700   else
701     phase = (FrameCounter % (delay * frames)) / delay;
702
703   if (mode == ANIM_REVERSE)
704     phase = -phase;
705
706   return phase;
707 }
708
709 static int getNewGraphicAnimationFrame(int graphic)
710 {
711   int frames = new_graphic_info[graphic].anim_frames;
712   int delay = new_graphic_info[graphic].anim_delay;
713   int mode = new_graphic_info[graphic].anim_mode;
714   int phase;
715
716   if (mode == ANIM_PINGPONG)
717   {
718     int max_anim_frames = 2 * frames - 2;
719
720     phase = (FrameCounter % (delay * max_anim_frames)) / delay;
721     phase = (phase < frames ? phase : max_anim_frames - phase);
722   }
723   else
724     phase = (FrameCounter % (delay * frames)) / delay;
725
726   if (mode == ANIM_REVERSE)
727     phase = (frames - 1) - phase;
728
729   return phase;
730 }
731
732 void DrawGraphicAnimationExt(int x, int y, int graphic,
733                              int frames, int delay, int mode, int mask_mode)
734 {
735   int phase = getGraphicAnimationPhase(frames, delay, mode);
736
737   if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
738   {
739     if (mask_mode == USE_MASKING)
740       DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
741     else
742       DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
743   }
744 }
745
746 void DrawNewGraphicAnimationExt(int x, int y, int graphic, int mask_mode)
747 {
748   int delay = new_graphic_info[graphic].anim_delay;
749
750   if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
751   {
752     int frame = getNewGraphicAnimationFrame(graphic);
753
754     if (mask_mode == USE_MASKING)
755       DrawNewGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
756     else
757       DrawNewGraphic(SCREENX(x), SCREENY(y), graphic, frame);
758   }
759 }
760
761 void DrawGraphicAnimation(int x, int y, int graphic,
762                           int frames, int delay, int mode)
763 {
764   DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
765 }
766
767 void DrawNewGraphicAnimation(int x, int y, int graphic)
768 {
769   DrawNewGraphicAnimationExt(x, y, graphic, NO_MASKING);
770 }
771
772 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
773                                   int frames, int delay, int mode)
774 {
775   DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
776 }
777
778 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
779                                                 int sxx, int syy,
780                                                 int graphic,
781                                                 int frames, int delay,
782                                                 int mode)
783 {
784   int phase = getGraphicAnimationPhase(frames, delay, mode);
785
786   DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
787 }
788
789 void getGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
790 {
791   if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
792   {
793     *bitmap = graphic_info[graphic].bitmap;
794     *x = graphic_info[graphic].src_x;
795     *y = graphic_info[graphic].src_y;
796   }
797   else if (graphic >= GFX_START_ROCKSELEMENTS &&
798            graphic <= GFX_END_ROCKSELEMENTS)
799   {
800     graphic -= GFX_START_ROCKSELEMENTS;
801     *bitmap = pix[PIX_ELEMENTS];
802     *x = (graphic % GFX_PER_LINE) * TILEX;
803     *y = (graphic / GFX_PER_LINE) * TILEY;
804   }
805   else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
806   {
807     graphic -= GFX_START_ROCKSHEROES;
808     *bitmap = pix[PIX_HEROES];
809     *x = (graphic % HEROES_PER_LINE) * TILEX;
810     *y = (graphic / HEROES_PER_LINE) * TILEY;
811   }
812   else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
813   {
814     graphic -= GFX_START_ROCKSSP;
815     *bitmap = pix[PIX_SP];
816     *x = (graphic % SP_PER_LINE) * TILEX;
817     *y = (graphic / SP_PER_LINE) * TILEY;
818   }
819   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
820   {
821     graphic -= GFX_START_ROCKSDC;
822     *bitmap = pix[PIX_DC];
823     *x = (graphic % DC_PER_LINE) * TILEX;
824     *y = (graphic / DC_PER_LINE) * TILEY;
825   }
826   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
827   {
828     graphic -= GFX_START_ROCKSMORE;
829     *bitmap = pix[PIX_MORE];
830     *x = (graphic % MORE_PER_LINE) * TILEX;
831     *y = (graphic / MORE_PER_LINE) * TILEY;
832   }
833   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
834   {
835     graphic -= GFX_START_ROCKSFONT;
836     *bitmap = pix[PIX_FONT_EM];
837     *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
838     *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
839   }
840   else
841   {
842     *bitmap = pix[PIX_SP];
843     *x = 0;
844     *y = 0;
845   }
846 }
847
848 void DrawGraphic(int x, int y, int graphic)
849 {
850 #if DEBUG
851   if (!IN_SCR_FIELD(x, y))
852   {
853     printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
854     printf("DrawGraphic(): This should never happen!\n");
855     return;
856   }
857 #endif
858
859   DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic);
860   MarkTileDirty(x, y);
861 }
862
863 void DrawNewGraphic(int x, int y, int graphic, int frame)
864 {
865 #if DEBUG
866   if (!IN_SCR_FIELD(x, y))
867   {
868     printf("DrawNewGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
869     printf("DrawNewGraphic(): This should never happen!\n");
870     return;
871   }
872 #endif
873
874   DrawNewGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
875                     graphic, frame);
876   MarkTileDirty(x, y);
877 }
878
879 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
880 {
881   Bitmap *src_bitmap;
882   int src_x, src_y;
883
884   getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
885   BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
886 }
887
888 void DrawNewGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
889                        int frame)
890 {
891   Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
892   int src_x = new_graphic_info[graphic].src_x;
893   int src_y = new_graphic_info[graphic].src_y;
894
895   if (new_graphic_info[graphic].anim_vertical)
896     src_y += frame * TILEY;
897   else
898     src_x += frame * TILEX;
899
900   BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
901 }
902
903 void DrawGraphicThruMask(int x, int y, int graphic)
904 {
905 #if DEBUG
906   if (!IN_SCR_FIELD(x, y))
907   {
908     printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
909     printf("DrawGraphicThruMask(): This should never happen!\n");
910     return;
911   }
912 #endif
913
914   DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic);
915   MarkTileDirty(x, y);
916 }
917
918 void DrawNewGraphicThruMask(int x, int y, int graphic, int frame)
919 {
920 #if DEBUG
921   if (!IN_SCR_FIELD(x, y))
922   {
923     printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
924     printf("DrawGraphicThruMask(): This should never happen!\n");
925     return;
926   }
927 #endif
928
929   DrawNewGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY,
930                             graphic, frame);
931   MarkTileDirty(x, y);
932 }
933
934 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
935 {
936   int tile = graphic;
937   int src_x, src_y;
938   Bitmap *src_bitmap;
939   GC drawing_gc;
940
941   if (graphic == GFX_LEERRAUM)
942     return;
943
944   getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
945   drawing_gc = src_bitmap->stored_clip_gc;
946
947   if (tile_clipmask[tile] != None)
948   {
949     SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
950     SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
951     BlitBitmapMasked(src_bitmap, d,
952                      src_x, src_y, TILEX, TILEY, dest_x, dest_y);
953   }
954   else
955   {
956 #if DEBUG
957 #ifndef TARGET_SDL
958     printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
959 #endif
960 #endif
961
962     SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
963     BlitBitmapMasked(src_bitmap, d,
964                      src_x, src_y, TILEX, TILEY, dest_x, dest_y);
965   }
966 }
967
968 void DrawNewGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y,
969                                int graphic, int frame)
970 {
971   Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
972   GC drawing_gc = src_bitmap->stored_clip_gc;
973   int src_x = new_graphic_info[graphic].src_x;
974   int src_y = new_graphic_info[graphic].src_y;
975
976   if (new_graphic_info[graphic].anim_vertical)
977     src_y += frame * TILEY;
978   else
979     src_x += frame * TILEX;
980
981   SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
982   BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
983 }
984
985 void DrawMiniGraphic(int x, int y, int graphic)
986 {
987   DrawMiniGraphicExt(drawto, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
988   MarkTileDirty(x/2, y/2);
989 }
990
991 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
992 {
993   if (graphic >= GFX_START_ROCKSELEMENTS && graphic <= GFX_END_ROCKSELEMENTS)
994   {
995     graphic -= GFX_START_ROCKSELEMENTS;
996     *bitmap = pix[PIX_ELEMENTS];
997     *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
998     *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
999   }
1000   else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1001   {
1002     graphic -= GFX_START_ROCKSSP;
1003     *bitmap = pix[PIX_SP];
1004     *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
1005     *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
1006   }
1007   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1008   {
1009     graphic -= GFX_START_ROCKSDC;
1010     *bitmap = pix[PIX_DC];
1011     *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
1012     *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
1013   }
1014   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1015   {
1016     graphic -= GFX_START_ROCKSMORE;
1017     *bitmap = pix[PIX_MORE];
1018     *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
1019     *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
1020   }
1021   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
1022   {
1023     graphic -= GFX_START_ROCKSFONT;
1024     *bitmap = pix[PIX_FONT_EM];
1025     *x = MINI_FONT_STARTX + (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
1026     *y = MINI_FONT_STARTY + (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE;
1027   }
1028   else
1029   {
1030     *bitmap = pix[PIX_SP];
1031     *x = MINI_SP_STARTX;
1032     *y = MINI_SP_STARTY;
1033   }
1034 }
1035
1036 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1037 {
1038   Bitmap *bitmap;
1039   int src_x, src_y;
1040
1041   getMiniGraphicSource(graphic, &bitmap, &src_x, &src_y);
1042   BlitBitmap(bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1043 }
1044
1045 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
1046                         int cut_mode, int mask_mode)
1047 {
1048   int width = TILEX, height = TILEY;
1049   int cx = 0, cy = 0;
1050   int src_x, src_y, dest_x, dest_y;
1051   int tile = graphic;
1052   Bitmap *src_bitmap;
1053   GC drawing_gc;
1054
1055   if (graphic < 0)
1056   {
1057     DrawGraphic(x, y, graphic);
1058     return;
1059   }
1060
1061   if (dx || dy)                 /* Verschiebung der Grafik? */
1062   {
1063     if (x < BX1)                /* Element kommt von links ins Bild */
1064     {
1065       x = BX1;
1066       width = dx;
1067       cx = TILEX - dx;
1068       dx = 0;
1069     }
1070     else if (x > BX2)           /* Element kommt von rechts ins Bild */
1071     {
1072       x = BX2;
1073       width = -dx;
1074       dx = TILEX + dx;
1075     }
1076     else if (x==BX1 && dx < 0)  /* Element verläßt links das Bild */
1077     {
1078       width += dx;
1079       cx = -dx;
1080       dx = 0;
1081     }
1082     else if (x==BX2 && dx > 0)  /* Element verläßt rechts das Bild */
1083       width -= dx;
1084     else if (dx)                /* allg. Bewegung in x-Richtung */
1085       MarkTileDirty(x + SIGN(dx), y);
1086
1087     if (y < BY1)                /* Element kommt von oben ins Bild */
1088     {
1089       if (cut_mode==CUT_BELOW)  /* Element oberhalb des Bildes */
1090         return;
1091
1092       y = BY1;
1093       height = dy;
1094       cy = TILEY - dy;
1095       dy = 0;
1096     }
1097     else if (y > BY2)           /* Element kommt von unten ins Bild */
1098     {
1099       y = BY2;
1100       height = -dy;
1101       dy = TILEY + dy;
1102     }
1103     else if (y==BY1 && dy < 0)  /* Element verläßt oben das Bild */
1104     {
1105       height += dy;
1106       cy = -dy;
1107       dy = 0;
1108     }
1109     else if (dy > 0 && cut_mode == CUT_ABOVE)
1110     {
1111       if (y == BY2)             /* Element unterhalb des Bildes */
1112         return;
1113
1114       height = dy;
1115       cy = TILEY - dy;
1116       dy = TILEY;
1117       MarkTileDirty(x, y + 1);
1118     }                           /* Element verläßt unten das Bild */
1119     else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1120       height -= dy;
1121     else if (dy)                /* allg. Bewegung in y-Richtung */
1122       MarkTileDirty(x, y + SIGN(dy));
1123   }
1124
1125   getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1126   drawing_gc = src_bitmap->stored_clip_gc;
1127
1128   src_x += cx;
1129   src_y += cy;
1130
1131   dest_x = FX + x * TILEX + dx;
1132   dest_y = FY + y * TILEY + dy;
1133
1134 #if DEBUG
1135   if (!IN_SCR_FIELD(x,y))
1136   {
1137     printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1138     printf("DrawGraphicShifted(): This should never happen!\n");
1139     return;
1140   }
1141 #endif
1142
1143   if (mask_mode == USE_MASKING)
1144   {
1145     if (tile_clipmask[tile] != None)
1146     {
1147       SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
1148       SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
1149       BlitBitmapMasked(src_bitmap, drawto_field,
1150                        src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1151     }
1152     else
1153     {
1154 #if DEBUG
1155 #ifndef TARGET_SDL
1156       printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1157 #endif
1158 #endif
1159
1160       SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1161       BlitBitmapMasked(src_bitmap, drawto_field,
1162                        src_x, src_y, width, height, dest_x, dest_y);
1163     }
1164   }
1165   else
1166     BlitBitmap(src_bitmap, drawto_field,
1167                src_x, src_y, width, height, dest_x, dest_y);
1168
1169   MarkTileDirty(x,y);
1170 }
1171
1172 void DrawNewGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1173                         int cut_mode, int mask_mode)
1174 {
1175   Bitmap *src_bitmap;
1176   GC drawing_gc;
1177   int src_x;
1178   int src_y;
1179
1180   int width = TILEX, height = TILEY;
1181   int cx = 0, cy = 0;
1182   int dest_x, dest_y;
1183
1184   if (graphic < 0)
1185   {
1186     DrawNewGraphic(x, y, graphic, frame);
1187     return;
1188   }
1189
1190   if (dx || dy)                 /* Verschiebung der Grafik? */
1191   {
1192     if (x < BX1)                /* Element kommt von links ins Bild */
1193     {
1194       x = BX1;
1195       width = dx;
1196       cx = TILEX - dx;
1197       dx = 0;
1198     }
1199     else if (x > BX2)           /* Element kommt von rechts ins Bild */
1200     {
1201       x = BX2;
1202       width = -dx;
1203       dx = TILEX + dx;
1204     }
1205     else if (x==BX1 && dx < 0)  /* Element verläßt links das Bild */
1206     {
1207       width += dx;
1208       cx = -dx;
1209       dx = 0;
1210     }
1211     else if (x==BX2 && dx > 0)  /* Element verläßt rechts das Bild */
1212       width -= dx;
1213     else if (dx)                /* allg. Bewegung in x-Richtung */
1214       MarkTileDirty(x + SIGN(dx), y);
1215
1216     if (y < BY1)                /* Element kommt von oben ins Bild */
1217     {
1218       if (cut_mode==CUT_BELOW)  /* Element oberhalb des Bildes */
1219         return;
1220
1221       y = BY1;
1222       height = dy;
1223       cy = TILEY - dy;
1224       dy = 0;
1225     }
1226     else if (y > BY2)           /* Element kommt von unten ins Bild */
1227     {
1228       y = BY2;
1229       height = -dy;
1230       dy = TILEY + dy;
1231     }
1232     else if (y==BY1 && dy < 0)  /* Element verläßt oben das Bild */
1233     {
1234       height += dy;
1235       cy = -dy;
1236       dy = 0;
1237     }
1238     else if (dy > 0 && cut_mode == CUT_ABOVE)
1239     {
1240       if (y == BY2)             /* Element unterhalb des Bildes */
1241         return;
1242
1243       height = dy;
1244       cy = TILEY - dy;
1245       dy = TILEY;
1246       MarkTileDirty(x, y + 1);
1247     }                           /* Element verläßt unten das Bild */
1248     else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1249       height -= dy;
1250     else if (dy)                /* allg. Bewegung in y-Richtung */
1251       MarkTileDirty(x, y + SIGN(dy));
1252   }
1253
1254   src_bitmap = new_graphic_info[graphic].bitmap;
1255   drawing_gc = src_bitmap->stored_clip_gc;
1256   src_x = new_graphic_info[graphic].src_x;
1257   src_y = new_graphic_info[graphic].src_y;
1258
1259   if (new_graphic_info[graphic].anim_vertical)
1260     src_y += frame * TILEY;
1261   else
1262     src_x += frame * TILEX;
1263
1264   src_x += cx;
1265   src_y += cy;
1266
1267   dest_x = FX + x * TILEX + dx;
1268   dest_y = FY + y * TILEY + dy;
1269
1270 #if DEBUG
1271   if (!IN_SCR_FIELD(x,y))
1272   {
1273     printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1274     printf("DrawGraphicShifted(): This should never happen!\n");
1275     return;
1276   }
1277 #endif
1278
1279   if (mask_mode == USE_MASKING)
1280     SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1281
1282   BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1283              dest_x, dest_y);
1284
1285   MarkTileDirty(x,y);
1286 }
1287
1288 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1289                                 int cut_mode)
1290 {
1291   DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1292 }
1293
1294 void DrawNewGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1295                                    int frame, int cut_mode)
1296 {
1297   DrawNewGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1298 }
1299
1300 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1301                           int cut_mode, int mask_mode)
1302 {
1303   int ux = LEVELX(x), uy = LEVELY(y);
1304   int graphic = el2gfx(element);
1305   int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1306   int phase4 = phase8 / 2;
1307   int phase2  = phase8 / 4;
1308   int dir = MovDir[ux][uy];
1309
1310   if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1311   {
1312     graphic += 1 * !phase2;
1313
1314     if (dir == MV_UP)
1315       graphic += 1 * 2;
1316     else if (dir == MV_LEFT)
1317       graphic += 2 * 2;
1318     else if (dir == MV_DOWN)
1319       graphic += 3 * 2;
1320   }
1321   else if (element == EL_SP_SNIKSNAK)
1322   {
1323     if (dir == MV_LEFT)
1324       graphic = GFX_SP_SNIKSNAK_LEFT;
1325     else if (dir == MV_RIGHT)
1326       graphic = GFX_SP_SNIKSNAK_RIGHT;
1327     else if (dir == MV_UP)
1328       graphic = GFX_SP_SNIKSNAK_UP;
1329     else
1330       graphic = GFX_SP_SNIKSNAK_DOWN;
1331
1332     graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1333   }
1334   else if (element == EL_SP_ELECTRON)
1335   {
1336     graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1337   }
1338   else if (element == EL_MOLE || element == EL_PINGUIN ||
1339            element == EL_SCHWEIN || element == EL_DRACHE)
1340   {
1341     if (dir == MV_LEFT)
1342       graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1343                  element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1344                  element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1345     else if (dir == MV_RIGHT)
1346       graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1347                  element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1348                  element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1349     else if (dir == MV_UP)
1350       graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1351                  element == EL_PINGUIN ? GFX_PINGUIN_UP :
1352                  element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1353     else
1354       graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1355                  element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1356                  element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1357
1358     graphic += phase4;
1359   }
1360   else if (element == EL_SONDE)
1361   {
1362     graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1363   }
1364   else if (element == EL_SALZSAEURE)
1365   {
1366     graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1367   }
1368   else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1369   {
1370     graphic += !phase2;
1371   }
1372   else if (element == EL_BALLOON)
1373   {
1374     graphic += phase4;
1375   }
1376   else if ((element == EL_FELSBROCKEN ||
1377             element == EL_SP_ZONK ||
1378             element == EL_BD_ROCK ||
1379             element == EL_SP_INFOTRON ||
1380             IS_GEM(element))
1381            && !cut_mode)
1382   {
1383     if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1384     {
1385       if (element == EL_FELSBROCKEN ||
1386           element == EL_SP_ZONK ||
1387           element == EL_BD_ROCK)
1388       {
1389         if (dir == MV_LEFT)
1390           graphic += (4 - phase4) % 4;
1391         else if (dir == MV_RIGHT)
1392           graphic += phase4;
1393         else
1394           graphic += phase2 * 2;
1395       }
1396       else if (element != EL_SP_INFOTRON)
1397         graphic += phase2;
1398     }
1399   }
1400   else if (element == EL_MAGIC_WALL_EMPTY ||
1401            element == EL_MAGIC_WALL_EMPTYING ||
1402            element == EL_MAGIC_WALL_BD_EMPTY ||
1403            element == EL_MAGIC_WALL_BD_EMPTYING ||
1404            element == EL_MAGIC_WALL_FULL ||
1405            element == EL_MAGIC_WALL_BD_FULL)
1406   {
1407     graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1408   }
1409   else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1410   {
1411     graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1412     graphic += (x + 2 * y + 4) % 4;
1413   }
1414   else if (element == EL_MAUER_LEBT)
1415   {
1416     boolean links_massiv = FALSE, rechts_massiv = FALSE;
1417
1418     if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1419       links_massiv = TRUE;
1420     if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1421       rechts_massiv = TRUE;
1422
1423     if (links_massiv && rechts_massiv)
1424       graphic = GFX_MAUERWERK;
1425     else if (links_massiv)
1426       graphic = GFX_MAUER_R;
1427     else if (rechts_massiv)
1428       graphic = GFX_MAUER_L;
1429   }
1430   else if ((element == EL_INVISIBLE_STEEL ||
1431             element == EL_UNSICHTBAR ||
1432             element == EL_SAND_INVISIBLE) && game.light_time_left)
1433   {
1434     graphic = (element == EL_INVISIBLE_STEEL ? GFX_INVISIBLE_STEEL_ON :
1435                element == EL_UNSICHTBAR ? GFX_UNSICHTBAR_ON :
1436                GFX_SAND_INVISIBLE_ON);
1437   }
1438
1439   if (dx || dy)
1440     DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1441   else if (mask_mode == USE_MASKING)
1442     DrawGraphicThruMask(x, y, graphic);
1443   else
1444     DrawGraphic(x, y, graphic);
1445 }
1446
1447 void DrawNewScreenElementExt(int x, int y, int dx, int dy, int element,
1448                           int cut_mode, int mask_mode)
1449 {
1450   int ux = LEVELX(x), uy = LEVELY(y);
1451   int dir = MovDir[ux][uy];
1452   int graphic = el_dir2img(element, dir);
1453   int frame = getNewGraphicAnimationFrame(graphic);
1454   int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1455   int phase4 = phase8 / 2;
1456   int phase2  = phase8 / 4;
1457
1458   if (element == EL_KAEFER)
1459   {
1460     ;
1461   }
1462   else if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1463   {
1464     graphic += 1 * !phase2;
1465
1466     if (dir == MV_UP)
1467       graphic += 1 * 2;
1468     else if (dir == MV_LEFT)
1469       graphic += 2 * 2;
1470     else if (dir == MV_DOWN)
1471       graphic += 3 * 2;
1472   }
1473   else if (element == EL_SP_SNIKSNAK)
1474   {
1475     if (dir == MV_LEFT)
1476       graphic = GFX_SP_SNIKSNAK_LEFT;
1477     else if (dir == MV_RIGHT)
1478       graphic = GFX_SP_SNIKSNAK_RIGHT;
1479     else if (dir == MV_UP)
1480       graphic = GFX_SP_SNIKSNAK_UP;
1481     else
1482       graphic = GFX_SP_SNIKSNAK_DOWN;
1483
1484     graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1485   }
1486   else if (element == EL_SP_ELECTRON)
1487   {
1488 #if 1
1489     graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1490 #else
1491     graphic = GFX2_SP_ELECTRON + getNewGraphicAnimationFrame(graphic);
1492 #endif
1493   }
1494   else if (element == EL_MOLE || element == EL_PINGUIN ||
1495            element == EL_SCHWEIN || element == EL_DRACHE)
1496   {
1497     if (dir == MV_LEFT)
1498       graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1499                  element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1500                  element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1501     else if (dir == MV_RIGHT)
1502       graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1503                  element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1504                  element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1505     else if (dir == MV_UP)
1506       graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1507                  element == EL_PINGUIN ? GFX_PINGUIN_UP :
1508                  element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1509     else
1510       graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1511                  element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1512                  element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1513
1514     graphic += phase4;
1515   }
1516   else if (element == EL_SONDE)
1517   {
1518 #if 1
1519     graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1520 #else
1521     graphic = GFX_SONDE_START + getNewGraphicAnimationFrame(graphic);
1522 #endif
1523   }
1524   else if (element == EL_SALZSAEURE)
1525   {
1526 #if 1
1527     graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1528 #else
1529     graphic = GFX_GEBLUBBER + getNewGraphicAnimationFrame(graphic);
1530 #endif
1531   }
1532   else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1533   {
1534     graphic += !phase2;
1535   }
1536   else if (element == EL_BALLOON)
1537   {
1538     graphic += phase4;
1539   }
1540   else if ((element == EL_FELSBROCKEN ||
1541             element == EL_SP_ZONK ||
1542             element == EL_BD_ROCK ||
1543             element == EL_SP_INFOTRON ||
1544             IS_GEM(element))
1545            && !cut_mode)
1546   {
1547     if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1548     {
1549       if (element == EL_FELSBROCKEN ||
1550           element == EL_SP_ZONK ||
1551           element == EL_BD_ROCK)
1552       {
1553         if (dir == MV_LEFT)
1554           graphic += (4 - phase4) % 4;
1555         else if (dir == MV_RIGHT)
1556           graphic += phase4;
1557         else
1558           graphic += phase2 * 2;
1559       }
1560       else if (element != EL_SP_INFOTRON)
1561         graphic += phase2;
1562     }
1563   }
1564   else if (element == EL_MAGIC_WALL_EMPTY ||
1565            element == EL_MAGIC_WALL_EMPTYING ||
1566            element == EL_MAGIC_WALL_BD_EMPTY ||
1567            element == EL_MAGIC_WALL_BD_EMPTYING ||
1568            element == EL_MAGIC_WALL_FULL ||
1569            element == EL_MAGIC_WALL_BD_FULL)
1570   {
1571 #if 1
1572     graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1573 #else
1574     graphic += 3 + getNewGraphicAnimationFrame(graphic);
1575 #endif
1576   }
1577   else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1578   {
1579     graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1580     graphic += (x + 2 * y + 4) % 4;
1581   }
1582   else if (element == EL_MAUER_LEBT)
1583   {
1584     boolean links_massiv = FALSE, rechts_massiv = FALSE;
1585
1586     if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1587       links_massiv = TRUE;
1588     if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1589       rechts_massiv = TRUE;
1590
1591     if (links_massiv && rechts_massiv)
1592       graphic = GFX_MAUERWERK;
1593     else if (links_massiv)
1594       graphic = GFX_MAUER_R;
1595     else if (rechts_massiv)
1596       graphic = GFX_MAUER_L;
1597   }
1598   else if ((element == EL_INVISIBLE_STEEL ||
1599             element == EL_UNSICHTBAR ||
1600             element == EL_SAND_INVISIBLE) && game.light_time_left)
1601   {
1602     graphic = (element == EL_INVISIBLE_STEEL ? GFX_INVISIBLE_STEEL_ON :
1603                element == EL_UNSICHTBAR ? GFX_UNSICHTBAR_ON :
1604                GFX_SAND_INVISIBLE_ON);
1605   }
1606
1607   if (dx || dy)
1608     DrawNewGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1609   else if (mask_mode == USE_MASKING)
1610     DrawNewGraphicThruMask(x, y, graphic, frame);
1611   else
1612     DrawNewGraphic(x, y, graphic, frame);
1613 }
1614
1615 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1616                          int cut_mode, int mask_mode)
1617 {
1618   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1619     DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1620                          cut_mode, mask_mode);
1621 }
1622
1623 void DrawNewLevelElementExt(int x, int y, int dx, int dy, int element,
1624                          int cut_mode, int mask_mode)
1625 {
1626   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1627     DrawNewScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1628                          cut_mode, mask_mode);
1629 }
1630
1631 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1632                               int cut_mode)
1633 {
1634   DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1635 }
1636
1637 void DrawNewScreenElementShifted(int x, int y, int dx, int dy, int element,
1638                               int cut_mode)
1639 {
1640   DrawNewScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1641 }
1642
1643 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1644                              int cut_mode)
1645 {
1646   DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1647 }
1648
1649 void DrawNewLevelElementShifted(int x, int y, int dx, int dy, int element,
1650                              int cut_mode)
1651 {
1652   DrawNewLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1653 }
1654
1655 void DrawScreenElementThruMask(int x, int y, int element)
1656 {
1657   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1658 }
1659
1660 void DrawNewScreenElementThruMask(int x, int y, int element)
1661 {
1662   DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1663 }
1664
1665 void DrawLevelElementThruMask(int x, int y, int element)
1666 {
1667   DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1668 }
1669
1670 void DrawNewLevelElementThruMask(int x, int y, int element)
1671 {
1672   DrawNewLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1673 }
1674
1675 void DrawLevelFieldThruMask(int x, int y)
1676 {
1677   DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1678 }
1679
1680 void DrawNewLevelFieldThruMask(int x, int y)
1681 {
1682   DrawNewLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1683 }
1684
1685 void ErdreichAnbroeckeln(int x, int y)
1686 {
1687   Bitmap *src_bitmap;
1688   int src_x, src_y;
1689   int i, width, height, cx,cy;
1690   int ux = LEVELX(x), uy = LEVELY(y);
1691   int element, graphic;
1692   int snip = 4;
1693   static int xy[4][2] =
1694   {
1695     { 0, -1 },
1696     { -1, 0 },
1697     { +1, 0 },
1698     { 0, +1 }
1699   };
1700
1701   if (!IN_LEV_FIELD(ux, uy))
1702     return;
1703
1704   element = Feld[ux][uy];
1705
1706   if (element == EL_ERDREICH ||
1707       element == EL_LANDMINE ||
1708       element == EL_TRAP_INACTIVE ||
1709       element == EL_TRAP_ACTIVE)
1710   {
1711     if (!IN_SCR_FIELD(x, y))
1712       return;
1713
1714     graphic = GFX_ERDENRAND;
1715
1716     getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1717
1718     for(i=0; i<4; i++)
1719     {
1720       int uxx, uyy;
1721
1722       uxx = ux + xy[i][0];
1723       uyy = uy + xy[i][1];
1724       if (!IN_LEV_FIELD(uxx, uyy))
1725         element = EL_BETON;
1726       else
1727         element = Feld[uxx][uyy];
1728
1729       if (element == EL_ERDREICH ||
1730           element == EL_LANDMINE ||
1731           element == EL_TRAP_INACTIVE ||
1732           element == EL_TRAP_ACTIVE)
1733         continue;
1734
1735       if (i == 1 || i == 2)
1736       {
1737         width = snip;
1738         height = TILEY;
1739         cx = (i == 2 ? TILEX - snip : 0);
1740         cy = 0;
1741       }
1742       else
1743       {
1744         width = TILEX;
1745         height = snip;
1746         cx = 0;
1747         cy = (i == 3 ? TILEY - snip : 0);
1748       }
1749
1750       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1751                  width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1752     }
1753
1754     MarkTileDirty(x, y);
1755   }
1756   else
1757   {
1758     graphic = GFX_ERDENRAND;
1759
1760     getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1761
1762     for(i=0; i<4; i++)
1763     {
1764       int xx, yy, uxx, uyy;
1765
1766       xx = x + xy[i][0];
1767       yy = y + xy[i][1];
1768       uxx = ux + xy[i][0];
1769       uyy = uy + xy[i][1];
1770
1771       if (!IN_LEV_FIELD(uxx, uyy) ||
1772           (Feld[uxx][uyy] != EL_ERDREICH &&
1773            Feld[uxx][uyy] != EL_LANDMINE &&
1774            Feld[uxx][uyy] != EL_TRAP_INACTIVE &&
1775            Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1776           !IN_SCR_FIELD(xx, yy))
1777         continue;
1778
1779       if (i == 1 || i == 2)
1780       {
1781         width = snip;
1782         height = TILEY;
1783         cx = (i == 1 ? TILEX - snip : 0);
1784         cy = 0;
1785       }
1786       else
1787       {
1788         width = TILEX;
1789         height = snip;
1790         cx = 0;
1791         cy = (i==0 ? TILEY-snip : 0);
1792       }
1793
1794       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1795                  width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1796
1797       MarkTileDirty(xx, yy);
1798     }
1799   }
1800 }
1801
1802 void DrawScreenElement(int x, int y, int element)
1803 {
1804   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1805   ErdreichAnbroeckeln(x, y);
1806 }
1807
1808 void DrawNewScreenElement(int x, int y, int element)
1809 {
1810   DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1811   ErdreichAnbroeckeln(x, y);
1812 }
1813
1814 void DrawLevelElement(int x, int y, int element)
1815 {
1816   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1817     DrawScreenElement(SCREENX(x), SCREENY(y), element);
1818 }
1819
1820 void DrawNewLevelElement(int x, int y, int element)
1821 {
1822   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1823     DrawNewScreenElement(SCREENX(x), SCREENY(y), element);
1824 }
1825
1826 void DrawScreenField(int x, int y)
1827 {
1828   int ux = LEVELX(x), uy = LEVELY(y);
1829   int element, content;
1830
1831   if (!IN_LEV_FIELD(ux, uy))
1832   {
1833     if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1834       element = EL_LEERRAUM;
1835     else
1836       element = BorderElement;
1837
1838     DrawScreenElement(x, y, element);
1839     return;
1840   }
1841
1842   element = Feld[ux][uy];
1843   content = Store[ux][uy];
1844
1845   if (IS_MOVING(ux, uy))
1846   {
1847     int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1848     boolean cut_mode = NO_CUTTING;
1849
1850     if (element == EL_QUICKSAND_EMPTYING ||
1851         element == EL_MAGIC_WALL_EMPTYING ||
1852         element == EL_MAGIC_WALL_BD_EMPTYING ||
1853         element == EL_AMOEBA_DRIPPING)
1854       cut_mode = CUT_ABOVE;
1855     else if (element == EL_QUICKSAND_FILLING ||
1856              element == EL_MAGIC_WALL_FILLING ||
1857              element == EL_MAGIC_WALL_BD_FILLING)
1858       cut_mode = CUT_BELOW;
1859
1860     if (cut_mode == CUT_ABOVE)
1861       DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1862     else
1863       DrawScreenElement(x, y, EL_LEERRAUM);
1864
1865     if (horiz_move)
1866       DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1867     else if (cut_mode == NO_CUTTING)
1868       DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1869     else
1870       DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1871
1872     if (content == EL_SALZSAEURE)
1873       DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1874   }
1875   else if (IS_BLOCKED(ux, uy))
1876   {
1877     int oldx, oldy;
1878     int sx, sy;
1879     int horiz_move;
1880     boolean cut_mode = NO_CUTTING;
1881     int element_old, content_old;
1882
1883     Blocked2Moving(ux, uy, &oldx, &oldy);
1884     sx = SCREENX(oldx);
1885     sy = SCREENY(oldy);
1886     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1887                   MovDir[oldx][oldy] == MV_RIGHT);
1888
1889     element_old = Feld[oldx][oldy];
1890     content_old = Store[oldx][oldy];
1891
1892     if (element_old == EL_QUICKSAND_EMPTYING ||
1893         element_old == EL_MAGIC_WALL_EMPTYING ||
1894         element_old == EL_MAGIC_WALL_BD_EMPTYING ||
1895         element_old == EL_AMOEBA_DRIPPING)
1896       cut_mode = CUT_ABOVE;
1897
1898     DrawScreenElement(x, y, EL_LEERRAUM);
1899
1900     if (horiz_move)
1901       DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1902                                NO_CUTTING);
1903     else if (cut_mode == NO_CUTTING)
1904       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1905                                cut_mode);
1906     else
1907       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1908                                cut_mode);
1909   }
1910   else if (IS_DRAWABLE(element))
1911     DrawScreenElement(x, y, element);
1912   else
1913     DrawScreenElement(x, y, EL_LEERRAUM);
1914 }
1915
1916 void DrawNewScreenField(int x, int y)
1917 {
1918   int ux = LEVELX(x), uy = LEVELY(y);
1919   int element, content;
1920
1921   if (!IN_LEV_FIELD(ux, uy))
1922   {
1923     if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1924       element = EL_LEERRAUM;
1925     else
1926       element = BorderElement;
1927
1928     DrawNewScreenElement(x, y, element);
1929     return;
1930   }
1931
1932   element = Feld[ux][uy];
1933   content = Store[ux][uy];
1934
1935   if (IS_MOVING(ux, uy))
1936   {
1937     int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1938     boolean cut_mode = NO_CUTTING;
1939
1940     if (element == EL_QUICKSAND_EMPTYING ||
1941         element == EL_MAGIC_WALL_EMPTYING ||
1942         element == EL_MAGIC_WALL_BD_EMPTYING ||
1943         element == EL_AMOEBA_DRIPPING)
1944       cut_mode = CUT_ABOVE;
1945     else if (element == EL_QUICKSAND_FILLING ||
1946              element == EL_MAGIC_WALL_FILLING ||
1947              element == EL_MAGIC_WALL_BD_FILLING)
1948       cut_mode = CUT_BELOW;
1949
1950     if (cut_mode == CUT_ABOVE)
1951       DrawNewScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1952     else
1953       DrawNewScreenElement(x, y, EL_LEERRAUM);
1954
1955     if (horiz_move)
1956       DrawNewScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1957     else if (cut_mode == NO_CUTTING)
1958       DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1959     else
1960       DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1961
1962     if (content == EL_SALZSAEURE)
1963       DrawNewLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1964   }
1965   else if (IS_BLOCKED(ux, uy))
1966   {
1967     int oldx, oldy;
1968     int sx, sy;
1969     int horiz_move;
1970     boolean cut_mode = NO_CUTTING;
1971     int element_old, content_old;
1972
1973     Blocked2Moving(ux, uy, &oldx, &oldy);
1974     sx = SCREENX(oldx);
1975     sy = SCREENY(oldy);
1976     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1977                   MovDir[oldx][oldy] == MV_RIGHT);
1978
1979     element_old = Feld[oldx][oldy];
1980     content_old = Store[oldx][oldy];
1981
1982     if (element_old == EL_QUICKSAND_EMPTYING ||
1983         element_old == EL_MAGIC_WALL_EMPTYING ||
1984         element_old == EL_MAGIC_WALL_BD_EMPTYING ||
1985         element_old == EL_AMOEBA_DRIPPING)
1986       cut_mode = CUT_ABOVE;
1987
1988     DrawNewScreenElement(x, y, EL_LEERRAUM);
1989
1990     if (horiz_move)
1991       DrawNewScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1992                                NO_CUTTING);
1993     else if (cut_mode == NO_CUTTING)
1994       DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1995                                cut_mode);
1996     else
1997       DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1998                                cut_mode);
1999   }
2000   else if (IS_DRAWABLE(element))
2001     DrawNewScreenElement(x, y, element);
2002   else
2003     DrawNewScreenElement(x, y, EL_LEERRAUM);
2004 }
2005
2006 void DrawLevelField(int x, int y)
2007 {
2008   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2009     DrawScreenField(SCREENX(x), SCREENY(y));
2010   else if (IS_MOVING(x, y))
2011   {
2012     int newx,newy;
2013
2014     Moving2Blocked(x, y, &newx, &newy);
2015     if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2016       DrawScreenField(SCREENX(newx), SCREENY(newy));
2017   }
2018   else if (IS_BLOCKED(x, y))
2019   {
2020     int oldx, oldy;
2021
2022     Blocked2Moving(x, y, &oldx, &oldy);
2023     if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2024       DrawScreenField(SCREENX(oldx), SCREENY(oldy));
2025   }
2026 }
2027
2028 void DrawNewLevelField(int x, int y)
2029 {
2030   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2031     DrawNewScreenField(SCREENX(x), SCREENY(y));
2032   else if (IS_MOVING(x, y))
2033   {
2034     int newx,newy;
2035
2036     Moving2Blocked(x, y, &newx, &newy);
2037     if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2038       DrawNewScreenField(SCREENX(newx), SCREENY(newy));
2039   }
2040   else if (IS_BLOCKED(x, y))
2041   {
2042     int oldx, oldy;
2043
2044     Blocked2Moving(x, y, &oldx, &oldy);
2045     if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2046       DrawNewScreenField(SCREENX(oldx), SCREENY(oldy));
2047   }
2048 }
2049
2050 void DrawMiniElement(int x, int y, int element)
2051 {
2052   int graphic;
2053
2054   if (!element)
2055   {
2056     DrawMiniGraphic(x, y, -1);
2057     return;
2058   }
2059
2060   graphic = el2gfx(element);
2061   DrawMiniGraphic(x, y, graphic);
2062 }
2063
2064 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2065 {
2066   int x = sx + scroll_x, y = sy + scroll_y;
2067
2068   if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2069     DrawMiniElement(sx, sy, EL_LEERRAUM);
2070   else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2071     DrawMiniElement(sx, sy, Feld[x][y]);
2072   else
2073   {
2074     int steel_type, steel_position;
2075     int border[6][2] =
2076     {
2077       { GFX_VSTEEL_UPPER_LEFT,  GFX_ISTEEL_UPPER_LEFT  },
2078       { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
2079       { GFX_VSTEEL_LOWER_LEFT,  GFX_ISTEEL_LOWER_LEFT  },
2080       { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
2081       { GFX_VSTEEL_VERTICAL,    GFX_ISTEEL_VERTICAL    },
2082       { GFX_VSTEEL_HORIZONTAL,  GFX_ISTEEL_HORIZONTAL  }
2083     };
2084
2085     steel_type = (BorderElement == EL_BETON ? 0 : 1);
2086     steel_position = (x == -1 && y == -1                        ? 0 :
2087                       x == lev_fieldx && y == -1                ? 1 :
2088                       x == -1 && y == lev_fieldy                ? 2 :
2089                       x == lev_fieldx && y == lev_fieldy        ? 3 :
2090                       x == -1 || x == lev_fieldx                ? 4 :
2091                       y == -1 || y == lev_fieldy                ? 5 : -1);
2092
2093     if (steel_position != -1)
2094       DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
2095   }
2096 }
2097
2098 void DrawMicroElement(int xpos, int ypos, int element)
2099 {
2100   int graphic;
2101
2102   if (element == EL_LEERRAUM)
2103     return;
2104
2105   graphic = el2gfx(element);
2106
2107   if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
2108   {
2109     graphic -= GFX_START_ROCKSSP;
2110     BlitBitmap(pix[PIX_SP], drawto,
2111                MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
2112                MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
2113                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2114   }
2115   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
2116   {
2117     graphic -= GFX_START_ROCKSDC;
2118     BlitBitmap(pix[PIX_DC], drawto,
2119                MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
2120                MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
2121                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2122   }
2123   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
2124   {
2125     graphic -= GFX_START_ROCKSMORE;
2126     BlitBitmap(pix[PIX_MORE], drawto,
2127                MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE)*MICRO_TILEX,
2128                MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE)*MICRO_TILEY,
2129                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2130   }
2131   else if (graphic >= GFX_CHAR_START && graphic <= GFX_CHAR_END)
2132   {
2133     graphic -= GFX_CHAR_START;
2134     BlitBitmap(pix[PIX_FONT_EM], drawto,
2135                MICRO_FONT_STARTX + (graphic % MICRO_GFX_PER_LINE)* MICRO_TILEX,
2136                MICRO_FONT_STARTY + (graphic / MICRO_GFX_PER_LINE)* MICRO_TILEY,
2137                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2138   }
2139   else
2140     BlitBitmap(pix[PIX_ELEMENTS], drawto,
2141                MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
2142                MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
2143                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2144 }
2145
2146 void DrawLevel()
2147 {
2148   int x,y;
2149
2150   ClearWindow();
2151
2152   for(x=BX1; x<=BX2; x++)
2153     for(y=BY1; y<=BY2; y++)
2154       DrawScreenField(x, y);
2155
2156   redraw_mask |= REDRAW_FIELD;
2157 }
2158
2159 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2160 {
2161   int x,y;
2162
2163   for(x=0; x<size_x; x++)
2164     for(y=0; y<size_y; y++)
2165       DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
2166
2167   redraw_mask |= REDRAW_FIELD;
2168 }
2169
2170 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
2171 {
2172   int x, y;
2173
2174   ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
2175
2176   if (lev_fieldx < STD_LEV_FIELDX)
2177     xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
2178   if (lev_fieldy < STD_LEV_FIELDY)
2179     ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
2180
2181   xpos += MICRO_TILEX;
2182   ypos += MICRO_TILEY;
2183
2184   for(x=-1; x<=STD_LEV_FIELDX; x++)
2185   {
2186     for(y=-1; y<=STD_LEV_FIELDY; y++)
2187     {
2188       int lx = from_x + x, ly = from_y + y;
2189
2190       if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
2191         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2192                          Ur[lx][ly]);
2193       else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
2194         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2195                          BorderElement);
2196     }
2197   }
2198
2199   redraw_mask |= REDRAW_MICROLEVEL;
2200 }
2201
2202 #define MICROLABEL_EMPTY                0
2203 #define MICROLABEL_LEVEL_NAME           1
2204 #define MICROLABEL_CREATED_BY           2
2205 #define MICROLABEL_LEVEL_AUTHOR         3
2206 #define MICROLABEL_IMPORTED_FROM        4
2207 #define MICROLABEL_LEVEL_IMPORT_INFO    5
2208
2209 #define MAX_MICROLABEL_SIZE             (SXSIZE / FONT4_XSIZE)
2210
2211 static void DrawMicroLevelLabelExt(int mode)
2212 {
2213   char label_text[MAX_MICROLABEL_SIZE + 1];
2214
2215   ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
2216
2217   strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
2218                        mode == MICROLABEL_CREATED_BY ? "created by" :
2219                        mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
2220                        mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
2221                        mode == MICROLABEL_LEVEL_IMPORT_INFO ?
2222                        leveldir_current->imported_from : ""),
2223           MAX_MICROLABEL_SIZE);
2224   label_text[MAX_MICROLABEL_SIZE] = '\0';
2225
2226   if (strlen(label_text) > 0)
2227   {
2228     int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
2229     int lypos = MICROLABEL_YPOS;
2230
2231     DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
2232   }
2233
2234   redraw_mask |= REDRAW_MICROLEVEL;
2235 }
2236
2237 void DrawMicroLevel(int xpos, int ypos, boolean restart)
2238 {
2239   static unsigned long scroll_delay = 0;
2240   static unsigned long label_delay = 0;
2241   static int from_x, from_y, scroll_direction;
2242   static int label_state, label_counter;
2243
2244   if (restart)
2245   {
2246     from_x = from_y = 0;
2247     scroll_direction = MV_RIGHT;
2248     label_state = 1;
2249     label_counter = 0;
2250
2251     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2252     DrawMicroLevelLabelExt(label_state);
2253
2254     /* initialize delay counters */
2255     DelayReached(&scroll_delay, 0);
2256     DelayReached(&label_delay, 0);
2257
2258     return;
2259   }
2260
2261   /* scroll micro level, if needed */
2262   if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
2263       DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
2264   {
2265     switch (scroll_direction)
2266     {
2267       case MV_LEFT:
2268         if (from_x > 0)
2269           from_x--;
2270         else
2271           scroll_direction = MV_UP;
2272         break;
2273
2274       case MV_RIGHT:
2275         if (from_x < lev_fieldx - STD_LEV_FIELDX)
2276           from_x++;
2277         else
2278           scroll_direction = MV_DOWN;
2279         break;
2280
2281       case MV_UP:
2282         if (from_y > 0)
2283           from_y--;
2284         else
2285           scroll_direction = MV_RIGHT;
2286         break;
2287
2288       case MV_DOWN:
2289         if (from_y < lev_fieldy - STD_LEV_FIELDY)
2290           from_y++;
2291         else
2292           scroll_direction = MV_LEFT;
2293         break;
2294
2295       default:
2296         break;
2297     }
2298
2299     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2300   }
2301
2302   /* redraw micro level label, if needed */
2303   if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
2304       strcmp(level.author, ANONYMOUS_NAME) != 0 &&
2305       strcmp(level.author, leveldir_current->name) != 0 &&
2306       DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
2307   {
2308     int max_label_counter = 23;
2309
2310     if (leveldir_current->imported_from != NULL)
2311       max_label_counter += 14;
2312
2313     label_counter = (label_counter + 1) % max_label_counter;
2314     label_state = (label_counter >= 0 && label_counter <= 7 ?
2315                    MICROLABEL_LEVEL_NAME :
2316                    label_counter >= 9 && label_counter <= 12 ?
2317                    MICROLABEL_CREATED_BY :
2318                    label_counter >= 14 && label_counter <= 21 ?
2319                    MICROLABEL_LEVEL_AUTHOR :
2320                    label_counter >= 23 && label_counter <= 26 ?
2321                    MICROLABEL_IMPORTED_FROM :
2322                    label_counter >= 28 && label_counter <= 35 ?
2323                    MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2324     DrawMicroLevelLabelExt(label_state);
2325   }
2326 }
2327
2328 int REQ_in_range(int x, int y)
2329 {
2330   if (y > DY+249 && y < DY+278)
2331   {
2332     if (x > DX+1 && x < DX+48)
2333       return 1;
2334     else if (x > DX+51 && x < DX+98) 
2335       return 2;
2336   }
2337   return 0;
2338 }
2339
2340 #define MAX_REQUEST_LINES               13
2341 #define MAX_REQUEST_LINE_LEN            7
2342
2343 boolean Request(char *text, unsigned int req_state)
2344 {
2345   int mx, my, ty, result = -1;
2346   unsigned int old_door_state;
2347
2348 #if defined(PLATFORM_UNIX)
2349   /* pause network game while waiting for request to answer */
2350   if (options.network &&
2351       game_status == PLAYING &&
2352       req_state & REQUEST_WAIT_FOR)
2353     SendToServer_PausePlaying();
2354 #endif
2355
2356   old_door_state = GetDoorState();
2357
2358   UnmapAllGadgets();
2359
2360   CloseDoor(DOOR_CLOSE_1);
2361
2362   /* save old door content */
2363   BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2364              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2365              DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2366
2367   /* clear door drawing field */
2368   ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
2369
2370   /* write text for request */
2371   for(ty=0; ty < MAX_REQUEST_LINES; ty++)
2372   {
2373     char text_line[MAX_REQUEST_LINE_LEN + 1];
2374     int tx, tl, tc;
2375
2376     if (!*text)
2377       break;
2378
2379     for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
2380     {
2381       tc = *(text + tx);
2382       if (!tc || tc == ' ')
2383         break;
2384     }
2385
2386     if (!tl)
2387     { 
2388       text++; 
2389       ty--; 
2390       continue; 
2391     }
2392
2393     strncpy(text_line, text, tl);
2394     text_line[tl] = 0;
2395
2396     DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2397                 text_line, FS_SMALL, FC_YELLOW);
2398
2399     text += tl + (tc == ' ' ? 1 : 0);
2400   }
2401
2402   if (req_state & REQ_ASK)
2403   {
2404     MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2405     MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2406   }
2407   else if (req_state & REQ_CONFIRM)
2408   {
2409     MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2410   }
2411   else if (req_state & REQ_PLAYER)
2412   {
2413     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2414     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2415     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2416     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2417   }
2418
2419   /* copy request gadgets to door backbuffer */
2420   BlitBitmap(drawto, pix[PIX_DB_DOOR],
2421              DX, DY, DXSIZE, DYSIZE,
2422              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2423
2424   OpenDoor(DOOR_OPEN_1);
2425
2426 #if 0
2427   ClearEventQueue();
2428 #endif
2429
2430   if (!(req_state & REQUEST_WAIT_FOR))
2431     return(FALSE);
2432
2433   if (game_status != MAINMENU)
2434     InitAnimation();
2435
2436   button_status = MB_RELEASED;
2437
2438   request_gadget_id = -1;
2439
2440   while(result < 0)
2441   {
2442     if (PendingEvent())
2443     {
2444       Event event;
2445
2446       NextEvent(&event);
2447
2448       switch(event.type)
2449       {
2450         case EVENT_BUTTONPRESS:
2451         case EVENT_BUTTONRELEASE:
2452         case EVENT_MOTIONNOTIFY:
2453         {
2454           if (event.type == EVENT_MOTIONNOTIFY)
2455           {
2456             if (!PointerInWindow(window))
2457               continue; /* window and pointer are on different screens */
2458
2459             if (!button_status)
2460               continue;
2461
2462             motion_status = TRUE;
2463             mx = ((MotionEvent *) &event)->x;
2464             my = ((MotionEvent *) &event)->y;
2465           }
2466           else
2467           {
2468             motion_status = FALSE;
2469             mx = ((ButtonEvent *) &event)->x;
2470             my = ((ButtonEvent *) &event)->y;
2471             if (event.type == EVENT_BUTTONPRESS)
2472               button_status = ((ButtonEvent *) &event)->button;
2473             else
2474               button_status = MB_RELEASED;
2475           }
2476
2477           /* this sets 'request_gadget_id' */
2478           HandleGadgets(mx, my, button_status);
2479
2480           switch(request_gadget_id)
2481           {
2482             case TOOL_CTRL_ID_YES:
2483               result = TRUE;
2484               break;
2485             case TOOL_CTRL_ID_NO:
2486               result = FALSE;
2487               break;
2488             case TOOL_CTRL_ID_CONFIRM:
2489               result = TRUE | FALSE;
2490               break;
2491
2492             case TOOL_CTRL_ID_PLAYER_1:
2493               result = 1;
2494               break;
2495             case TOOL_CTRL_ID_PLAYER_2:
2496               result = 2;
2497               break;
2498             case TOOL_CTRL_ID_PLAYER_3:
2499               result = 3;
2500               break;
2501             case TOOL_CTRL_ID_PLAYER_4:
2502               result = 4;
2503               break;
2504
2505             default:
2506               break;
2507           }
2508
2509           break;
2510         }
2511
2512         case EVENT_KEYPRESS:
2513           switch(GetEventKey((KeyEvent *)&event, TRUE))
2514           {
2515             case KSYM_Return:
2516               result = 1;
2517               break;
2518
2519             case KSYM_Escape:
2520               result = 0;
2521               break;
2522
2523             default:
2524               break;
2525           }
2526           if (req_state & REQ_PLAYER)
2527             result = 0;
2528           break;
2529
2530         case EVENT_KEYRELEASE:
2531           ClearPlayerAction();
2532           break;
2533
2534         default:
2535           HandleOtherEvents(&event);
2536           break;
2537       }
2538     }
2539     else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2540     {
2541       int joy = AnyJoystick();
2542
2543       if (joy & JOY_BUTTON_1)
2544         result = 1;
2545       else if (joy & JOY_BUTTON_2)
2546         result = 0;
2547     }
2548
2549     DoAnimation();
2550
2551     /* don't eat all CPU time */
2552     Delay(10);
2553   }
2554
2555   if (game_status != MAINMENU)
2556     StopAnimation();
2557
2558   UnmapToolButtons();
2559
2560   if (!(req_state & REQ_STAY_OPEN))
2561   {
2562     CloseDoor(DOOR_CLOSE_1);
2563
2564     if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2565     {
2566       BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2567                  DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2568                  DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2569       OpenDoor(DOOR_OPEN_1);
2570     }
2571   }
2572
2573   RemapAllGadgets();
2574
2575 #if defined(PLATFORM_UNIX)
2576   /* continue network game after request */
2577   if (options.network &&
2578       game_status == PLAYING &&
2579       req_state & REQUEST_WAIT_FOR)
2580     SendToServer_ContinuePlaying();
2581 #endif
2582
2583   return(result);
2584 }
2585
2586 unsigned int OpenDoor(unsigned int door_state)
2587 {
2588   unsigned int new_door_state;
2589
2590   if (door_state & DOOR_COPY_BACK)
2591   {
2592     BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2593                DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2594                DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2595     door_state &= ~DOOR_COPY_BACK;
2596   }
2597
2598   new_door_state = MoveDoor(door_state);
2599
2600   return(new_door_state);
2601 }
2602
2603 unsigned int CloseDoor(unsigned int door_state)
2604 {
2605   unsigned int new_door_state;
2606
2607   BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2608              DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2609   BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2610              VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2611
2612   new_door_state = MoveDoor(door_state);
2613
2614   return(new_door_state);
2615 }
2616
2617 unsigned int GetDoorState()
2618 {
2619   return MoveDoor(DOOR_GET_STATE);
2620 }
2621
2622 unsigned int SetDoorState(unsigned int door_state)
2623 {
2624   return MoveDoor(door_state | DOOR_SET_STATE);
2625 }
2626
2627 unsigned int MoveDoor(unsigned int door_state)
2628 {
2629   static int door1 = DOOR_OPEN_1;
2630   static int door2 = DOOR_CLOSE_2;
2631   static unsigned long door_delay = 0;
2632   int x, start, stepsize = 2;
2633   unsigned long door_delay_value = stepsize * 5;
2634
2635   if (door_state == DOOR_GET_STATE)
2636     return(door1 | door2);
2637
2638   if (door_state & DOOR_SET_STATE)
2639   {
2640     if (door_state & DOOR_ACTION_1)
2641       door1 = door_state & DOOR_ACTION_1;
2642     if (door_state & DOOR_ACTION_2)
2643       door2 = door_state & DOOR_ACTION_2;
2644
2645     return(door1 | door2);
2646   }
2647
2648   if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2649     door_state &= ~DOOR_OPEN_1;
2650   else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2651     door_state &= ~DOOR_CLOSE_1;
2652   if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2653     door_state &= ~DOOR_OPEN_2;
2654   else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2655     door_state &= ~DOOR_CLOSE_2;
2656
2657   if (setup.quick_doors)
2658   {
2659     stepsize = 20;
2660     door_delay_value = 0;
2661     StopSound(SND_MENU_DOOR_OPENING);
2662     StopSound(SND_MENU_DOOR_CLOSING);
2663   }
2664
2665   if (door_state & DOOR_ACTION)
2666   {
2667     if (!(door_state & DOOR_NO_DELAY))
2668     {
2669       /* opening door sound has priority over simultaneously closing door */
2670       if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2671         PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2672       else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2673         PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2674     }
2675
2676     start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2677
2678     for(x=start; x<=DXSIZE; x+=stepsize)
2679     {
2680       Bitmap *bitmap = pix[PIX_DOOR];
2681       GC gc = bitmap->stored_clip_gc;
2682
2683       WaitUntilDelayReached(&door_delay, door_delay_value);
2684
2685       if (door_state & DOOR_ACTION_1)
2686       {
2687         int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2688         int j = (DXSIZE - i) / 3;
2689
2690         BlitBitmap(pix[PIX_DB_DOOR], drawto,
2691                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2692                    DXSIZE,DYSIZE - i/2, DX, DY);
2693
2694         ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2695
2696         SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2697         BlitBitmapMasked(bitmap, drawto,
2698                          DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2699                          DX + DXSIZE - i, DY + j);
2700         BlitBitmapMasked(bitmap, drawto,
2701                          DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2702                          DX + DXSIZE - i, DY + 140 + j);
2703         SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2704         BlitBitmapMasked(bitmap, drawto,
2705                          DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2706                          DX, DY);
2707         BlitBitmapMasked(bitmap, drawto,
2708                          DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2709                          DX, DY + 140 - j);
2710
2711         BlitBitmapMasked(bitmap, drawto,
2712                          DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2713                          DX, DY + 77 - j);
2714         BlitBitmapMasked(bitmap, drawto,
2715                          DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2716                          DX, DY + 203 - j);
2717         SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2718         BlitBitmapMasked(bitmap, drawto,
2719                          DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2720                          DX + DXSIZE - i, DY + 77 + j);
2721         BlitBitmapMasked(bitmap, drawto,
2722                          DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2723                          DX + DXSIZE - i, DY + 203 + j);
2724
2725         redraw_mask |= REDRAW_DOOR_1;
2726       }
2727
2728       if (door_state & DOOR_ACTION_2)
2729       {
2730         int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2731         int j = (VXSIZE - i) / 3;
2732
2733         BlitBitmap(pix[PIX_DB_DOOR], drawto,
2734                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2735                    VXSIZE, VYSIZE - i/2, VX, VY);
2736
2737         ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2738
2739         SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2740         BlitBitmapMasked(bitmap, drawto,
2741                          VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2742                          VX + VXSIZE-i, VY+j);
2743         SetClipOrigin(bitmap, gc,
2744                       VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2745         BlitBitmapMasked(bitmap, drawto,
2746                          VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2747                          VX, VY);
2748
2749         BlitBitmapMasked(bitmap, drawto,
2750                          VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2751                          i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2752         SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2753         BlitBitmapMasked(bitmap, drawto,
2754                          VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2755                          i, VYSIZE / 2 - j,
2756                          VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2757
2758         redraw_mask |= REDRAW_DOOR_2;
2759       }
2760
2761       BackToFront();
2762
2763       if (game_status == MAINMENU)
2764         DoAnimation();
2765     }
2766   }
2767
2768   if (setup.quick_doors)
2769   {
2770     StopSound(SND_MENU_DOOR_OPENING);
2771     StopSound(SND_MENU_DOOR_CLOSING);
2772   }
2773
2774   if (door_state & DOOR_ACTION_1)
2775     door1 = door_state & DOOR_ACTION_1;
2776   if (door_state & DOOR_ACTION_2)
2777     door2 = door_state & DOOR_ACTION_2;
2778
2779   return (door1 | door2);
2780 }
2781
2782 void DrawSpecialEditorDoor()
2783 {
2784   /* draw bigger toolbox window */
2785   BlitBitmap(pix[PIX_DOOR], drawto,
2786              DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2787
2788   redraw_mask |= REDRAW_ALL;
2789 }
2790
2791 void UndrawSpecialEditorDoor()
2792 {
2793   /* draw normal tape recorder window */
2794   BlitBitmap(pix[PIX_BACK], drawto,
2795              562, 344, 108, 56, EX - 4, EY - 12);
2796
2797   redraw_mask |= REDRAW_ALL;
2798 }
2799
2800 #ifndef TARGET_SDL
2801 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2802 {
2803   XImage *pixel_image;
2804   unsigned long pixel_value;
2805
2806   pixel_image = XGetImage(display, bitmap->drawable,
2807                           x, y, 1, 1, AllPlanes, ZPixmap);
2808   pixel_value = XGetPixel(pixel_image, 0, 0);
2809
2810   XDestroyImage(pixel_image);
2811
2812   return pixel_value;
2813 }
2814 #endif
2815
2816 /* ---------- new tool button stuff ---------------------------------------- */
2817
2818 /* graphic position values for tool buttons */
2819 #define TOOL_BUTTON_YES_XPOS            2
2820 #define TOOL_BUTTON_YES_YPOS            250
2821 #define TOOL_BUTTON_YES_GFX_YPOS        0
2822 #define TOOL_BUTTON_YES_XSIZE           46
2823 #define TOOL_BUTTON_YES_YSIZE           28
2824 #define TOOL_BUTTON_NO_XPOS             52
2825 #define TOOL_BUTTON_NO_YPOS             TOOL_BUTTON_YES_YPOS
2826 #define TOOL_BUTTON_NO_GFX_YPOS         TOOL_BUTTON_YES_GFX_YPOS
2827 #define TOOL_BUTTON_NO_XSIZE            TOOL_BUTTON_YES_XSIZE
2828 #define TOOL_BUTTON_NO_YSIZE            TOOL_BUTTON_YES_YSIZE
2829 #define TOOL_BUTTON_CONFIRM_XPOS        TOOL_BUTTON_YES_XPOS
2830 #define TOOL_BUTTON_CONFIRM_YPOS        TOOL_BUTTON_YES_YPOS
2831 #define TOOL_BUTTON_CONFIRM_GFX_YPOS    30
2832 #define TOOL_BUTTON_CONFIRM_XSIZE       96
2833 #define TOOL_BUTTON_CONFIRM_YSIZE       TOOL_BUTTON_YES_YSIZE
2834 #define TOOL_BUTTON_PLAYER_XSIZE        30
2835 #define TOOL_BUTTON_PLAYER_YSIZE        30
2836 #define TOOL_BUTTON_PLAYER_GFX_XPOS     5
2837 #define TOOL_BUTTON_PLAYER_GFX_YPOS     185
2838 #define TOOL_BUTTON_PLAYER_XPOS         (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2839 #define TOOL_BUTTON_PLAYER_YPOS         (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2840 #define TOOL_BUTTON_PLAYER1_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2841                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2842 #define TOOL_BUTTON_PLAYER2_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2843                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2844 #define TOOL_BUTTON_PLAYER3_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2845                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2846 #define TOOL_BUTTON_PLAYER4_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2847                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2848 #define TOOL_BUTTON_PLAYER1_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2849                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2850 #define TOOL_BUTTON_PLAYER2_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2851                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2852 #define TOOL_BUTTON_PLAYER3_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2853                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2854 #define TOOL_BUTTON_PLAYER4_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2855                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2856
2857 static struct
2858 {
2859   int xpos, ypos;
2860   int x, y;
2861   int width, height;
2862   int gadget_id;
2863   char *infotext;
2864 } toolbutton_info[NUM_TOOL_BUTTONS] =
2865 {
2866   {
2867     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_GFX_YPOS,
2868     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_YPOS,
2869     TOOL_BUTTON_YES_XSIZE,      TOOL_BUTTON_YES_YSIZE,
2870     TOOL_CTRL_ID_YES,
2871     "yes"
2872   },
2873   {
2874     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_GFX_YPOS,
2875     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_YPOS,
2876     TOOL_BUTTON_NO_XSIZE,       TOOL_BUTTON_NO_YSIZE,
2877     TOOL_CTRL_ID_NO,
2878     "no"
2879   },
2880   {
2881     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_GFX_YPOS,
2882     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_YPOS,
2883     TOOL_BUTTON_CONFIRM_XSIZE,  TOOL_BUTTON_CONFIRM_YSIZE,
2884     TOOL_CTRL_ID_CONFIRM,
2885     "confirm"
2886   },
2887   {
2888     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2889     TOOL_BUTTON_PLAYER1_XPOS,   TOOL_BUTTON_PLAYER1_YPOS,
2890     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2891     TOOL_CTRL_ID_PLAYER_1,
2892     "player 1"
2893   },
2894   {
2895     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2896     TOOL_BUTTON_PLAYER2_XPOS,   TOOL_BUTTON_PLAYER2_YPOS,
2897     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2898     TOOL_CTRL_ID_PLAYER_2,
2899     "player 2"
2900   },
2901   {
2902     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2903     TOOL_BUTTON_PLAYER3_XPOS,   TOOL_BUTTON_PLAYER3_YPOS,
2904     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2905     TOOL_CTRL_ID_PLAYER_3,
2906     "player 3"
2907   },
2908   {
2909     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2910     TOOL_BUTTON_PLAYER4_XPOS,   TOOL_BUTTON_PLAYER4_YPOS,
2911     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2912     TOOL_CTRL_ID_PLAYER_4,
2913     "player 4"
2914   }
2915 };
2916
2917 void CreateToolButtons()
2918 {
2919   int i;
2920
2921   for (i=0; i<NUM_TOOL_BUTTONS; i++)
2922   {
2923     Bitmap *gd_bitmap = pix[PIX_DOOR];
2924     Bitmap *deco_bitmap = None;
2925     int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2926     struct GadgetInfo *gi;
2927     unsigned long event_mask;
2928     int gd_xoffset, gd_yoffset;
2929     int gd_x1, gd_x2, gd_y;
2930     int id = i;
2931
2932     event_mask = GD_EVENT_RELEASED;
2933
2934     gd_xoffset = toolbutton_info[i].xpos;
2935     gd_yoffset = toolbutton_info[i].ypos;
2936     gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2937     gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2938     gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2939
2940     if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2941     {
2942       getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2943                            &deco_bitmap, &deco_x, &deco_y);
2944       deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2945       deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2946     }
2947
2948     gi = CreateGadget(GDI_CUSTOM_ID, id,
2949                       GDI_INFO_TEXT, toolbutton_info[i].infotext,
2950                       GDI_X, DX + toolbutton_info[i].x,
2951                       GDI_Y, DY + toolbutton_info[i].y,
2952                       GDI_WIDTH, toolbutton_info[i].width,
2953                       GDI_HEIGHT, toolbutton_info[i].height,
2954                       GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2955                       GDI_STATE, GD_BUTTON_UNPRESSED,
2956                       GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2957                       GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2958                       GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2959                       GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2960                       GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2961                       GDI_DECORATION_SHIFTING, 1, 1,
2962                       GDI_EVENT_MASK, event_mask,
2963                       GDI_CALLBACK_ACTION, HandleToolButtons,
2964                       GDI_END);
2965
2966     if (gi == NULL)
2967       Error(ERR_EXIT, "cannot create gadget");
2968
2969     tool_gadget[id] = gi;
2970   }
2971 }
2972
2973 static void UnmapToolButtons()
2974 {
2975   int i;
2976
2977   for (i=0; i<NUM_TOOL_BUTTONS; i++)
2978     UnmapGadget(tool_gadget[i]);
2979 }
2980
2981 static void HandleToolButtons(struct GadgetInfo *gi)
2982 {
2983   request_gadget_id = gi->custom_id;
2984 }
2985
2986 int get_next_element(int element)
2987 {
2988   switch(element)
2989   {
2990     case EL_QUICKSAND_FILLING:          return EL_MORAST_VOLL;
2991     case EL_QUICKSAND_EMPTYING:         return EL_MORAST_LEER;
2992     case EL_MAGIC_WALL_FILLING:         return EL_MAGIC_WALL_FULL;
2993     case EL_MAGIC_WALL_EMPTYING:        return EL_MAGIC_WALL_EMPTY;
2994     case EL_MAGIC_WALL_BD_FILLING:      return EL_MAGIC_WALL_BD_FULL;
2995     case EL_MAGIC_WALL_BD_EMPTYING:     return EL_MAGIC_WALL_BD_EMPTY;
2996     case EL_AMOEBA_DRIPPING:            return EL_AMOEBE_NASS;
2997
2998     default:                            return element;
2999   }
3000 }
3001
3002 int el2gfx_OLD(int element)
3003 {
3004   switch(element)
3005   {
3006     case EL_LEERRAUM:           return -1;
3007     case EL_ERDREICH:           return GFX_ERDREICH;
3008     case EL_MAUERWERK:          return GFX_MAUERWERK;
3009     case EL_FELSBODEN:          return GFX_FELSBODEN;
3010     case EL_FELSBROCKEN:        return GFX_FELSBROCKEN;
3011     case EL_SCHLUESSEL:         return GFX_SCHLUESSEL;
3012     case EL_EDELSTEIN:          return GFX_EDELSTEIN;
3013     case EL_AUSGANG_ZU:         return GFX_AUSGANG_ZU;
3014     case EL_AUSGANG_ACT:        return GFX_AUSGANG_ACT;
3015     case EL_AUSGANG_AUF:        return GFX_AUSGANG_AUF;
3016     case EL_SPIELFIGUR:         return GFX_SPIELFIGUR;
3017     case EL_SPIELER1:           return GFX_SPIELER1;
3018     case EL_SPIELER2:           return GFX_SPIELER2;
3019     case EL_SPIELER3:           return GFX_SPIELER3;
3020     case EL_SPIELER4:           return GFX_SPIELER4;
3021     case EL_KAEFER:             return GFX_KAEFER;
3022     case EL_KAEFER_RIGHT:       return GFX_KAEFER_RIGHT;
3023     case EL_KAEFER_UP:          return GFX_KAEFER_UP;
3024     case EL_KAEFER_LEFT:        return GFX_KAEFER_LEFT;
3025     case EL_KAEFER_DOWN:        return GFX_KAEFER_DOWN;
3026     case EL_FLIEGER:            return GFX_FLIEGER;
3027     case EL_FLIEGER_RIGHT:      return GFX_FLIEGER_RIGHT;
3028     case EL_FLIEGER_UP:         return GFX_FLIEGER_UP;
3029     case EL_FLIEGER_LEFT:       return GFX_FLIEGER_LEFT;
3030     case EL_FLIEGER_DOWN:       return GFX_FLIEGER_DOWN;
3031     case EL_BUTTERFLY:          return GFX_BUTTERFLY;
3032     case EL_BUTTERFLY_RIGHT:    return GFX_BUTTERFLY_RIGHT;
3033     case EL_BUTTERFLY_UP:       return GFX_BUTTERFLY_UP;
3034     case EL_BUTTERFLY_LEFT:     return GFX_BUTTERFLY_LEFT;
3035     case EL_BUTTERFLY_DOWN:     return GFX_BUTTERFLY_DOWN;
3036     case EL_FIREFLY:            return GFX_FIREFLY;
3037     case EL_FIREFLY_RIGHT:      return GFX_FIREFLY_RIGHT;
3038     case EL_FIREFLY_UP:         return GFX_FIREFLY_UP;
3039     case EL_FIREFLY_LEFT:       return GFX_FIREFLY_LEFT;
3040     case EL_FIREFLY_DOWN:       return GFX_FIREFLY_DOWN;
3041     case EL_MAMPFER:            return GFX_MAMPFER;
3042     case EL_ROBOT:              return GFX_ROBOT;
3043     case EL_BETON:              return GFX_BETON;
3044     case EL_DIAMANT:            return GFX_DIAMANT;
3045     case EL_MORAST_LEER:        return GFX_MORAST_LEER;
3046     case EL_MORAST_VOLL:        return GFX_MORAST_VOLL;
3047     case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
3048     case EL_TROPFEN:            return GFX_TROPFEN;
3049     case EL_BOMBE:              return GFX_BOMBE;
3050     case EL_MAGIC_WALL_OFF:     return GFX_MAGIC_WALL_OFF;
3051     case EL_MAGIC_WALL_EMPTY:   return GFX_MAGIC_WALL_EMPTY;
3052     case EL_MAGIC_WALL_EMPTYING:return GFX_MAGIC_WALL_EMPTY;
3053     case EL_MAGIC_WALL_FULL:    return GFX_MAGIC_WALL_FULL;
3054     case EL_MAGIC_WALL_DEAD:    return GFX_MAGIC_WALL_DEAD;
3055     case EL_SALZSAEURE:         return GFX_SALZSAEURE;
3056     case EL_AMOEBE_TOT:         return GFX_AMOEBE_TOT;
3057     case EL_AMOEBE_NASS:        return GFX_AMOEBE_NASS;
3058     case EL_AMOEBE_NORM:        return GFX_AMOEBE_NORM;
3059     case EL_AMOEBE_VOLL:        return GFX_AMOEBE_VOLL;
3060     case EL_AMOEBE_BD:          return GFX_AMOEBE_BD;
3061     case EL_AMOEBA2DIAM:        return GFX_AMOEBA2DIAM;
3062     case EL_AMOEBA_DRIPPING:    return GFX_AMOEBE_NASS;
3063     case EL_KOKOSNUSS:          return GFX_KOKOSNUSS;
3064     case EL_LIFE:               return GFX_LIFE;
3065     case EL_LIFE_ASYNC:         return GFX_LIFE_ASYNC;
3066     case EL_DYNAMITE_ACTIVE:    return GFX_DYNAMIT;
3067     case EL_BADEWANNE:          return GFX_BADEWANNE;
3068     case EL_BADEWANNE1:         return GFX_BADEWANNE1;
3069     case EL_BADEWANNE2:         return GFX_BADEWANNE2;
3070     case EL_BADEWANNE3:         return GFX_BADEWANNE3;
3071     case EL_BADEWANNE4:         return GFX_BADEWANNE4;
3072     case EL_BADEWANNE5:         return GFX_BADEWANNE5;
3073     case EL_ABLENK_AUS:         return GFX_ABLENK_AUS;
3074     case EL_ABLENK_EIN:         return GFX_ABLENK_EIN;
3075     case EL_SCHLUESSEL1:        return GFX_SCHLUESSEL1;
3076     case EL_SCHLUESSEL2:        return GFX_SCHLUESSEL2;
3077     case EL_SCHLUESSEL3:        return GFX_SCHLUESSEL3;
3078     case EL_SCHLUESSEL4:        return GFX_SCHLUESSEL4;
3079     case EL_PFORTE1:            return GFX_PFORTE1;
3080     case EL_PFORTE2:            return GFX_PFORTE2;
3081     case EL_PFORTE3:            return GFX_PFORTE3;
3082     case EL_PFORTE4:            return GFX_PFORTE4;
3083     case EL_PFORTE1X:           return GFX_PFORTE1X;
3084     case EL_PFORTE2X:           return GFX_PFORTE2X;
3085     case EL_PFORTE3X:           return GFX_PFORTE3X;
3086     case EL_PFORTE4X:           return GFX_PFORTE4X;
3087     case EL_DYNAMITE_INACTIVE:  return GFX_DYNAMIT_AUS;
3088     case EL_PACMAN:             return GFX_PACMAN;
3089     case EL_PACMAN_RIGHT:       return GFX_PACMAN_RIGHT;
3090     case EL_PACMAN_UP:          return GFX_PACMAN_UP;
3091     case EL_PACMAN_LEFT:        return GFX_PACMAN_LEFT;
3092     case EL_PACMAN_DOWN:        return GFX_PACMAN_DOWN;
3093     case EL_UNSICHTBAR:         return GFX_UNSICHTBAR;
3094     case EL_ERZ_EDEL:           return GFX_ERZ_EDEL;
3095     case EL_ERZ_DIAM:           return GFX_ERZ_DIAM;
3096     case EL_BIRNE_AUS:          return GFX_BIRNE_AUS;
3097     case EL_BIRNE_EIN:          return GFX_BIRNE_EIN;
3098     case EL_ZEIT_VOLL:          return GFX_ZEIT_VOLL;
3099     case EL_ZEIT_LEER:          return GFX_ZEIT_LEER;
3100     case EL_MAUER_LEBT:         return GFX_MAUER_LEBT;
3101     case EL_MAUER_X:            return GFX_MAUER_X;
3102     case EL_MAUER_Y:            return GFX_MAUER_Y;
3103     case EL_MAUER_XY:           return GFX_MAUER_XY;
3104     case EL_EDELSTEIN_BD:       return GFX_EDELSTEIN_BD;
3105     case EL_EDELSTEIN_GELB:     return GFX_EDELSTEIN_GELB;
3106     case EL_EDELSTEIN_ROT:      return GFX_EDELSTEIN_ROT;
3107     case EL_EDELSTEIN_LILA:     return GFX_EDELSTEIN_LILA;
3108     case EL_ERZ_EDEL_BD:        return GFX_ERZ_EDEL_BD;
3109     case EL_ERZ_EDEL_GELB:      return GFX_ERZ_EDEL_GELB;
3110     case EL_ERZ_EDEL_ROT:       return GFX_ERZ_EDEL_ROT;
3111     case EL_ERZ_EDEL_LILA:      return GFX_ERZ_EDEL_LILA;
3112     case EL_MAMPFER2:           return GFX_MAMPFER2;
3113     case EL_MAGIC_WALL_BD_OFF:  return GFX_MAGIC_WALL_BD_OFF;
3114     case EL_MAGIC_WALL_BD_EMPTY:return GFX_MAGIC_WALL_BD_EMPTY;
3115     case EL_MAGIC_WALL_BD_EMPTYING:return GFX_MAGIC_WALL_BD_EMPTY;
3116     case EL_MAGIC_WALL_BD_FULL: return GFX_MAGIC_WALL_BD_FULL;
3117     case EL_MAGIC_WALL_BD_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
3118     case EL_DYNABOMB_ACTIVE_1:  return GFX_DYNABOMB;
3119     case EL_DYNABOMB_ACTIVE_2:  return GFX_DYNABOMB;
3120     case EL_DYNABOMB_ACTIVE_3:  return GFX_DYNABOMB;
3121     case EL_DYNABOMB_ACTIVE_4:  return GFX_DYNABOMB;
3122     case EL_DYNABOMB_NR:        return GFX_DYNABOMB_NR;
3123     case EL_DYNABOMB_SZ:        return GFX_DYNABOMB_SZ;
3124     case EL_DYNABOMB_XL:        return GFX_DYNABOMB_XL;
3125     case EL_SOKOBAN_OBJEKT:     return GFX_SOKOBAN_OBJEKT;
3126     case EL_SOKOBAN_FELD_LEER:  return GFX_SOKOBAN_FELD_LEER;
3127     case EL_SOKOBAN_FELD_VOLL:  return GFX_SOKOBAN_FELD_VOLL;
3128     case EL_MOLE:               return GFX_MOLE;
3129     case EL_PINGUIN:            return GFX_PINGUIN;
3130     case EL_SCHWEIN:            return GFX_SCHWEIN;
3131     case EL_DRACHE:             return GFX_DRACHE;
3132     case EL_SONDE:              return GFX_SONDE;
3133     case EL_PFEIL_LEFT:         return GFX_PFEIL_LEFT;
3134     case EL_PFEIL_RIGHT:        return GFX_PFEIL_RIGHT;
3135     case EL_PFEIL_UP:           return GFX_PFEIL_UP;
3136     case EL_PFEIL_DOWN:         return GFX_PFEIL_DOWN;
3137     case EL_SPEED_PILL:         return GFX_SPEED_PILL;
3138     case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
3139     case EL_SP_BUG_ACTIVE:      return GFX_SP_BUG_ACTIVE;
3140     case EL_SP_ZONK:            return GFX_SP_ZONK;
3141       /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
3142     case EL_INVISIBLE_STEEL:    return GFX_INVISIBLE_STEEL;
3143     case EL_BLACK_ORB:          return GFX_BLACK_ORB;
3144     case EL_EM_GATE_1:          return GFX_EM_GATE_1;
3145     case EL_EM_GATE_2:          return GFX_EM_GATE_2;
3146     case EL_EM_GATE_3:          return GFX_EM_GATE_3;
3147     case EL_EM_GATE_4:          return GFX_EM_GATE_4;
3148     case EL_EM_GATE_1X:         return GFX_EM_GATE_1X;
3149     case EL_EM_GATE_2X:         return GFX_EM_GATE_2X;
3150     case EL_EM_GATE_3X:         return GFX_EM_GATE_3X;
3151     case EL_EM_GATE_4X:         return GFX_EM_GATE_4X;
3152     case EL_EM_KEY_1_FILE:      return GFX_EM_KEY_1;
3153     case EL_EM_KEY_2_FILE:      return GFX_EM_KEY_2;
3154     case EL_EM_KEY_3_FILE:      return GFX_EM_KEY_3;
3155     case EL_EM_KEY_4_FILE:      return GFX_EM_KEY_4;
3156     case EL_EM_KEY_1:           return GFX_EM_KEY_1;
3157     case EL_EM_KEY_2:           return GFX_EM_KEY_2;
3158     case EL_EM_KEY_3:           return GFX_EM_KEY_3;
3159     case EL_EM_KEY_4:           return GFX_EM_KEY_4;
3160     case EL_PEARL:              return GFX_PEARL;
3161     case EL_CRYSTAL:            return GFX_CRYSTAL;
3162     case EL_WALL_PEARL:         return GFX_WALL_PEARL;
3163     case EL_WALL_CRYSTAL:       return GFX_WALL_CRYSTAL;
3164     case EL_DOOR_WHITE:         return GFX_DOOR_WHITE;
3165     case EL_DOOR_WHITE_GRAY:    return GFX_DOOR_WHITE_GRAY;
3166     case EL_KEY_WHITE:          return GFX_KEY_WHITE;
3167     case EL_SHIELD_PASSIVE:     return GFX_SHIELD_PASSIVE;
3168     case EL_SHIELD_ACTIVE:      return GFX_SHIELD_ACTIVE;
3169     case EL_EXTRA_TIME:         return GFX_EXTRA_TIME;
3170     case EL_SWITCHGATE_OPEN:    return GFX_SWITCHGATE_OPEN;
3171     case EL_SWITCHGATE_CLOSED:  return GFX_SWITCHGATE_CLOSED;
3172     case EL_SWITCHGATE_SWITCH_1:return GFX_SWITCHGATE_SWITCH_1;
3173     case EL_SWITCHGATE_SWITCH_2:return GFX_SWITCHGATE_SWITCH_2;
3174     case EL_BELT1_LEFT:         return GFX_BELT1_LEFT;
3175     case EL_BELT1_MIDDLE:       return GFX_BELT1_MIDDLE;
3176     case EL_BELT1_RIGHT:        return GFX_BELT1_RIGHT;
3177     case EL_BELT1_SWITCH_LEFT:  return GFX_BELT1_SWITCH_LEFT;
3178     case EL_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
3179     case EL_BELT1_SWITCH_RIGHT: return GFX_BELT1_SWITCH_RIGHT;
3180     case EL_BELT2_LEFT:         return GFX_BELT2_LEFT;
3181     case EL_BELT2_MIDDLE:       return GFX_BELT2_MIDDLE;
3182     case EL_BELT2_RIGHT:        return GFX_BELT2_RIGHT;
3183     case EL_BELT2_SWITCH_LEFT:  return GFX_BELT2_SWITCH_LEFT;
3184     case EL_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
3185     case EL_BELT2_SWITCH_RIGHT: return GFX_BELT2_SWITCH_RIGHT;
3186     case EL_BELT3_LEFT:         return GFX_BELT3_LEFT;
3187     case EL_BELT3_MIDDLE:       return GFX_BELT3_MIDDLE;
3188     case EL_BELT3_RIGHT:        return GFX_BELT3_RIGHT;
3189     case EL_BELT3_SWITCH_LEFT:  return GFX_BELT3_SWITCH_LEFT;
3190     case EL_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
3191     case EL_BELT3_SWITCH_RIGHT: return GFX_BELT3_SWITCH_RIGHT;
3192     case EL_BELT4_LEFT:         return GFX_BELT4_LEFT;
3193     case EL_BELT4_MIDDLE:       return GFX_BELT4_MIDDLE;
3194     case EL_BELT4_RIGHT:        return GFX_BELT4_RIGHT;
3195     case EL_BELT4_SWITCH_LEFT:  return GFX_BELT4_SWITCH_LEFT;
3196     case EL_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
3197     case EL_BELT4_SWITCH_RIGHT: return GFX_BELT4_SWITCH_RIGHT;
3198     case EL_LANDMINE:           return GFX_LANDMINE;
3199     case EL_ENVELOPE:           return GFX_ENVELOPE;
3200     case EL_LIGHT_SWITCH_OFF:   return GFX_LIGHT_SWITCH_OFF;
3201     case EL_LIGHT_SWITCH_ON:    return GFX_LIGHT_SWITCH_ON;
3202     case EL_SIGN_EXCLAMATION:   return GFX_SIGN_EXCLAMATION;
3203     case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
3204     case EL_SIGN_STOP:          return GFX_SIGN_STOP;
3205     case EL_SIGN_WHEELCHAIR:    return GFX_SIGN_WHEELCHAIR;
3206     case EL_SIGN_PARKING:       return GFX_SIGN_PARKING;
3207     case EL_SIGN_ONEWAY:        return GFX_SIGN_ONEWAY;
3208     case EL_SIGN_HEART:         return GFX_SIGN_HEART;
3209     case EL_SIGN_TRIANGLE:      return GFX_SIGN_TRIANGLE;
3210     case EL_SIGN_ROUND:         return GFX_SIGN_ROUND;
3211     case EL_SIGN_EXIT:          return GFX_SIGN_EXIT;
3212     case EL_SIGN_YINYANG:       return GFX_SIGN_YINYANG;
3213     case EL_SIGN_OTHER:         return GFX_SIGN_OTHER;
3214     case EL_MOLE_LEFT:          return GFX_MOLE_LEFT;
3215     case EL_MOLE_RIGHT:         return GFX_MOLE_RIGHT;
3216     case EL_MOLE_UP:            return GFX_MOLE_UP;
3217     case EL_MOLE_DOWN:          return GFX_MOLE_DOWN;
3218     case EL_STEEL_SLANTED:      return GFX_STEEL_SLANTED;
3219     case EL_SAND_INVISIBLE:     return GFX_SAND_INVISIBLE;
3220     case EL_DX_UNKNOWN_15:      return GFX_DX_UNKNOWN_15;
3221     case EL_DX_UNKNOWN_42:      return GFX_DX_UNKNOWN_42;
3222     case EL_TIMEGATE_OPEN:      return GFX_TIMEGATE_OPEN;
3223     case EL_TIMEGATE_CLOSED:    return GFX_TIMEGATE_CLOSED;
3224     case EL_TIMEGATE_SWITCH_ON: return GFX_TIMEGATE_SWITCH;
3225     case EL_TIMEGATE_SWITCH_OFF:return GFX_TIMEGATE_SWITCH;
3226     case EL_BALLOON:            return GFX_BALLOON;
3227     case EL_BALLOON_SEND_LEFT:  return GFX_BALLOON_SEND_LEFT;
3228     case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
3229     case EL_BALLOON_SEND_UP:    return GFX_BALLOON_SEND_UP;
3230     case EL_BALLOON_SEND_DOWN:  return GFX_BALLOON_SEND_DOWN;
3231     case EL_BALLOON_SEND_ANY:   return GFX_BALLOON_SEND_ANY;
3232     case EL_EMC_STEEL_WALL_1:   return GFX_EMC_STEEL_WALL_1;
3233     case EL_EMC_STEEL_WALL_2:   return GFX_EMC_STEEL_WALL_2;
3234     case EL_EMC_STEEL_WALL_3:   return GFX_EMC_STEEL_WALL_3;
3235     case EL_EMC_STEEL_WALL_4:   return GFX_EMC_STEEL_WALL_4;
3236     case EL_EMC_WALL_1:         return GFX_EMC_WALL_1;
3237     case EL_EMC_WALL_2:         return GFX_EMC_WALL_2;
3238     case EL_EMC_WALL_3:         return GFX_EMC_WALL_3;
3239     case EL_EMC_WALL_4:         return GFX_EMC_WALL_4;
3240     case EL_EMC_WALL_5:         return GFX_EMC_WALL_5;
3241     case EL_EMC_WALL_6:         return GFX_EMC_WALL_6;
3242     case EL_EMC_WALL_7:         return GFX_EMC_WALL_7;
3243     case EL_EMC_WALL_8:         return GFX_EMC_WALL_8;
3244     case EL_TUBE_CROSS:         return GFX_TUBE_CROSS;
3245     case EL_TUBE_VERTICAL:      return GFX_TUBE_VERTICAL;
3246     case EL_TUBE_HORIZONTAL:    return GFX_TUBE_HORIZONTAL;
3247     case EL_TUBE_VERT_LEFT:     return GFX_TUBE_VERT_LEFT;
3248     case EL_TUBE_VERT_RIGHT:    return GFX_TUBE_VERT_RIGHT;
3249     case EL_TUBE_HORIZ_UP:      return GFX_TUBE_HORIZ_UP;
3250     case EL_TUBE_HORIZ_DOWN:    return GFX_TUBE_HORIZ_DOWN;
3251     case EL_TUBE_LEFT_UP:       return GFX_TUBE_LEFT_UP;
3252     case EL_TUBE_LEFT_DOWN:     return GFX_TUBE_LEFT_DOWN;
3253     case EL_TUBE_RIGHT_UP:      return GFX_TUBE_RIGHT_UP;
3254     case EL_TUBE_RIGHT_DOWN:    return GFX_TUBE_RIGHT_DOWN;
3255     case EL_SPRING:             return GFX_SPRING;
3256     case EL_SPRING_MOVING:      return GFX_SPRING;
3257     case EL_TRAP_INACTIVE:      return GFX_TRAP_INACTIVE;
3258     case EL_TRAP_ACTIVE:        return GFX_TRAP_ACTIVE;
3259     case EL_BD_WALL:            return GFX_BD_WALL;
3260     case EL_BD_ROCK:            return GFX_BD_ROCK;
3261     case EL_DX_SUPABOMB:        return GFX_DX_SUPABOMB;
3262     case EL_SP_MURPHY_CLONE:    return GFX_SP_MURPHY_CLONE;
3263
3264     default:
3265     {
3266       if (IS_CHAR(element))
3267         return GFX_CHAR_START + (element - EL_CHAR_START);
3268       else if (element >= EL_SP_START && element <= EL_SP_END)
3269       {
3270         int nr_element = element - EL_SP_START;
3271         int gfx_per_line = 8;
3272         int nr_graphic =
3273           (nr_element / gfx_per_line) * SP_PER_LINE +
3274           (nr_element % gfx_per_line);
3275
3276         return GFX_START_ROCKSSP + nr_graphic;
3277       }
3278       else
3279         return -1;
3280     }
3281   }
3282 }
3283
3284 int el2gfx(int element)
3285 {
3286   int graphic_NEW = element_info[element].graphic;
3287
3288 #if DEBUG
3289   int graphic_OLD = el2gfx_OLD(element);
3290
3291   if (element >= MAX_ELEMENTS)
3292   {
3293     Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
3294   }
3295
3296   if (graphic_NEW != graphic_OLD)
3297   {
3298     Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
3299           graphic_NEW, graphic_OLD);
3300   }
3301 #endif
3302
3303   return graphic_NEW;
3304 }
3305
3306 int el2img(int element)
3307 {
3308   switch(element)
3309   {
3310     case EL_BUTTERFLY:          return IMG_BD_BUTTERFLY;
3311     case EL_FIREFLY:            return IMG_BD_FIREFLY;
3312
3313     default:
3314       break;
3315   }
3316
3317   return IMG_EMPTY_SPACE;
3318 }
3319
3320 int el_dir2img(int element, int direction)
3321 {
3322   if (element_info[element].has_direction_graphic)
3323     return element_info[element].direction_graphic[LOG_MV_DIR(direction)];
3324   else
3325     return el2img(element);
3326 }