rnd-20020921-5-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_EMPTY;
406
407   for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
408   {
409     for(x=0; x<lev_fieldx; x++)
410     {
411       if (!IS_MASSIVE(Feld[x][y]))
412         BorderElement = EL_STEELWALL;
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_EXPLOSION)
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_FIELD_FULL)
486           DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
487         else
488           DrawLevelElement(next_jx, next_jy, EL_EMPTY);
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_EMPTY);
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_FIELD_EMPTY ||
609         Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
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_ROCK ||
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_EXPLOSION)
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, int sync_frame)
710 {
711   int num_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 frame;
715
716   /* animation synchronized with global frame counter, not move position */
717   if (new_graphic_info[graphic].anim_global_sync || sync_frame < 0)
718     sync_frame = FrameCounter;
719
720   if (mode & ANIM_PINGPONG)             /* use border frames once */
721   {
722     int max_anim_frames = 2 * num_frames - 2;
723
724     frame = (sync_frame % (delay * max_anim_frames)) / delay;
725     frame = (frame < num_frames ? frame : max_anim_frames - frame);
726   }
727   else if (mode & ANIM_PINGPONG2)       /* use border frames twice */
728   {
729     int max_anim_frames = 2 * num_frames;
730
731     frame = (sync_frame % (delay * max_anim_frames)) / delay;
732     frame = (frame < num_frames ? frame : max_anim_frames - frame - 1);
733   }
734   else  /* mode == ANIM_NORMAL || mode == ANIM_REVERSE */
735     frame = (sync_frame % (delay * num_frames)) / delay;
736
737   if (mode & ANIM_REVERSE)              /* use reverse animation direction */
738     frame = num_frames - frame - 1;
739
740   return frame;
741 }
742
743 void DrawGraphicAnimationExt(int x, int y, int graphic,
744                              int frames, int delay, int mode, int mask_mode)
745 {
746   int phase = getGraphicAnimationPhase(frames, delay, mode);
747
748   if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
749   {
750     if (mask_mode == USE_MASKING)
751       DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
752     else
753       DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
754   }
755 }
756
757 void DrawNewGraphicAnimationExt(int x, int y, int graphic, int mask_mode)
758 {
759   int delay = new_graphic_info[graphic].anim_delay;
760
761   if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
762   {
763     int frame = getNewGraphicAnimationFrame(graphic, -1);
764
765     if (mask_mode == USE_MASKING)
766       DrawNewGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
767     else
768       DrawNewGraphic(SCREENX(x), SCREENY(y), graphic, frame);
769   }
770 }
771
772 void DrawGraphicAnimation(int x, int y, int graphic,
773                           int frames, int delay, int mode)
774 {
775   DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
776 }
777
778 void DrawNewGraphicAnimation(int x, int y, int graphic)
779 {
780   DrawNewGraphicAnimationExt(x, y, graphic, NO_MASKING);
781 }
782
783 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
784                                   int frames, int delay, int mode)
785 {
786   DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
787 }
788
789 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
790                                                 int sxx, int syy,
791                                                 int graphic,
792                                                 int frames, int delay,
793                                                 int mode)
794 {
795   int phase = getGraphicAnimationPhase(frames, delay, mode);
796
797   DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
798 }
799
800 void getGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
801 {
802   if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
803   {
804     *bitmap = graphic_info[graphic].bitmap;
805     *x = graphic_info[graphic].src_x;
806     *y = graphic_info[graphic].src_y;
807   }
808   else if (graphic >= GFX_START_ROCKSELEMENTS &&
809            graphic <= GFX_END_ROCKSELEMENTS)
810   {
811     graphic -= GFX_START_ROCKSELEMENTS;
812     *bitmap = pix[PIX_ELEMENTS];
813     *x = (graphic % GFX_PER_LINE) * TILEX;
814     *y = (graphic / GFX_PER_LINE) * TILEY;
815   }
816   else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
817   {
818     graphic -= GFX_START_ROCKSHEROES;
819     *bitmap = pix[PIX_HEROES];
820     *x = (graphic % HEROES_PER_LINE) * TILEX;
821     *y = (graphic / HEROES_PER_LINE) * TILEY;
822   }
823   else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
824   {
825     graphic -= GFX_START_ROCKSSP;
826     *bitmap = pix[PIX_SP];
827     *x = (graphic % SP_PER_LINE) * TILEX;
828     *y = (graphic / SP_PER_LINE) * TILEY;
829   }
830   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
831   {
832     graphic -= GFX_START_ROCKSDC;
833     *bitmap = pix[PIX_DC];
834     *x = (graphic % DC_PER_LINE) * TILEX;
835     *y = (graphic / DC_PER_LINE) * TILEY;
836   }
837   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
838   {
839     graphic -= GFX_START_ROCKSMORE;
840     *bitmap = pix[PIX_MORE];
841     *x = (graphic % MORE_PER_LINE) * TILEX;
842     *y = (graphic / MORE_PER_LINE) * TILEY;
843   }
844   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
845   {
846     graphic -= GFX_START_ROCKSFONT;
847     *bitmap = pix[PIX_FONT_EM];
848     *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
849     *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
850   }
851   else
852   {
853     *bitmap = pix[PIX_SP];
854     *x = 0;
855     *y = 0;
856   }
857 }
858
859 void DrawGraphic(int x, int y, int graphic)
860 {
861 #if DEBUG
862   if (!IN_SCR_FIELD(x, y))
863   {
864     printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
865     printf("DrawGraphic(): This should never happen!\n");
866     return;
867   }
868 #endif
869
870   DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic);
871   MarkTileDirty(x, y);
872 }
873
874 void DrawNewGraphic(int x, int y, int graphic, int frame)
875 {
876 #if DEBUG
877   if (!IN_SCR_FIELD(x, y))
878   {
879     printf("DrawNewGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
880     printf("DrawNewGraphic(): This should never happen!\n");
881     return;
882   }
883 #endif
884
885   DrawNewGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
886                     graphic, frame);
887   MarkTileDirty(x, y);
888 }
889
890 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
891 {
892   Bitmap *src_bitmap;
893   int src_x, src_y;
894
895   getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
896   BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
897 }
898
899 void DrawNewGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
900                        int frame)
901 {
902   Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
903   int src_x = new_graphic_info[graphic].src_x;
904   int src_y = new_graphic_info[graphic].src_y;
905
906   if (new_graphic_info[graphic].anim_vertical)
907     src_y += frame * TILEY;
908   else
909     src_x += frame * TILEX;
910
911   BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
912 }
913
914 void DrawGraphicThruMask(int x, int y, int graphic)
915 {
916 #if DEBUG
917   if (!IN_SCR_FIELD(x, y))
918   {
919     printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
920     printf("DrawGraphicThruMask(): This should never happen!\n");
921     return;
922   }
923 #endif
924
925   DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic);
926   MarkTileDirty(x, y);
927 }
928
929 void DrawNewGraphicThruMask(int x, int y, int graphic, int frame)
930 {
931 #if DEBUG
932   if (!IN_SCR_FIELD(x, y))
933   {
934     printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
935     printf("DrawGraphicThruMask(): This should never happen!\n");
936     return;
937   }
938 #endif
939
940   DrawNewGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY,
941                             graphic, frame);
942   MarkTileDirty(x, y);
943 }
944
945 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
946 {
947   int tile = graphic;
948   int src_x, src_y;
949   Bitmap *src_bitmap;
950   GC drawing_gc;
951
952   if (graphic == GFX_LEERRAUM)
953     return;
954
955   getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
956   drawing_gc = src_bitmap->stored_clip_gc;
957
958   if (tile_clipmask[tile] != None)
959   {
960     SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
961     SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
962     BlitBitmapMasked(src_bitmap, d,
963                      src_x, src_y, TILEX, TILEY, dest_x, dest_y);
964   }
965   else
966   {
967 #if DEBUG
968 #ifndef TARGET_SDL
969     printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
970 #endif
971 #endif
972
973     SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
974     BlitBitmapMasked(src_bitmap, d,
975                      src_x, src_y, TILEX, TILEY, dest_x, dest_y);
976   }
977 }
978
979 void DrawNewGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y,
980                                int graphic, int frame)
981 {
982   Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
983   GC drawing_gc = src_bitmap->stored_clip_gc;
984   int src_x = new_graphic_info[graphic].src_x;
985   int src_y = new_graphic_info[graphic].src_y;
986
987   if (new_graphic_info[graphic].anim_vertical)
988     src_y += frame * TILEY;
989   else
990     src_x += frame * TILEX;
991
992   SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
993   BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
994 }
995
996 void DrawMiniGraphic(int x, int y, int graphic)
997 {
998   DrawMiniGraphicExt(drawto, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
999   MarkTileDirty(x/2, y/2);
1000 }
1001
1002 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1003 {
1004   if (graphic >= GFX_START_ROCKSELEMENTS && graphic <= GFX_END_ROCKSELEMENTS)
1005   {
1006     graphic -= GFX_START_ROCKSELEMENTS;
1007     *bitmap = pix[PIX_ELEMENTS];
1008     *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
1009     *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
1010   }
1011   else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1012   {
1013     graphic -= GFX_START_ROCKSSP;
1014     *bitmap = pix[PIX_SP];
1015     *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
1016     *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
1017   }
1018   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1019   {
1020     graphic -= GFX_START_ROCKSDC;
1021     *bitmap = pix[PIX_DC];
1022     *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
1023     *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
1024   }
1025   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1026   {
1027     graphic -= GFX_START_ROCKSMORE;
1028     *bitmap = pix[PIX_MORE];
1029     *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
1030     *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
1031   }
1032   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
1033   {
1034     graphic -= GFX_START_ROCKSFONT;
1035     *bitmap = pix[PIX_FONT_EM];
1036     *x = MINI_FONT_STARTX + (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
1037     *y = MINI_FONT_STARTY + (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE;
1038   }
1039   else
1040   {
1041     *bitmap = pix[PIX_SP];
1042     *x = MINI_SP_STARTX;
1043     *y = MINI_SP_STARTY;
1044   }
1045 }
1046
1047 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1048 {
1049   Bitmap *bitmap;
1050   int src_x, src_y;
1051
1052   getMiniGraphicSource(graphic, &bitmap, &src_x, &src_y);
1053   BlitBitmap(bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1054 }
1055
1056 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
1057                         int cut_mode, int mask_mode)
1058 {
1059   int width = TILEX, height = TILEY;
1060   int cx = 0, cy = 0;
1061   int src_x, src_y, dest_x, dest_y;
1062   int tile = graphic;
1063   Bitmap *src_bitmap;
1064   GC drawing_gc;
1065
1066   if (graphic < 0)
1067   {
1068     DrawGraphic(x, y, graphic);
1069     return;
1070   }
1071
1072   if (dx || dy)                 /* Verschiebung der Grafik? */
1073   {
1074     if (x < BX1)                /* Element kommt von links ins Bild */
1075     {
1076       x = BX1;
1077       width = dx;
1078       cx = TILEX - dx;
1079       dx = 0;
1080     }
1081     else if (x > BX2)           /* Element kommt von rechts ins Bild */
1082     {
1083       x = BX2;
1084       width = -dx;
1085       dx = TILEX + dx;
1086     }
1087     else if (x==BX1 && dx < 0)  /* Element verläßt links das Bild */
1088     {
1089       width += dx;
1090       cx = -dx;
1091       dx = 0;
1092     }
1093     else if (x==BX2 && dx > 0)  /* Element verläßt rechts das Bild */
1094       width -= dx;
1095     else if (dx)                /* allg. Bewegung in x-Richtung */
1096       MarkTileDirty(x + SIGN(dx), y);
1097
1098     if (y < BY1)                /* Element kommt von oben ins Bild */
1099     {
1100       if (cut_mode==CUT_BELOW)  /* Element oberhalb des Bildes */
1101         return;
1102
1103       y = BY1;
1104       height = dy;
1105       cy = TILEY - dy;
1106       dy = 0;
1107     }
1108     else if (y > BY2)           /* Element kommt von unten ins Bild */
1109     {
1110       y = BY2;
1111       height = -dy;
1112       dy = TILEY + dy;
1113     }
1114     else if (y==BY1 && dy < 0)  /* Element verläßt oben das Bild */
1115     {
1116       height += dy;
1117       cy = -dy;
1118       dy = 0;
1119     }
1120     else if (dy > 0 && cut_mode == CUT_ABOVE)
1121     {
1122       if (y == BY2)             /* Element unterhalb des Bildes */
1123         return;
1124
1125       height = dy;
1126       cy = TILEY - dy;
1127       dy = TILEY;
1128       MarkTileDirty(x, y + 1);
1129     }                           /* Element verläßt unten das Bild */
1130     else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1131       height -= dy;
1132     else if (dy)                /* allg. Bewegung in y-Richtung */
1133       MarkTileDirty(x, y + SIGN(dy));
1134   }
1135
1136   getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1137   drawing_gc = src_bitmap->stored_clip_gc;
1138
1139   src_x += cx;
1140   src_y += cy;
1141
1142   dest_x = FX + x * TILEX + dx;
1143   dest_y = FY + y * TILEY + dy;
1144
1145 #if DEBUG
1146   if (!IN_SCR_FIELD(x,y))
1147   {
1148     printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1149     printf("DrawGraphicShifted(): This should never happen!\n");
1150     return;
1151   }
1152 #endif
1153
1154   if (mask_mode == USE_MASKING)
1155   {
1156     if (tile_clipmask[tile] != None)
1157     {
1158       SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
1159       SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
1160       BlitBitmapMasked(src_bitmap, drawto_field,
1161                        src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1162     }
1163     else
1164     {
1165 #if DEBUG
1166 #ifndef TARGET_SDL
1167       printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1168 #endif
1169 #endif
1170
1171       SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1172       BlitBitmapMasked(src_bitmap, drawto_field,
1173                        src_x, src_y, width, height, dest_x, dest_y);
1174     }
1175   }
1176   else
1177     BlitBitmap(src_bitmap, drawto_field,
1178                src_x, src_y, width, height, dest_x, dest_y);
1179
1180   MarkTileDirty(x,y);
1181 }
1182
1183 void DrawNewGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1184                         int cut_mode, int mask_mode)
1185 {
1186   Bitmap *src_bitmap;
1187   GC drawing_gc;
1188   int src_x;
1189   int src_y;
1190
1191   int width = TILEX, height = TILEY;
1192   int cx = 0, cy = 0;
1193   int dest_x, dest_y;
1194
1195   if (graphic < 0)
1196   {
1197     DrawNewGraphic(x, y, graphic, frame);
1198     return;
1199   }
1200
1201   if (dx || dy)                 /* Verschiebung der Grafik? */
1202   {
1203     if (x < BX1)                /* Element kommt von links ins Bild */
1204     {
1205       x = BX1;
1206       width = dx;
1207       cx = TILEX - dx;
1208       dx = 0;
1209     }
1210     else if (x > BX2)           /* Element kommt von rechts ins Bild */
1211     {
1212       x = BX2;
1213       width = -dx;
1214       dx = TILEX + dx;
1215     }
1216     else if (x==BX1 && dx < 0)  /* Element verläßt links das Bild */
1217     {
1218       width += dx;
1219       cx = -dx;
1220       dx = 0;
1221     }
1222     else if (x==BX2 && dx > 0)  /* Element verläßt rechts das Bild */
1223       width -= dx;
1224     else if (dx)                /* allg. Bewegung in x-Richtung */
1225       MarkTileDirty(x + SIGN(dx), y);
1226
1227     if (y < BY1)                /* Element kommt von oben ins Bild */
1228     {
1229       if (cut_mode==CUT_BELOW)  /* Element oberhalb des Bildes */
1230         return;
1231
1232       y = BY1;
1233       height = dy;
1234       cy = TILEY - dy;
1235       dy = 0;
1236     }
1237     else if (y > BY2)           /* Element kommt von unten ins Bild */
1238     {
1239       y = BY2;
1240       height = -dy;
1241       dy = TILEY + dy;
1242     }
1243     else if (y==BY1 && dy < 0)  /* Element verläßt oben das Bild */
1244     {
1245       height += dy;
1246       cy = -dy;
1247       dy = 0;
1248     }
1249     else if (dy > 0 && cut_mode == CUT_ABOVE)
1250     {
1251       if (y == BY2)             /* Element unterhalb des Bildes */
1252         return;
1253
1254       height = dy;
1255       cy = TILEY - dy;
1256       dy = TILEY;
1257       MarkTileDirty(x, y + 1);
1258     }                           /* Element verläßt unten das Bild */
1259     else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1260       height -= dy;
1261     else if (dy)                /* allg. Bewegung in y-Richtung */
1262       MarkTileDirty(x, y + SIGN(dy));
1263   }
1264
1265   src_bitmap = new_graphic_info[graphic].bitmap;
1266   drawing_gc = src_bitmap->stored_clip_gc;
1267   src_x = new_graphic_info[graphic].src_x;
1268   src_y = new_graphic_info[graphic].src_y;
1269
1270   if (new_graphic_info[graphic].anim_vertical)
1271     src_y += frame * TILEY;
1272   else
1273     src_x += frame * TILEX;
1274
1275   src_x += cx;
1276   src_y += cy;
1277
1278   dest_x = FX + x * TILEX + dx;
1279   dest_y = FY + y * TILEY + dy;
1280
1281 #if DEBUG
1282   if (!IN_SCR_FIELD(x,y))
1283   {
1284     printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1285     printf("DrawGraphicShifted(): This should never happen!\n");
1286     return;
1287   }
1288 #endif
1289
1290   if (mask_mode == USE_MASKING)
1291     SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1292
1293   BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1294              dest_x, dest_y);
1295
1296   MarkTileDirty(x,y);
1297 }
1298
1299 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1300                                 int cut_mode)
1301 {
1302   DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1303 }
1304
1305 void DrawNewGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1306                                    int frame, int cut_mode)
1307 {
1308   DrawNewGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1309 }
1310
1311 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1312                           int cut_mode, int mask_mode)
1313 {
1314   int ux = LEVELX(x), uy = LEVELY(y);
1315   int graphic = el2gfx(element);
1316   int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1317   int phase4 = phase8 / 2;
1318   int phase2  = phase8 / 4;
1319   int dir = MovDir[ux][uy];
1320
1321   if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1322   {
1323     graphic += 1 * !phase2;
1324
1325     if (dir == MV_UP)
1326       graphic += 1 * 2;
1327     else if (dir == MV_LEFT)
1328       graphic += 2 * 2;
1329     else if (dir == MV_DOWN)
1330       graphic += 3 * 2;
1331   }
1332   else if (element == EL_SP_SNIKSNAK)
1333   {
1334     if (dir == MV_LEFT)
1335       graphic = GFX_SP_SNIKSNAK_LEFT;
1336     else if (dir == MV_RIGHT)
1337       graphic = GFX_SP_SNIKSNAK_RIGHT;
1338     else if (dir == MV_UP)
1339       graphic = GFX_SP_SNIKSNAK_UP;
1340     else
1341       graphic = GFX_SP_SNIKSNAK_DOWN;
1342
1343     graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1344   }
1345   else if (element == EL_SP_ELECTRON)
1346   {
1347     graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1348   }
1349   else if (element == EL_MOLE || element == EL_PENGUIN ||
1350            element == EL_PIG || element == EL_DRAGON)
1351   {
1352     if (dir == MV_LEFT)
1353       graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1354                  element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1355                  element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1356     else if (dir == MV_RIGHT)
1357       graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1358                  element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1359                  element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1360     else if (dir == MV_UP)
1361       graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1362                  element == EL_PENGUIN ? GFX_PINGUIN_UP :
1363                  element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1364     else
1365       graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1366                  element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1367                  element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1368
1369     graphic += phase4;
1370   }
1371   else if (element == EL_SATELLITE)
1372   {
1373     graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1374   }
1375   else if (element == EL_ACID)
1376   {
1377     graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1378   }
1379   else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1380   {
1381     graphic += !phase2;
1382   }
1383   else if (element == EL_BALLOON)
1384   {
1385     graphic += phase4;
1386   }
1387   else if ((element == EL_ROCK ||
1388             element == EL_SP_ZONK ||
1389             element == EL_BD_ROCK ||
1390             element == EL_SP_INFOTRON ||
1391             IS_GEM(element))
1392            && !cut_mode)
1393   {
1394     if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1395     {
1396       if (element == EL_ROCK ||
1397           element == EL_SP_ZONK ||
1398           element == EL_BD_ROCK)
1399       {
1400         if (dir == MV_LEFT)
1401           graphic += (4 - phase4) % 4;
1402         else if (dir == MV_RIGHT)
1403           graphic += phase4;
1404         else
1405           graphic += phase2 * 2;
1406       }
1407       else if (element != EL_SP_INFOTRON)
1408         graphic += phase2;
1409     }
1410   }
1411   else if (element == EL_MAGIC_WALL_ACTIVE ||
1412            element == EL_MAGIC_WALL_EMPTYING ||
1413            element == EL_BD_MAGIC_WALL_ACTIVE ||
1414            element == EL_BD_MAGIC_WALL_EMPTYING ||
1415            element == EL_MAGIC_WALL_FULL ||
1416            element == EL_BD_MAGIC_WALL_FULL)
1417   {
1418     graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1419   }
1420   else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1421   {
1422     graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1423     graphic += (x + 2 * y + 4) % 4;
1424   }
1425   else if (element == EL_WALL_GROWING)
1426   {
1427     boolean links_massiv = FALSE, rechts_massiv = FALSE;
1428
1429     if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1430       links_massiv = TRUE;
1431     if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1432       rechts_massiv = TRUE;
1433
1434     if (links_massiv && rechts_massiv)
1435       graphic = GFX_MAUERWERK;
1436     else if (links_massiv)
1437       graphic = GFX_MAUER_R;
1438     else if (rechts_massiv)
1439       graphic = GFX_MAUER_L;
1440   }
1441 #if 0
1442   else if ((element == EL_INVISIBLE_STEELWALL ||
1443             element == EL_INVISIBLE_WALL ||
1444             element == EL_INVISIBLE_SAND) && game.light_time_left)
1445   {
1446     graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1447                element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1448                GFX_SAND_INVISIBLE_ON);
1449   }
1450 #endif
1451
1452   if (dx || dy)
1453     DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1454   else if (mask_mode == USE_MASKING)
1455     DrawGraphicThruMask(x, y, graphic);
1456   else
1457     DrawGraphic(x, y, graphic);
1458 }
1459
1460 void DrawNewScreenElementExt(int x, int y, int dx, int dy, int element,
1461                           int cut_mode, int mask_mode)
1462 {
1463   int ux = LEVELX(x), uy = LEVELY(y);
1464   int move_dir = MovDir[ux][uy];
1465   int move_pos = ABS(MovPos[ux][uy]) / (TILEX / 8);
1466   int graphic = el_dir2img(element, move_dir);
1467   int frame = getNewGraphicAnimationFrame(graphic, move_pos);
1468   int phase8 = move_pos;
1469   int phase4 = phase8 / 2;
1470   int phase2  = phase8 / 4;
1471
1472   int dir = move_dir;   /* !!! THROW AWAY LATER !!! */
1473
1474   if (0)
1475   {
1476     ;
1477   }
1478 #if 0
1479   else if (element == EL_PACMAN || element == EL_BUG ||
1480            element == EL_SPACESHIP)
1481   {
1482     graphic += 1 * !phase2;
1483
1484     if (dir == MV_UP)
1485       graphic += 1 * 2;
1486     else if (dir == MV_LEFT)
1487       graphic += 2 * 2;
1488     else if (dir == MV_DOWN)
1489       graphic += 3 * 2;
1490   }
1491   else if (element == EL_SP_SNIKSNAK)
1492   {
1493     if (dir == MV_LEFT)
1494       graphic = GFX_SP_SNIKSNAK_LEFT;
1495     else if (dir == MV_RIGHT)
1496       graphic = GFX_SP_SNIKSNAK_RIGHT;
1497     else if (dir == MV_UP)
1498       graphic = GFX_SP_SNIKSNAK_UP;
1499     else
1500       graphic = GFX_SP_SNIKSNAK_DOWN;
1501
1502     graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1503   }
1504   else if (element == EL_SP_ELECTRON)
1505   {
1506     graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1507   }
1508 #endif
1509   else if (element == EL_MOLE || element == EL_PENGUIN ||
1510            element == EL_PIG || element == EL_DRAGON)
1511   {
1512     if (dir == MV_LEFT)
1513       graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1514                  element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1515                  element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1516     else if (dir == MV_RIGHT)
1517       graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1518                  element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1519                  element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1520     else if (dir == MV_UP)
1521       graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1522                  element == EL_PENGUIN ? GFX_PINGUIN_UP :
1523                  element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1524     else
1525       graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1526                  element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1527                  element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1528
1529     graphic += phase4;
1530   }
1531   else if (element == EL_SATELLITE)
1532   {
1533 #if 1
1534     graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1535 #else
1536     graphic = GFX_SONDE_START + getNewGraphicAnimationFrame(graphic, move_pos);
1537 #endif
1538   }
1539   else if (element == EL_ACID)
1540   {
1541 #if 1
1542     graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1543 #else
1544     graphic = GFX_GEBLUBBER + getNewGraphicAnimationFrame(graphic, move_pos);
1545 #endif
1546   }
1547   else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1548   {
1549     graphic += !phase2;
1550   }
1551   else if (element == EL_BALLOON)
1552   {
1553     graphic += phase4;
1554   }
1555   else if ((element == EL_ROCK ||
1556             element == EL_SP_ZONK ||
1557             element == EL_BD_ROCK ||
1558             element == EL_SP_INFOTRON ||
1559             IS_GEM(element))
1560            && !cut_mode)
1561   {
1562     if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1563     {
1564       if (element == EL_ROCK ||
1565           element == EL_SP_ZONK ||
1566           element == EL_BD_ROCK)
1567       {
1568         if (dir == MV_LEFT)
1569           graphic += (4 - phase4) % 4;
1570         else if (dir == MV_RIGHT)
1571           graphic += phase4;
1572         else
1573           graphic += phase2 * 2;
1574       }
1575       else if (element != EL_SP_INFOTRON)
1576         graphic += phase2;
1577     }
1578   }
1579   else if (element == EL_MAGIC_WALL_ACTIVE ||
1580            element == EL_MAGIC_WALL_EMPTYING ||
1581            element == EL_BD_MAGIC_WALL_ACTIVE ||
1582            element == EL_BD_MAGIC_WALL_EMPTYING ||
1583            element == EL_MAGIC_WALL_FULL ||
1584            element == EL_BD_MAGIC_WALL_FULL)
1585   {
1586 #if 1
1587     graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1588 #else
1589     graphic += 3 + getNewGraphicAnimationFrame(graphic, move_pos);
1590 #endif
1591   }
1592   else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1593   {
1594     graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1595     graphic += (x + 2 * y + 4) % 4;
1596   }
1597   else if (element == EL_WALL_GROWING)
1598   {
1599     boolean links_massiv = FALSE, rechts_massiv = FALSE;
1600
1601     if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1602       links_massiv = TRUE;
1603     if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1604       rechts_massiv = TRUE;
1605
1606     if (links_massiv && rechts_massiv)
1607       graphic = GFX_MAUERWERK;
1608     else if (links_massiv)
1609       graphic = GFX_MAUER_R;
1610     else if (rechts_massiv)
1611       graphic = GFX_MAUER_L;
1612   }
1613 #if 0
1614   else if ((element == EL_INVISIBLE_STEELWALL ||
1615             element == EL_INVISIBLE_WALL ||
1616             element == EL_INVISIBLE_SAND) && game.light_time_left)
1617   {
1618     graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1619                element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1620                GFX_SAND_INVISIBLE_ON);
1621   }
1622 #endif
1623
1624   if (dx || dy)
1625     DrawNewGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1626   else if (mask_mode == USE_MASKING)
1627     DrawNewGraphicThruMask(x, y, graphic, frame);
1628   else
1629     DrawNewGraphic(x, y, graphic, frame);
1630 }
1631
1632 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1633                          int cut_mode, int mask_mode)
1634 {
1635   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1636     DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1637                          cut_mode, mask_mode);
1638 }
1639
1640 void DrawNewLevelElementExt(int x, int y, int dx, int dy, int element,
1641                          int cut_mode, int mask_mode)
1642 {
1643   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1644     DrawNewScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1645                          cut_mode, mask_mode);
1646 }
1647
1648 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1649                               int cut_mode)
1650 {
1651   DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1652 }
1653
1654 void DrawNewScreenElementShifted(int x, int y, int dx, int dy, int element,
1655                               int cut_mode)
1656 {
1657   DrawNewScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1658 }
1659
1660 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1661                              int cut_mode)
1662 {
1663   DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1664 }
1665
1666 void DrawNewLevelElementShifted(int x, int y, int dx, int dy, int element,
1667                              int cut_mode)
1668 {
1669   DrawNewLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1670 }
1671
1672 void DrawScreenElementThruMask(int x, int y, int element)
1673 {
1674   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1675 }
1676
1677 void DrawNewScreenElementThruMask(int x, int y, int element)
1678 {
1679   DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1680 }
1681
1682 void DrawLevelElementThruMask(int x, int y, int element)
1683 {
1684   DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1685 }
1686
1687 void DrawNewLevelElementThruMask(int x, int y, int element)
1688 {
1689   DrawNewLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1690 }
1691
1692 void DrawLevelFieldThruMask(int x, int y)
1693 {
1694   DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1695 }
1696
1697 void DrawNewLevelFieldThruMask(int x, int y)
1698 {
1699   DrawNewLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1700 }
1701
1702 void ErdreichAnbroeckeln(int x, int y)
1703 {
1704   Bitmap *src_bitmap;
1705   int src_x, src_y;
1706   int i, width, height, cx,cy;
1707   int ux = LEVELX(x), uy = LEVELY(y);
1708   int element, graphic;
1709   int snip = 4;
1710   static int xy[4][2] =
1711   {
1712     { 0, -1 },
1713     { -1, 0 },
1714     { +1, 0 },
1715     { 0, +1 }
1716   };
1717
1718   if (!IN_LEV_FIELD(ux, uy))
1719     return;
1720
1721   element = Feld[ux][uy];
1722
1723   if (element == EL_SAND ||
1724       element == EL_LANDMINE ||
1725       element == EL_TRAP ||
1726       element == EL_TRAP_ACTIVE)
1727   {
1728     if (!IN_SCR_FIELD(x, y))
1729       return;
1730
1731     graphic = GFX_ERDENRAND;
1732
1733     getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1734
1735     for(i=0; i<4; i++)
1736     {
1737       int uxx, uyy;
1738
1739       uxx = ux + xy[i][0];
1740       uyy = uy + xy[i][1];
1741       if (!IN_LEV_FIELD(uxx, uyy))
1742         element = EL_STEELWALL;
1743       else
1744         element = Feld[uxx][uyy];
1745
1746       if (element == EL_SAND ||
1747           element == EL_LANDMINE ||
1748           element == EL_TRAP ||
1749           element == EL_TRAP_ACTIVE)
1750         continue;
1751
1752       if (i == 1 || i == 2)
1753       {
1754         width = snip;
1755         height = TILEY;
1756         cx = (i == 2 ? TILEX - snip : 0);
1757         cy = 0;
1758       }
1759       else
1760       {
1761         width = TILEX;
1762         height = snip;
1763         cx = 0;
1764         cy = (i == 3 ? TILEY - snip : 0);
1765       }
1766
1767       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1768                  width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1769     }
1770
1771     MarkTileDirty(x, y);
1772   }
1773   else
1774   {
1775     graphic = GFX_ERDENRAND;
1776
1777     getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1778
1779     for(i=0; i<4; i++)
1780     {
1781       int xx, yy, uxx, uyy;
1782
1783       xx = x + xy[i][0];
1784       yy = y + xy[i][1];
1785       uxx = ux + xy[i][0];
1786       uyy = uy + xy[i][1];
1787
1788       if (!IN_LEV_FIELD(uxx, uyy) ||
1789           (Feld[uxx][uyy] != EL_SAND &&
1790            Feld[uxx][uyy] != EL_LANDMINE &&
1791            Feld[uxx][uyy] != EL_TRAP &&
1792            Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1793           !IN_SCR_FIELD(xx, yy))
1794         continue;
1795
1796       if (i == 1 || i == 2)
1797       {
1798         width = snip;
1799         height = TILEY;
1800         cx = (i == 1 ? TILEX - snip : 0);
1801         cy = 0;
1802       }
1803       else
1804       {
1805         width = TILEX;
1806         height = snip;
1807         cx = 0;
1808         cy = (i==0 ? TILEY-snip : 0);
1809       }
1810
1811       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1812                  width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1813
1814       MarkTileDirty(xx, yy);
1815     }
1816   }
1817 }
1818
1819 void DrawScreenElement(int x, int y, int element)
1820 {
1821   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1822   ErdreichAnbroeckeln(x, y);
1823 }
1824
1825 void DrawNewScreenElement(int x, int y, int element)
1826 {
1827   DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1828   ErdreichAnbroeckeln(x, y);
1829 }
1830
1831 void DrawLevelElement(int x, int y, int element)
1832 {
1833   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1834     DrawScreenElement(SCREENX(x), SCREENY(y), element);
1835 }
1836
1837 void DrawNewLevelElement(int x, int y, int element)
1838 {
1839   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1840     DrawNewScreenElement(SCREENX(x), SCREENY(y), element);
1841 }
1842
1843 void DrawScreenField(int x, int y)
1844 {
1845   int ux = LEVELX(x), uy = LEVELY(y);
1846   int element, content;
1847
1848   if (!IN_LEV_FIELD(ux, uy))
1849   {
1850     if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1851       element = EL_EMPTY;
1852     else
1853       element = BorderElement;
1854
1855     DrawScreenElement(x, y, element);
1856     return;
1857   }
1858
1859   element = Feld[ux][uy];
1860   content = Store[ux][uy];
1861
1862   if (IS_MOVING(ux, uy))
1863   {
1864     int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1865     boolean cut_mode = NO_CUTTING;
1866
1867     if (element == EL_QUICKSAND_EMPTYING ||
1868         element == EL_MAGIC_WALL_EMPTYING ||
1869         element == EL_BD_MAGIC_WALL_EMPTYING ||
1870         element == EL_AMOEBA_DRIPPING)
1871       cut_mode = CUT_ABOVE;
1872     else if (element == EL_QUICKSAND_FILLING ||
1873              element == EL_MAGIC_WALL_FILLING ||
1874              element == EL_BD_MAGIC_WALL_FILLING)
1875       cut_mode = CUT_BELOW;
1876
1877     if (cut_mode == CUT_ABOVE)
1878       DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1879     else
1880       DrawScreenElement(x, y, EL_EMPTY);
1881
1882     if (horiz_move)
1883       DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1884     else if (cut_mode == NO_CUTTING)
1885       DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1886     else
1887       DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1888
1889     if (content == EL_ACID)
1890       DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1891   }
1892   else if (IS_BLOCKED(ux, uy))
1893   {
1894     int oldx, oldy;
1895     int sx, sy;
1896     int horiz_move;
1897     boolean cut_mode = NO_CUTTING;
1898     int element_old, content_old;
1899
1900     Blocked2Moving(ux, uy, &oldx, &oldy);
1901     sx = SCREENX(oldx);
1902     sy = SCREENY(oldy);
1903     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1904                   MovDir[oldx][oldy] == MV_RIGHT);
1905
1906     element_old = Feld[oldx][oldy];
1907     content_old = Store[oldx][oldy];
1908
1909     if (element_old == EL_QUICKSAND_EMPTYING ||
1910         element_old == EL_MAGIC_WALL_EMPTYING ||
1911         element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1912         element_old == EL_AMOEBA_DRIPPING)
1913       cut_mode = CUT_ABOVE;
1914
1915     DrawScreenElement(x, y, EL_EMPTY);
1916
1917     if (horiz_move)
1918       DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1919                                NO_CUTTING);
1920     else if (cut_mode == NO_CUTTING)
1921       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1922                                cut_mode);
1923     else
1924       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1925                                cut_mode);
1926   }
1927   else if (IS_DRAWABLE(element))
1928     DrawScreenElement(x, y, element);
1929   else
1930     DrawScreenElement(x, y, EL_EMPTY);
1931 }
1932
1933 void DrawNewScreenField(int x, int y)
1934 {
1935   int ux = LEVELX(x), uy = LEVELY(y);
1936   int element, content;
1937
1938   if (!IN_LEV_FIELD(ux, uy))
1939   {
1940     if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1941       element = EL_EMPTY;
1942     else
1943       element = BorderElement;
1944
1945     DrawNewScreenElement(x, y, element);
1946     return;
1947   }
1948
1949   element = Feld[ux][uy];
1950   content = Store[ux][uy];
1951
1952   if (IS_MOVING(ux, uy))
1953   {
1954     int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1955     boolean cut_mode = NO_CUTTING;
1956
1957     if (element == EL_QUICKSAND_EMPTYING ||
1958         element == EL_MAGIC_WALL_EMPTYING ||
1959         element == EL_BD_MAGIC_WALL_EMPTYING ||
1960         element == EL_AMOEBA_DRIPPING)
1961       cut_mode = CUT_ABOVE;
1962     else if (element == EL_QUICKSAND_FILLING ||
1963              element == EL_MAGIC_WALL_FILLING ||
1964              element == EL_BD_MAGIC_WALL_FILLING)
1965       cut_mode = CUT_BELOW;
1966
1967     if (cut_mode == CUT_ABOVE)
1968       DrawNewScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1969     else
1970       DrawNewScreenElement(x, y, EL_EMPTY);
1971
1972     if (horiz_move)
1973       DrawNewScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1974     else if (cut_mode == NO_CUTTING)
1975       DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1976     else
1977       DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1978
1979     if (content == EL_ACID)
1980       DrawNewLevelElementThruMask(ux, uy + 1, EL_ACID);
1981   }
1982   else if (IS_BLOCKED(ux, uy))
1983   {
1984     int oldx, oldy;
1985     int sx, sy;
1986     int horiz_move;
1987     boolean cut_mode = NO_CUTTING;
1988     int element_old, content_old;
1989
1990     Blocked2Moving(ux, uy, &oldx, &oldy);
1991     sx = SCREENX(oldx);
1992     sy = SCREENY(oldy);
1993     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1994                   MovDir[oldx][oldy] == MV_RIGHT);
1995
1996     element_old = Feld[oldx][oldy];
1997     content_old = Store[oldx][oldy];
1998
1999     if (element_old == EL_QUICKSAND_EMPTYING ||
2000         element_old == EL_MAGIC_WALL_EMPTYING ||
2001         element_old == EL_BD_MAGIC_WALL_EMPTYING ||
2002         element_old == EL_AMOEBA_DRIPPING)
2003       cut_mode = CUT_ABOVE;
2004
2005     DrawNewScreenElement(x, y, EL_EMPTY);
2006
2007     if (horiz_move)
2008       DrawNewScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
2009                                NO_CUTTING);
2010     else if (cut_mode == NO_CUTTING)
2011       DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
2012                                cut_mode);
2013     else
2014       DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
2015                                cut_mode);
2016   }
2017   else if (IS_DRAWABLE(element))
2018     DrawNewScreenElement(x, y, element);
2019   else
2020     DrawNewScreenElement(x, y, EL_EMPTY);
2021 }
2022
2023 void DrawLevelField(int x, int y)
2024 {
2025   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2026     DrawScreenField(SCREENX(x), SCREENY(y));
2027   else if (IS_MOVING(x, y))
2028   {
2029     int newx,newy;
2030
2031     Moving2Blocked(x, y, &newx, &newy);
2032     if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2033       DrawScreenField(SCREENX(newx), SCREENY(newy));
2034   }
2035   else if (IS_BLOCKED(x, y))
2036   {
2037     int oldx, oldy;
2038
2039     Blocked2Moving(x, y, &oldx, &oldy);
2040     if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2041       DrawScreenField(SCREENX(oldx), SCREENY(oldy));
2042   }
2043 }
2044
2045 void DrawNewLevelField(int x, int y)
2046 {
2047   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2048     DrawNewScreenField(SCREENX(x), SCREENY(y));
2049   else if (IS_MOVING(x, y))
2050   {
2051     int newx,newy;
2052
2053     Moving2Blocked(x, y, &newx, &newy);
2054     if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2055       DrawNewScreenField(SCREENX(newx), SCREENY(newy));
2056   }
2057   else if (IS_BLOCKED(x, y))
2058   {
2059     int oldx, oldy;
2060
2061     Blocked2Moving(x, y, &oldx, &oldy);
2062     if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2063       DrawNewScreenField(SCREENX(oldx), SCREENY(oldy));
2064   }
2065 }
2066
2067 void DrawMiniElement(int x, int y, int element)
2068 {
2069   int graphic;
2070
2071   if (!element)
2072   {
2073     DrawMiniGraphic(x, y, -1);
2074     return;
2075   }
2076
2077   graphic = el2gfx(element);
2078   DrawMiniGraphic(x, y, graphic);
2079 }
2080
2081 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2082 {
2083   int x = sx + scroll_x, y = sy + scroll_y;
2084
2085   if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2086     DrawMiniElement(sx, sy, EL_EMPTY);
2087   else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2088     DrawMiniElement(sx, sy, Feld[x][y]);
2089   else
2090   {
2091     int steel_type, steel_position;
2092     int border[6][2] =
2093     {
2094       { GFX_VSTEEL_UPPER_LEFT,  GFX_ISTEEL_UPPER_LEFT  },
2095       { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
2096       { GFX_VSTEEL_LOWER_LEFT,  GFX_ISTEEL_LOWER_LEFT  },
2097       { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
2098       { GFX_VSTEEL_VERTICAL,    GFX_ISTEEL_VERTICAL    },
2099       { GFX_VSTEEL_HORIZONTAL,  GFX_ISTEEL_HORIZONTAL  }
2100     };
2101
2102     steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2103     steel_position = (x == -1 && y == -1                        ? 0 :
2104                       x == lev_fieldx && y == -1                ? 1 :
2105                       x == -1 && y == lev_fieldy                ? 2 :
2106                       x == lev_fieldx && y == lev_fieldy        ? 3 :
2107                       x == -1 || x == lev_fieldx                ? 4 :
2108                       y == -1 || y == lev_fieldy                ? 5 : -1);
2109
2110     if (steel_position != -1)
2111       DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
2112   }
2113 }
2114
2115 void DrawMicroElement(int xpos, int ypos, int element)
2116 {
2117   int graphic;
2118
2119   if (element == EL_EMPTY)
2120     return;
2121
2122   graphic = el2gfx(element);
2123
2124   if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
2125   {
2126     graphic -= GFX_START_ROCKSSP;
2127     BlitBitmap(pix[PIX_SP], drawto,
2128                MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
2129                MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
2130                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2131   }
2132   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
2133   {
2134     graphic -= GFX_START_ROCKSDC;
2135     BlitBitmap(pix[PIX_DC], drawto,
2136                MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
2137                MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
2138                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2139   }
2140   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
2141   {
2142     graphic -= GFX_START_ROCKSMORE;
2143     BlitBitmap(pix[PIX_MORE], drawto,
2144                MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE)*MICRO_TILEX,
2145                MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE)*MICRO_TILEY,
2146                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2147   }
2148   else if (graphic >= GFX_CHAR_START && graphic <= GFX_CHAR_END)
2149   {
2150     graphic -= GFX_CHAR_START;
2151     BlitBitmap(pix[PIX_FONT_EM], drawto,
2152                MICRO_FONT_STARTX + (graphic % MICRO_GFX_PER_LINE)* MICRO_TILEX,
2153                MICRO_FONT_STARTY + (graphic / MICRO_GFX_PER_LINE)* MICRO_TILEY,
2154                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2155   }
2156   else
2157     BlitBitmap(pix[PIX_ELEMENTS], drawto,
2158                MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
2159                MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
2160                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2161 }
2162
2163 void DrawLevel()
2164 {
2165   int x,y;
2166
2167   ClearWindow();
2168
2169   for(x=BX1; x<=BX2; x++)
2170     for(y=BY1; y<=BY2; y++)
2171       DrawScreenField(x, y);
2172
2173   redraw_mask |= REDRAW_FIELD;
2174 }
2175
2176 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2177 {
2178   int x,y;
2179
2180   for(x=0; x<size_x; x++)
2181     for(y=0; y<size_y; y++)
2182       DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
2183
2184   redraw_mask |= REDRAW_FIELD;
2185 }
2186
2187 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
2188 {
2189   int x, y;
2190
2191   ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
2192
2193   if (lev_fieldx < STD_LEV_FIELDX)
2194     xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
2195   if (lev_fieldy < STD_LEV_FIELDY)
2196     ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
2197
2198   xpos += MICRO_TILEX;
2199   ypos += MICRO_TILEY;
2200
2201   for(x=-1; x<=STD_LEV_FIELDX; x++)
2202   {
2203     for(y=-1; y<=STD_LEV_FIELDY; y++)
2204     {
2205       int lx = from_x + x, ly = from_y + y;
2206
2207       if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
2208         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2209                          Ur[lx][ly]);
2210       else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
2211         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2212                          BorderElement);
2213     }
2214   }
2215
2216   redraw_mask |= REDRAW_MICROLEVEL;
2217 }
2218
2219 #define MICROLABEL_EMPTY                0
2220 #define MICROLABEL_LEVEL_NAME           1
2221 #define MICROLABEL_CREATED_BY           2
2222 #define MICROLABEL_LEVEL_AUTHOR         3
2223 #define MICROLABEL_IMPORTED_FROM        4
2224 #define MICROLABEL_LEVEL_IMPORT_INFO    5
2225
2226 #define MAX_MICROLABEL_SIZE             (SXSIZE / FONT4_XSIZE)
2227
2228 static void DrawMicroLevelLabelExt(int mode)
2229 {
2230   char label_text[MAX_MICROLABEL_SIZE + 1];
2231
2232   ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
2233
2234   strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
2235                        mode == MICROLABEL_CREATED_BY ? "created by" :
2236                        mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
2237                        mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
2238                        mode == MICROLABEL_LEVEL_IMPORT_INFO ?
2239                        leveldir_current->imported_from : ""),
2240           MAX_MICROLABEL_SIZE);
2241   label_text[MAX_MICROLABEL_SIZE] = '\0';
2242
2243   if (strlen(label_text) > 0)
2244   {
2245     int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
2246     int lypos = MICROLABEL_YPOS;
2247
2248     DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
2249   }
2250
2251   redraw_mask |= REDRAW_MICROLEVEL;
2252 }
2253
2254 void DrawMicroLevel(int xpos, int ypos, boolean restart)
2255 {
2256   static unsigned long scroll_delay = 0;
2257   static unsigned long label_delay = 0;
2258   static int from_x, from_y, scroll_direction;
2259   static int label_state, label_counter;
2260
2261   if (restart)
2262   {
2263     from_x = from_y = 0;
2264     scroll_direction = MV_RIGHT;
2265     label_state = 1;
2266     label_counter = 0;
2267
2268     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2269     DrawMicroLevelLabelExt(label_state);
2270
2271     /* initialize delay counters */
2272     DelayReached(&scroll_delay, 0);
2273     DelayReached(&label_delay, 0);
2274
2275     return;
2276   }
2277
2278   /* scroll micro level, if needed */
2279   if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
2280       DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
2281   {
2282     switch (scroll_direction)
2283     {
2284       case MV_LEFT:
2285         if (from_x > 0)
2286           from_x--;
2287         else
2288           scroll_direction = MV_UP;
2289         break;
2290
2291       case MV_RIGHT:
2292         if (from_x < lev_fieldx - STD_LEV_FIELDX)
2293           from_x++;
2294         else
2295           scroll_direction = MV_DOWN;
2296         break;
2297
2298       case MV_UP:
2299         if (from_y > 0)
2300           from_y--;
2301         else
2302           scroll_direction = MV_RIGHT;
2303         break;
2304
2305       case MV_DOWN:
2306         if (from_y < lev_fieldy - STD_LEV_FIELDY)
2307           from_y++;
2308         else
2309           scroll_direction = MV_LEFT;
2310         break;
2311
2312       default:
2313         break;
2314     }
2315
2316     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2317   }
2318
2319   /* redraw micro level label, if needed */
2320   if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
2321       strcmp(level.author, ANONYMOUS_NAME) != 0 &&
2322       strcmp(level.author, leveldir_current->name) != 0 &&
2323       DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
2324   {
2325     int max_label_counter = 23;
2326
2327     if (leveldir_current->imported_from != NULL)
2328       max_label_counter += 14;
2329
2330     label_counter = (label_counter + 1) % max_label_counter;
2331     label_state = (label_counter >= 0 && label_counter <= 7 ?
2332                    MICROLABEL_LEVEL_NAME :
2333                    label_counter >= 9 && label_counter <= 12 ?
2334                    MICROLABEL_CREATED_BY :
2335                    label_counter >= 14 && label_counter <= 21 ?
2336                    MICROLABEL_LEVEL_AUTHOR :
2337                    label_counter >= 23 && label_counter <= 26 ?
2338                    MICROLABEL_IMPORTED_FROM :
2339                    label_counter >= 28 && label_counter <= 35 ?
2340                    MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2341     DrawMicroLevelLabelExt(label_state);
2342   }
2343 }
2344
2345 int REQ_in_range(int x, int y)
2346 {
2347   if (y > DY+249 && y < DY+278)
2348   {
2349     if (x > DX+1 && x < DX+48)
2350       return 1;
2351     else if (x > DX+51 && x < DX+98) 
2352       return 2;
2353   }
2354   return 0;
2355 }
2356
2357 #define MAX_REQUEST_LINES               13
2358 #define MAX_REQUEST_LINE_LEN            7
2359
2360 boolean Request(char *text, unsigned int req_state)
2361 {
2362   int mx, my, ty, result = -1;
2363   unsigned int old_door_state;
2364
2365 #if defined(PLATFORM_UNIX)
2366   /* pause network game while waiting for request to answer */
2367   if (options.network &&
2368       game_status == PLAYING &&
2369       req_state & REQUEST_WAIT_FOR)
2370     SendToServer_PausePlaying();
2371 #endif
2372
2373   old_door_state = GetDoorState();
2374
2375   UnmapAllGadgets();
2376
2377   CloseDoor(DOOR_CLOSE_1);
2378
2379   /* save old door content */
2380   BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2381              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2382              DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2383
2384   /* clear door drawing field */
2385   ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
2386
2387   /* write text for request */
2388   for(ty=0; ty < MAX_REQUEST_LINES; ty++)
2389   {
2390     char text_line[MAX_REQUEST_LINE_LEN + 1];
2391     int tx, tl, tc;
2392
2393     if (!*text)
2394       break;
2395
2396     for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
2397     {
2398       tc = *(text + tx);
2399       if (!tc || tc == ' ')
2400         break;
2401     }
2402
2403     if (!tl)
2404     { 
2405       text++; 
2406       ty--; 
2407       continue; 
2408     }
2409
2410     strncpy(text_line, text, tl);
2411     text_line[tl] = 0;
2412
2413     DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2414                 text_line, FS_SMALL, FC_YELLOW);
2415
2416     text += tl + (tc == ' ' ? 1 : 0);
2417   }
2418
2419   if (req_state & REQ_ASK)
2420   {
2421     MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2422     MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2423   }
2424   else if (req_state & REQ_CONFIRM)
2425   {
2426     MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2427   }
2428   else if (req_state & REQ_PLAYER)
2429   {
2430     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2431     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2432     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2433     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2434   }
2435
2436   /* copy request gadgets to door backbuffer */
2437   BlitBitmap(drawto, pix[PIX_DB_DOOR],
2438              DX, DY, DXSIZE, DYSIZE,
2439              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2440
2441   OpenDoor(DOOR_OPEN_1);
2442
2443 #if 0
2444   ClearEventQueue();
2445 #endif
2446
2447   if (!(req_state & REQUEST_WAIT_FOR))
2448     return(FALSE);
2449
2450   if (game_status != MAINMENU)
2451     InitAnimation();
2452
2453   button_status = MB_RELEASED;
2454
2455   request_gadget_id = -1;
2456
2457   while(result < 0)
2458   {
2459     if (PendingEvent())
2460     {
2461       Event event;
2462
2463       NextEvent(&event);
2464
2465       switch(event.type)
2466       {
2467         case EVENT_BUTTONPRESS:
2468         case EVENT_BUTTONRELEASE:
2469         case EVENT_MOTIONNOTIFY:
2470         {
2471           if (event.type == EVENT_MOTIONNOTIFY)
2472           {
2473             if (!PointerInWindow(window))
2474               continue; /* window and pointer are on different screens */
2475
2476             if (!button_status)
2477               continue;
2478
2479             motion_status = TRUE;
2480             mx = ((MotionEvent *) &event)->x;
2481             my = ((MotionEvent *) &event)->y;
2482           }
2483           else
2484           {
2485             motion_status = FALSE;
2486             mx = ((ButtonEvent *) &event)->x;
2487             my = ((ButtonEvent *) &event)->y;
2488             if (event.type == EVENT_BUTTONPRESS)
2489               button_status = ((ButtonEvent *) &event)->button;
2490             else
2491               button_status = MB_RELEASED;
2492           }
2493
2494           /* this sets 'request_gadget_id' */
2495           HandleGadgets(mx, my, button_status);
2496
2497           switch(request_gadget_id)
2498           {
2499             case TOOL_CTRL_ID_YES:
2500               result = TRUE;
2501               break;
2502             case TOOL_CTRL_ID_NO:
2503               result = FALSE;
2504               break;
2505             case TOOL_CTRL_ID_CONFIRM:
2506               result = TRUE | FALSE;
2507               break;
2508
2509             case TOOL_CTRL_ID_PLAYER_1:
2510               result = 1;
2511               break;
2512             case TOOL_CTRL_ID_PLAYER_2:
2513               result = 2;
2514               break;
2515             case TOOL_CTRL_ID_PLAYER_3:
2516               result = 3;
2517               break;
2518             case TOOL_CTRL_ID_PLAYER_4:
2519               result = 4;
2520               break;
2521
2522             default:
2523               break;
2524           }
2525
2526           break;
2527         }
2528
2529         case EVENT_KEYPRESS:
2530           switch(GetEventKey((KeyEvent *)&event, TRUE))
2531           {
2532             case KSYM_Return:
2533               result = 1;
2534               break;
2535
2536             case KSYM_Escape:
2537               result = 0;
2538               break;
2539
2540             default:
2541               break;
2542           }
2543           if (req_state & REQ_PLAYER)
2544             result = 0;
2545           break;
2546
2547         case EVENT_KEYRELEASE:
2548           ClearPlayerAction();
2549           break;
2550
2551         default:
2552           HandleOtherEvents(&event);
2553           break;
2554       }
2555     }
2556     else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2557     {
2558       int joy = AnyJoystick();
2559
2560       if (joy & JOY_BUTTON_1)
2561         result = 1;
2562       else if (joy & JOY_BUTTON_2)
2563         result = 0;
2564     }
2565
2566     DoAnimation();
2567
2568     /* don't eat all CPU time */
2569     Delay(10);
2570   }
2571
2572   if (game_status != MAINMENU)
2573     StopAnimation();
2574
2575   UnmapToolButtons();
2576
2577   if (!(req_state & REQ_STAY_OPEN))
2578   {
2579     CloseDoor(DOOR_CLOSE_1);
2580
2581     if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2582     {
2583       BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2584                  DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2585                  DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2586       OpenDoor(DOOR_OPEN_1);
2587     }
2588   }
2589
2590   RemapAllGadgets();
2591
2592 #if defined(PLATFORM_UNIX)
2593   /* continue network game after request */
2594   if (options.network &&
2595       game_status == PLAYING &&
2596       req_state & REQUEST_WAIT_FOR)
2597     SendToServer_ContinuePlaying();
2598 #endif
2599
2600   return(result);
2601 }
2602
2603 unsigned int OpenDoor(unsigned int door_state)
2604 {
2605   unsigned int new_door_state;
2606
2607   if (door_state & DOOR_COPY_BACK)
2608   {
2609     BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2610                DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2611                DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2612     door_state &= ~DOOR_COPY_BACK;
2613   }
2614
2615   new_door_state = MoveDoor(door_state);
2616
2617   return(new_door_state);
2618 }
2619
2620 unsigned int CloseDoor(unsigned int door_state)
2621 {
2622   unsigned int new_door_state;
2623
2624   BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2625              DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2626   BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2627              VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2628
2629   new_door_state = MoveDoor(door_state);
2630
2631   return(new_door_state);
2632 }
2633
2634 unsigned int GetDoorState()
2635 {
2636   return MoveDoor(DOOR_GET_STATE);
2637 }
2638
2639 unsigned int SetDoorState(unsigned int door_state)
2640 {
2641   return MoveDoor(door_state | DOOR_SET_STATE);
2642 }
2643
2644 unsigned int MoveDoor(unsigned int door_state)
2645 {
2646   static int door1 = DOOR_OPEN_1;
2647   static int door2 = DOOR_CLOSE_2;
2648   static unsigned long door_delay = 0;
2649   int x, start, stepsize = 2;
2650   unsigned long door_delay_value = stepsize * 5;
2651
2652   if (door_state == DOOR_GET_STATE)
2653     return(door1 | door2);
2654
2655   if (door_state & DOOR_SET_STATE)
2656   {
2657     if (door_state & DOOR_ACTION_1)
2658       door1 = door_state & DOOR_ACTION_1;
2659     if (door_state & DOOR_ACTION_2)
2660       door2 = door_state & DOOR_ACTION_2;
2661
2662     return(door1 | door2);
2663   }
2664
2665   if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2666     door_state &= ~DOOR_OPEN_1;
2667   else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2668     door_state &= ~DOOR_CLOSE_1;
2669   if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2670     door_state &= ~DOOR_OPEN_2;
2671   else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2672     door_state &= ~DOOR_CLOSE_2;
2673
2674   if (setup.quick_doors)
2675   {
2676     stepsize = 20;
2677     door_delay_value = 0;
2678     StopSound(SND_MENU_DOOR_OPENING);
2679     StopSound(SND_MENU_DOOR_CLOSING);
2680   }
2681
2682   if (door_state & DOOR_ACTION)
2683   {
2684     if (!(door_state & DOOR_NO_DELAY))
2685     {
2686       /* opening door sound has priority over simultaneously closing door */
2687       if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2688         PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2689       else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2690         PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2691     }
2692
2693     start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2694
2695     for(x=start; x<=DXSIZE; x+=stepsize)
2696     {
2697       Bitmap *bitmap = pix[PIX_DOOR];
2698       GC gc = bitmap->stored_clip_gc;
2699
2700       WaitUntilDelayReached(&door_delay, door_delay_value);
2701
2702       if (door_state & DOOR_ACTION_1)
2703       {
2704         int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2705         int j = (DXSIZE - i) / 3;
2706
2707         BlitBitmap(pix[PIX_DB_DOOR], drawto,
2708                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2709                    DXSIZE,DYSIZE - i/2, DX, DY);
2710
2711         ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2712
2713         SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2714         BlitBitmapMasked(bitmap, drawto,
2715                          DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2716                          DX + DXSIZE - i, DY + j);
2717         BlitBitmapMasked(bitmap, drawto,
2718                          DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2719                          DX + DXSIZE - i, DY + 140 + j);
2720         SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2721         BlitBitmapMasked(bitmap, drawto,
2722                          DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2723                          DX, DY);
2724         BlitBitmapMasked(bitmap, drawto,
2725                          DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2726                          DX, DY + 140 - j);
2727
2728         BlitBitmapMasked(bitmap, drawto,
2729                          DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2730                          DX, DY + 77 - j);
2731         BlitBitmapMasked(bitmap, drawto,
2732                          DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2733                          DX, DY + 203 - j);
2734         SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2735         BlitBitmapMasked(bitmap, drawto,
2736                          DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2737                          DX + DXSIZE - i, DY + 77 + j);
2738         BlitBitmapMasked(bitmap, drawto,
2739                          DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2740                          DX + DXSIZE - i, DY + 203 + j);
2741
2742         redraw_mask |= REDRAW_DOOR_1;
2743       }
2744
2745       if (door_state & DOOR_ACTION_2)
2746       {
2747         int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2748         int j = (VXSIZE - i) / 3;
2749
2750         BlitBitmap(pix[PIX_DB_DOOR], drawto,
2751                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2752                    VXSIZE, VYSIZE - i/2, VX, VY);
2753
2754         ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2755
2756         SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2757         BlitBitmapMasked(bitmap, drawto,
2758                          VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2759                          VX + VXSIZE-i, VY+j);
2760         SetClipOrigin(bitmap, gc,
2761                       VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2762         BlitBitmapMasked(bitmap, drawto,
2763                          VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2764                          VX, VY);
2765
2766         BlitBitmapMasked(bitmap, drawto,
2767                          VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2768                          i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2769         SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2770         BlitBitmapMasked(bitmap, drawto,
2771                          VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2772                          i, VYSIZE / 2 - j,
2773                          VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2774
2775         redraw_mask |= REDRAW_DOOR_2;
2776       }
2777
2778       BackToFront();
2779
2780       if (game_status == MAINMENU)
2781         DoAnimation();
2782     }
2783   }
2784
2785   if (setup.quick_doors)
2786   {
2787     StopSound(SND_MENU_DOOR_OPENING);
2788     StopSound(SND_MENU_DOOR_CLOSING);
2789   }
2790
2791   if (door_state & DOOR_ACTION_1)
2792     door1 = door_state & DOOR_ACTION_1;
2793   if (door_state & DOOR_ACTION_2)
2794     door2 = door_state & DOOR_ACTION_2;
2795
2796   return (door1 | door2);
2797 }
2798
2799 void DrawSpecialEditorDoor()
2800 {
2801   /* draw bigger toolbox window */
2802   BlitBitmap(pix[PIX_DOOR], drawto,
2803              DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2804
2805   redraw_mask |= REDRAW_ALL;
2806 }
2807
2808 void UndrawSpecialEditorDoor()
2809 {
2810   /* draw normal tape recorder window */
2811   BlitBitmap(pix[PIX_BACK], drawto,
2812              562, 344, 108, 56, EX - 4, EY - 12);
2813
2814   redraw_mask |= REDRAW_ALL;
2815 }
2816
2817 #ifndef TARGET_SDL
2818 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2819 {
2820   XImage *pixel_image;
2821   unsigned long pixel_value;
2822
2823   pixel_image = XGetImage(display, bitmap->drawable,
2824                           x, y, 1, 1, AllPlanes, ZPixmap);
2825   pixel_value = XGetPixel(pixel_image, 0, 0);
2826
2827   XDestroyImage(pixel_image);
2828
2829   return pixel_value;
2830 }
2831 #endif
2832
2833 /* ---------- new tool button stuff ---------------------------------------- */
2834
2835 /* graphic position values for tool buttons */
2836 #define TOOL_BUTTON_YES_XPOS            2
2837 #define TOOL_BUTTON_YES_YPOS            250
2838 #define TOOL_BUTTON_YES_GFX_YPOS        0
2839 #define TOOL_BUTTON_YES_XSIZE           46
2840 #define TOOL_BUTTON_YES_YSIZE           28
2841 #define TOOL_BUTTON_NO_XPOS             52
2842 #define TOOL_BUTTON_NO_YPOS             TOOL_BUTTON_YES_YPOS
2843 #define TOOL_BUTTON_NO_GFX_YPOS         TOOL_BUTTON_YES_GFX_YPOS
2844 #define TOOL_BUTTON_NO_XSIZE            TOOL_BUTTON_YES_XSIZE
2845 #define TOOL_BUTTON_NO_YSIZE            TOOL_BUTTON_YES_YSIZE
2846 #define TOOL_BUTTON_CONFIRM_XPOS        TOOL_BUTTON_YES_XPOS
2847 #define TOOL_BUTTON_CONFIRM_YPOS        TOOL_BUTTON_YES_YPOS
2848 #define TOOL_BUTTON_CONFIRM_GFX_YPOS    30
2849 #define TOOL_BUTTON_CONFIRM_XSIZE       96
2850 #define TOOL_BUTTON_CONFIRM_YSIZE       TOOL_BUTTON_YES_YSIZE
2851 #define TOOL_BUTTON_PLAYER_XSIZE        30
2852 #define TOOL_BUTTON_PLAYER_YSIZE        30
2853 #define TOOL_BUTTON_PLAYER_GFX_XPOS     5
2854 #define TOOL_BUTTON_PLAYER_GFX_YPOS     185
2855 #define TOOL_BUTTON_PLAYER_XPOS         (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2856 #define TOOL_BUTTON_PLAYER_YPOS         (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2857 #define TOOL_BUTTON_PLAYER1_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2858                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2859 #define TOOL_BUTTON_PLAYER2_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2860                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2861 #define TOOL_BUTTON_PLAYER3_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2862                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2863 #define TOOL_BUTTON_PLAYER4_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2864                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2865 #define TOOL_BUTTON_PLAYER1_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2866                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2867 #define TOOL_BUTTON_PLAYER2_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2868                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2869 #define TOOL_BUTTON_PLAYER3_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2870                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2871 #define TOOL_BUTTON_PLAYER4_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2872                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2873
2874 static struct
2875 {
2876   int xpos, ypos;
2877   int x, y;
2878   int width, height;
2879   int gadget_id;
2880   char *infotext;
2881 } toolbutton_info[NUM_TOOL_BUTTONS] =
2882 {
2883   {
2884     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_GFX_YPOS,
2885     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_YPOS,
2886     TOOL_BUTTON_YES_XSIZE,      TOOL_BUTTON_YES_YSIZE,
2887     TOOL_CTRL_ID_YES,
2888     "yes"
2889   },
2890   {
2891     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_GFX_YPOS,
2892     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_YPOS,
2893     TOOL_BUTTON_NO_XSIZE,       TOOL_BUTTON_NO_YSIZE,
2894     TOOL_CTRL_ID_NO,
2895     "no"
2896   },
2897   {
2898     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_GFX_YPOS,
2899     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_YPOS,
2900     TOOL_BUTTON_CONFIRM_XSIZE,  TOOL_BUTTON_CONFIRM_YSIZE,
2901     TOOL_CTRL_ID_CONFIRM,
2902     "confirm"
2903   },
2904   {
2905     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2906     TOOL_BUTTON_PLAYER1_XPOS,   TOOL_BUTTON_PLAYER1_YPOS,
2907     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2908     TOOL_CTRL_ID_PLAYER_1,
2909     "player 1"
2910   },
2911   {
2912     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2913     TOOL_BUTTON_PLAYER2_XPOS,   TOOL_BUTTON_PLAYER2_YPOS,
2914     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2915     TOOL_CTRL_ID_PLAYER_2,
2916     "player 2"
2917   },
2918   {
2919     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2920     TOOL_BUTTON_PLAYER3_XPOS,   TOOL_BUTTON_PLAYER3_YPOS,
2921     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2922     TOOL_CTRL_ID_PLAYER_3,
2923     "player 3"
2924   },
2925   {
2926     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2927     TOOL_BUTTON_PLAYER4_XPOS,   TOOL_BUTTON_PLAYER4_YPOS,
2928     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2929     TOOL_CTRL_ID_PLAYER_4,
2930     "player 4"
2931   }
2932 };
2933
2934 void CreateToolButtons()
2935 {
2936   int i;
2937
2938   for (i=0; i<NUM_TOOL_BUTTONS; i++)
2939   {
2940     Bitmap *gd_bitmap = pix[PIX_DOOR];
2941     Bitmap *deco_bitmap = None;
2942     int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2943     struct GadgetInfo *gi;
2944     unsigned long event_mask;
2945     int gd_xoffset, gd_yoffset;
2946     int gd_x1, gd_x2, gd_y;
2947     int id = i;
2948
2949     event_mask = GD_EVENT_RELEASED;
2950
2951     gd_xoffset = toolbutton_info[i].xpos;
2952     gd_yoffset = toolbutton_info[i].ypos;
2953     gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2954     gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2955     gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2956
2957     if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2958     {
2959       getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2960                            &deco_bitmap, &deco_x, &deco_y);
2961       deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2962       deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2963     }
2964
2965     gi = CreateGadget(GDI_CUSTOM_ID, id,
2966                       GDI_INFO_TEXT, toolbutton_info[i].infotext,
2967                       GDI_X, DX + toolbutton_info[i].x,
2968                       GDI_Y, DY + toolbutton_info[i].y,
2969                       GDI_WIDTH, toolbutton_info[i].width,
2970                       GDI_HEIGHT, toolbutton_info[i].height,
2971                       GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2972                       GDI_STATE, GD_BUTTON_UNPRESSED,
2973                       GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2974                       GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2975                       GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2976                       GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2977                       GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2978                       GDI_DECORATION_SHIFTING, 1, 1,
2979                       GDI_EVENT_MASK, event_mask,
2980                       GDI_CALLBACK_ACTION, HandleToolButtons,
2981                       GDI_END);
2982
2983     if (gi == NULL)
2984       Error(ERR_EXIT, "cannot create gadget");
2985
2986     tool_gadget[id] = gi;
2987   }
2988 }
2989
2990 static void UnmapToolButtons()
2991 {
2992   int i;
2993
2994   for (i=0; i<NUM_TOOL_BUTTONS; i++)
2995     UnmapGadget(tool_gadget[i]);
2996 }
2997
2998 static void HandleToolButtons(struct GadgetInfo *gi)
2999 {
3000   request_gadget_id = gi->custom_id;
3001 }
3002
3003 int get_next_element(int element)
3004 {
3005   switch(element)
3006   {
3007     case EL_QUICKSAND_FILLING:          return EL_QUICKSAND_FULL;
3008     case EL_QUICKSAND_EMPTYING:         return EL_QUICKSAND_EMPTY;
3009     case EL_MAGIC_WALL_FILLING:         return EL_MAGIC_WALL_FULL;
3010     case EL_MAGIC_WALL_EMPTYING:        return EL_MAGIC_WALL_ACTIVE;
3011     case EL_BD_MAGIC_WALL_FILLING:      return EL_BD_MAGIC_WALL_FULL;
3012     case EL_BD_MAGIC_WALL_EMPTYING:     return EL_BD_MAGIC_WALL_ACTIVE;
3013     case EL_AMOEBA_DRIPPING:            return EL_AMOEBA_WET;
3014
3015     default:                            return element;
3016   }
3017 }
3018
3019 int el2gfx_OLD(int element)
3020 {
3021   switch(element)
3022   {
3023     case EL_EMPTY:                      return -1;
3024     case EL_SAND:                       return GFX_ERDREICH;
3025     case EL_WALL:                       return GFX_MAUERWERK;
3026     case EL_WALL_CRUMBLED:              return GFX_FELSBODEN;
3027     case EL_ROCK:                       return GFX_FELSBROCKEN;
3028     case EL_EMERALD:                    return GFX_EDELSTEIN;
3029     case EL_EXIT_CLOSED:                return GFX_AUSGANG_ZU;
3030     case EL_EXIT_OPENING:               return GFX_AUSGANG_ACT;
3031     case EL_EXIT_OPEN:                  return GFX_AUSGANG_AUF;
3032     case EL_SP_EXIT_OPEN:               return GFX_SP_EXIT;
3033     case EL_PLAYER:                     return GFX_SPIELFIGUR;
3034     case EL_PLAYER1:                    return GFX_SPIELER1;
3035     case EL_PLAYER2:                    return GFX_SPIELER2;
3036     case EL_PLAYER3:                    return GFX_SPIELER3;
3037     case EL_PLAYER4:                    return GFX_SPIELER4;
3038     case EL_BUG:                        return GFX_KAEFER;
3039     case EL_BUG_RIGHT:                  return GFX_KAEFER_RIGHT;
3040     case EL_BUG_UP:                     return GFX_KAEFER_UP;
3041     case EL_BUG_LEFT:                   return GFX_KAEFER_LEFT;
3042     case EL_BUG_DOWN:                   return GFX_KAEFER_DOWN;
3043     case EL_SPACESHIP:                  return GFX_FLIEGER;
3044     case EL_SPACESHIP_RIGHT:            return GFX_FLIEGER_RIGHT;
3045     case EL_SPACESHIP_UP:               return GFX_FLIEGER_UP;
3046     case EL_SPACESHIP_LEFT:             return GFX_FLIEGER_LEFT;
3047     case EL_SPACESHIP_DOWN:             return GFX_FLIEGER_DOWN;
3048     case EL_BD_BUTTERFLY:               return GFX_BUTTERFLY;
3049     case EL_BD_BUTTERFLY_RIGHT:         return GFX_BUTTERFLY_RIGHT;
3050     case EL_BD_BUTTERFLY_UP:            return GFX_BUTTERFLY_UP;
3051     case EL_BD_BUTTERFLY_LEFT:          return GFX_BUTTERFLY_LEFT;
3052     case EL_BD_BUTTERFLY_DOWN:          return GFX_BUTTERFLY_DOWN;
3053     case EL_BD_FIREFLY:                 return GFX_FIREFLY;
3054     case EL_BD_FIREFLY_RIGHT:           return GFX_FIREFLY_RIGHT;
3055     case EL_BD_FIREFLY_UP:              return GFX_FIREFLY_UP;
3056     case EL_BD_FIREFLY_LEFT:            return GFX_FIREFLY_LEFT;
3057     case EL_BD_FIREFLY_DOWN:            return GFX_FIREFLY_DOWN;
3058     case EL_YAMYAM:                     return GFX_MAMPFER;
3059     case EL_ROBOT:                      return GFX_ROBOT;
3060     case EL_STEELWALL:                  return GFX_BETON;
3061     case EL_DIAMOND:                    return GFX_DIAMANT;
3062     case EL_QUICKSAND_EMPTY:            return GFX_MORAST_LEER;
3063     case EL_QUICKSAND_FULL:             return GFX_MORAST_VOLL;
3064     case EL_QUICKSAND_EMPTYING:         return GFX_MORAST_LEER;
3065     case EL_AMOEBA_DROP:                return GFX_TROPFEN;
3066     case EL_BOMB:                       return GFX_BOMBE;
3067     case EL_MAGIC_WALL:                 return GFX_MAGIC_WALL_OFF;
3068     case EL_MAGIC_WALL_ACTIVE:          return GFX_MAGIC_WALL_EMPTY;
3069     case EL_MAGIC_WALL_EMPTYING:        return GFX_MAGIC_WALL_EMPTY;
3070     case EL_MAGIC_WALL_FULL:            return GFX_MAGIC_WALL_FULL;
3071     case EL_MAGIC_WALL_DEAD:            return GFX_MAGIC_WALL_DEAD;
3072     case EL_ACID:                       return GFX_SALZSAEURE;
3073     case EL_AMOEBA_DEAD:                return GFX_AMOEBE_TOT;
3074     case EL_AMOEBA_WET:                 return GFX_AMOEBE_NASS;
3075     case EL_AMOEBA_DRY:                 return GFX_AMOEBE_NORM;
3076     case EL_AMOEBA_FULL:                return GFX_AMOEBE_VOLL;
3077     case EL_BD_AMOEBA:                  return GFX_AMOEBE_BD;
3078     case EL_AMOEBA_TO_DIAMOND:          return GFX_AMOEBA2DIAM;
3079     case EL_AMOEBA_DRIPPING:            return GFX_AMOEBE_NASS;
3080     case EL_NUT:                        return GFX_KOKOSNUSS;
3081     case EL_GAMEOFLIFE:                 return GFX_LIFE;
3082     case EL_BIOMAZE:                    return GFX_LIFE_ASYNC;
3083     case EL_DYNAMITE_ACTIVE:            return GFX_DYNAMIT;
3084     case EL_STONEBLOCK:                 return GFX_BADEWANNE;
3085     case EL_ACIDPOOL_TOPLEFT:           return GFX_BADEWANNE1;
3086     case EL_ACIDPOOL_TOPRIGHT:          return GFX_BADEWANNE2;
3087     case EL_ACIDPOOL_BOTTOMLEFT:        return GFX_BADEWANNE3;
3088     case EL_ACIDPOOL_BOTTOM:            return GFX_BADEWANNE4;
3089     case EL_ACIDPOOL_BOTTOMRIGHT:       return GFX_BADEWANNE5;
3090     case EL_ROBOT_WHEEL:                return GFX_ABLENK_AUS;
3091     case EL_ROBOT_WHEEL_ACTIVE:         return GFX_ABLENK_EIN;
3092     case EL_KEY1:                       return GFX_SCHLUESSEL1;
3093     case EL_KEY2:                       return GFX_SCHLUESSEL2;
3094     case EL_KEY3:                       return GFX_SCHLUESSEL3;
3095     case EL_KEY4:                       return GFX_SCHLUESSEL4;
3096     case EL_GATE1:                      return GFX_PFORTE1;
3097     case EL_GATE2:                      return GFX_PFORTE2;
3098     case EL_GATE3:                      return GFX_PFORTE3;
3099     case EL_GATE4:                      return GFX_PFORTE4;
3100     case EL_GATE1_GRAY:                 return GFX_PFORTE1X;
3101     case EL_GATE2_GRAY:                 return GFX_PFORTE2X;
3102     case EL_GATE3_GRAY:                 return GFX_PFORTE3X;
3103     case EL_GATE4_GRAY:                 return GFX_PFORTE4X;
3104     case EL_DYNAMITE:                   return GFX_DYNAMIT_AUS;
3105     case EL_PACMAN:                     return GFX_PACMAN;
3106     case EL_PACMAN_RIGHT:               return GFX_PACMAN_RIGHT;
3107     case EL_PACMAN_UP:                  return GFX_PACMAN_UP;
3108     case EL_PACMAN_LEFT:                return GFX_PACMAN_LEFT;
3109     case EL_PACMAN_DOWN:                return GFX_PACMAN_DOWN;
3110     case EL_INVISIBLE_WALL:             return GFX_UNSICHTBAR;
3111     case EL_INVISIBLE_WALL_ACTIVE:      return GFX_UNSICHTBAR_ON;
3112     case EL_WALL_EMERALD:               return GFX_ERZ_EDEL;
3113     case EL_WALL_DIAMOND:               return GFX_ERZ_DIAM;
3114     case EL_LAMP:                       return GFX_BIRNE_AUS;
3115     case EL_LAMP_ACTIVE:                return GFX_BIRNE_EIN;
3116     case EL_TIME_ORB_FULL:              return GFX_ZEIT_VOLL;
3117     case EL_TIME_ORB_EMPTY:             return GFX_ZEIT_LEER;
3118     case EL_WALL_GROWING:               return GFX_MAUER_LEBT;
3119     case EL_WALL_GROWING_X:             return GFX_MAUER_X;
3120     case EL_WALL_GROWING_Y:             return GFX_MAUER_Y;
3121     case EL_WALL_GROWING_XY:            return GFX_MAUER_XY;
3122     case EL_BD_DIAMOND:                 return GFX_EDELSTEIN_BD;
3123     case EL_EMERALD_YELLOW:             return GFX_EDELSTEIN_GELB;
3124     case EL_EMERALD_RED:                return GFX_EDELSTEIN_ROT;
3125     case EL_EMERALD_PURPLE:             return GFX_EDELSTEIN_LILA;
3126     case EL_WALL_BD_DIAMOND:            return GFX_ERZ_EDEL_BD;
3127     case EL_WALL_EMERALD_YELLOW:        return GFX_ERZ_EDEL_GELB;
3128     case EL_WALL_EMERALD_RED:           return GFX_ERZ_EDEL_ROT;
3129     case EL_WALL_EMERALD_PURPLE:        return GFX_ERZ_EDEL_LILA;
3130     case EL_DARK_YAMYAM:                return GFX_MAMPFER2;
3131     case EL_BD_MAGIC_WALL:              return GFX_MAGIC_WALL_BD_OFF;
3132     case EL_BD_MAGIC_WALL_ACTIVE:       return GFX_MAGIC_WALL_BD_EMPTY;
3133     case EL_BD_MAGIC_WALL_EMPTYING:     return GFX_MAGIC_WALL_BD_EMPTY;
3134     case EL_BD_MAGIC_WALL_FULL:         return GFX_MAGIC_WALL_BD_FULL;
3135     case EL_BD_MAGIC_WALL_DEAD:         return GFX_MAGIC_WALL_BD_DEAD;
3136     case EL_DYNABOMB_ACTIVE_1:          return GFX_DYNABOMB;
3137     case EL_DYNABOMB_ACTIVE_2:          return GFX_DYNABOMB;
3138     case EL_DYNABOMB_ACTIVE_3:          return GFX_DYNABOMB;
3139     case EL_DYNABOMB_ACTIVE_4:          return GFX_DYNABOMB;
3140     case EL_DYNABOMB_NR:                return GFX_DYNABOMB_NR;
3141     case EL_DYNABOMB_SZ:                return GFX_DYNABOMB_SZ;
3142     case EL_DYNABOMB_XL:                return GFX_DYNABOMB_XL;
3143     case EL_SOKOBAN_OBJECT:             return GFX_SOKOBAN_OBJEKT;
3144     case EL_SOKOBAN_FIELD_EMPTY:        return GFX_SOKOBAN_FELD_LEER;
3145     case EL_SOKOBAN_FIELD_FULL:         return GFX_SOKOBAN_FELD_VOLL;
3146     case EL_MOLE:                       return GFX_MOLE;
3147     case EL_PENGUIN:                    return GFX_PINGUIN;
3148     case EL_PIG:                        return GFX_SCHWEIN;
3149     case EL_DRAGON:                     return GFX_DRACHE;
3150     case EL_SATELLITE:                  return GFX_SONDE;
3151     case EL_ARROW_BLUE_LEFT:            return GFX_PFEIL_LEFT;
3152     case EL_ARROW_BLUE_RIGHT:           return GFX_PFEIL_RIGHT;
3153     case EL_ARROW_BLUE_UP:              return GFX_PFEIL_UP;
3154     case EL_ARROW_BLUE_DOWN:            return GFX_PFEIL_DOWN;
3155     case EL_SPEED_PILL:                 return GFX_SPEED_PILL;
3156     case EL_SP_TERMINAL_ACTIVE:         return GFX_SP_TERMINAL;
3157     case EL_SP_BUGGY_BASE_ACTIVE:       return GFX_SP_BUG_ACTIVE;
3158     case EL_SP_ZONK:                    return GFX_SP_ZONK;
3159       /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
3160     case EL_INVISIBLE_STEELWALL:        return GFX_INVISIBLE_STEEL;
3161     case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
3162     case EL_BLACK_ORB:                  return GFX_BLACK_ORB;
3163     case EL_EM_GATE1:                   return GFX_EM_GATE_1;
3164     case EL_EM_GATE2:                   return GFX_EM_GATE_2;
3165     case EL_EM_GATE3:                   return GFX_EM_GATE_3;
3166     case EL_EM_GATE4:                   return GFX_EM_GATE_4;
3167     case EL_EM_GATE1_GRAY:              return GFX_EM_GATE_1X;
3168     case EL_EM_GATE2_GRAY:              return GFX_EM_GATE_2X;
3169     case EL_EM_GATE3_GRAY:              return GFX_EM_GATE_3X;
3170     case EL_EM_GATE4_GRAY:              return GFX_EM_GATE_4X;
3171     case EL_EM_KEY1_FILE:               return GFX_EM_KEY_1;
3172     case EL_EM_KEY2_FILE:               return GFX_EM_KEY_2;
3173     case EL_EM_KEY3_FILE:               return GFX_EM_KEY_3;
3174     case EL_EM_KEY4_FILE:               return GFX_EM_KEY_4;
3175     case EL_EM_KEY1:                    return GFX_EM_KEY_1;
3176     case EL_EM_KEY2:                    return GFX_EM_KEY_2;
3177     case EL_EM_KEY3:                    return GFX_EM_KEY_3;
3178     case EL_EM_KEY4:                    return GFX_EM_KEY_4;
3179     case EL_PEARL:                      return GFX_PEARL;
3180     case EL_CRYSTAL:                    return GFX_CRYSTAL;
3181     case EL_WALL_PEARL:                 return GFX_WALL_PEARL;
3182     case EL_WALL_CRYSTAL:               return GFX_WALL_CRYSTAL;
3183     case EL_DOOR_WHITE:                 return GFX_DOOR_WHITE;
3184     case EL_DOOR_WHITE_GRAY:            return GFX_DOOR_WHITE_GRAY;
3185     case EL_KEY_WHITE:                  return GFX_KEY_WHITE;
3186     case EL_SHIELD_NORMAL:              return GFX_SHIELD_PASSIVE;
3187     case EL_SHIELD_DEADLY:              return GFX_SHIELD_ACTIVE;
3188     case EL_EXTRA_TIME:                 return GFX_EXTRA_TIME;
3189     case EL_SWITCHGATE_OPEN:            return GFX_SWITCHGATE_OPEN;
3190     case EL_SWITCHGATE_CLOSED:          return GFX_SWITCHGATE_CLOSED;
3191     case EL_SWITCHGATE_SWITCH_UP:       return GFX_SWITCHGATE_SWITCH_1;
3192     case EL_SWITCHGATE_SWITCH_DOWN:     return GFX_SWITCHGATE_SWITCH_2;
3193     case EL_CONVEYOR_BELT1_LEFT:        return GFX_BELT1_LEFT;
3194     case EL_CONVEYOR_BELT1_MIDDLE:      return GFX_BELT1_MIDDLE;
3195     case EL_CONVEYOR_BELT1_RIGHT:       return GFX_BELT1_RIGHT;
3196     case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
3197     case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
3198     case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
3199     case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
3200     case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
3201     case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
3202     case EL_CONVEYOR_BELT2_LEFT:        return GFX_BELT2_LEFT;
3203     case EL_CONVEYOR_BELT2_MIDDLE:      return GFX_BELT2_MIDDLE;
3204     case EL_CONVEYOR_BELT2_RIGHT:       return GFX_BELT2_RIGHT;
3205     case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
3206     case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
3207     case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
3208     case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
3209     case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
3210     case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
3211     case EL_CONVEYOR_BELT3_LEFT:        return GFX_BELT3_LEFT;
3212     case EL_CONVEYOR_BELT3_MIDDLE:      return GFX_BELT3_MIDDLE;
3213     case EL_CONVEYOR_BELT3_RIGHT:       return GFX_BELT3_RIGHT;
3214     case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
3215     case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
3216     case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
3217     case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
3218     case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
3219     case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
3220     case EL_CONVEYOR_BELT4_LEFT:        return GFX_BELT4_LEFT;
3221     case EL_CONVEYOR_BELT4_MIDDLE:      return GFX_BELT4_MIDDLE;
3222     case EL_CONVEYOR_BELT4_RIGHT:       return GFX_BELT4_RIGHT;
3223     case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
3224     case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
3225     case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
3226     case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
3227     case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
3228     case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
3229     case EL_LANDMINE:                   return GFX_LANDMINE;
3230     case EL_ENVELOPE:                   return GFX_ENVELOPE;
3231     case EL_LIGHT_SWITCH:               return GFX_LIGHT_SWITCH_OFF;
3232     case EL_LIGHT_SWITCH_ACTIVE:        return GFX_LIGHT_SWITCH_ON;
3233     case EL_SIGN_EXCLAMATION:           return GFX_SIGN_EXCLAMATION;
3234     case EL_SIGN_RADIOACTIVITY:         return GFX_SIGN_RADIOACTIVITY;
3235     case EL_SIGN_STOP:                  return GFX_SIGN_STOP;
3236     case EL_SIGN_WHEELCHAIR:            return GFX_SIGN_WHEELCHAIR;
3237     case EL_SIGN_PARKING:               return GFX_SIGN_PARKING;
3238     case EL_SIGN_ONEWAY:                return GFX_SIGN_ONEWAY;
3239     case EL_SIGN_HEART:                 return GFX_SIGN_HEART;
3240     case EL_SIGN_TRIANGLE:              return GFX_SIGN_TRIANGLE;
3241     case EL_SIGN_ROUND:                 return GFX_SIGN_ROUND;
3242     case EL_SIGN_EXIT:                  return GFX_SIGN_EXIT;
3243     case EL_SIGN_YINYANG:               return GFX_SIGN_YINYANG;
3244     case EL_SIGN_OTHER:                 return GFX_SIGN_OTHER;
3245     case EL_MOLE_LEFT:                  return GFX_MOLE_LEFT;
3246     case EL_MOLE_RIGHT:                 return GFX_MOLE_RIGHT;
3247     case EL_MOLE_UP:                    return GFX_MOLE_UP;
3248     case EL_MOLE_DOWN:                  return GFX_MOLE_DOWN;
3249     case EL_STEELWALL_SLANTED:          return GFX_STEEL_SLANTED;
3250     case EL_INVISIBLE_SAND:             return GFX_SAND_INVISIBLE;
3251     case EL_INVISIBLE_SAND_ACTIVE:      return GFX_SAND_INVISIBLE_ON;
3252     case EL_DX_UNKNOWN_15:              return GFX_DX_UNKNOWN_15;
3253     case EL_DX_UNKNOWN_42:              return GFX_DX_UNKNOWN_42;
3254     case EL_TIMEGATE_OPEN:              return GFX_TIMEGATE_OPEN;
3255     case EL_TIMEGATE_CLOSED:            return GFX_TIMEGATE_CLOSED;
3256     case EL_TIMEGATE_SWITCH_ACTIVE:     return GFX_TIMEGATE_SWITCH;
3257     case EL_TIMEGATE_SWITCH:            return GFX_TIMEGATE_SWITCH;
3258     case EL_BALLOON:                    return GFX_BALLOON;
3259     case EL_BALLOON_SEND_LEFT:          return GFX_BALLOON_SEND_LEFT;
3260     case EL_BALLOON_SEND_RIGHT:         return GFX_BALLOON_SEND_RIGHT;
3261     case EL_BALLOON_SEND_UP:            return GFX_BALLOON_SEND_UP;
3262     case EL_BALLOON_SEND_DOWN:          return GFX_BALLOON_SEND_DOWN;
3263     case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
3264     case EL_EMC_STEELWALL1:             return GFX_EMC_STEEL_WALL_1;
3265     case EL_EMC_STEELWALL2:             return GFX_EMC_STEEL_WALL_2;
3266     case EL_EMC_STEELWALL3:             return GFX_EMC_STEEL_WALL_3;
3267     case EL_EMC_STEELWALL4:             return GFX_EMC_STEEL_WALL_4;
3268     case EL_EMC_WALL_PILLAR_UPPER:      return GFX_EMC_WALL_1;
3269     case EL_EMC_WALL_PILLAR_MIDDLE:     return GFX_EMC_WALL_2;
3270     case EL_EMC_WALL_PILLAR_LOWER:      return GFX_EMC_WALL_3;
3271     case EL_EMC_WALL4:                  return GFX_EMC_WALL_4;
3272     case EL_EMC_WALL5:                  return GFX_EMC_WALL_5;
3273     case EL_EMC_WALL6:                  return GFX_EMC_WALL_6;
3274     case EL_EMC_WALL7:                  return GFX_EMC_WALL_7;
3275     case EL_EMC_WALL8:                  return GFX_EMC_WALL_8;
3276     case EL_TUBE_ALL:                   return GFX_TUBE_CROSS;
3277     case EL_TUBE_VERTICAL:              return GFX_TUBE_VERTICAL;
3278     case EL_TUBE_HORIZONTAL:            return GFX_TUBE_HORIZONTAL;
3279     case EL_TUBE_VERTICAL_LEFT:         return GFX_TUBE_VERT_LEFT;
3280     case EL_TUBE_VERTICAL_RIGHT:        return GFX_TUBE_VERT_RIGHT;
3281     case EL_TUBE_HORIZONTAL_UP:         return GFX_TUBE_HORIZ_UP;
3282     case EL_TUBE_HORIZONTAL_DOWN:       return GFX_TUBE_HORIZ_DOWN;
3283     case EL_TUBE_LEFT_UP:               return GFX_TUBE_LEFT_UP;
3284     case EL_TUBE_LEFT_DOWN:             return GFX_TUBE_LEFT_DOWN;
3285     case EL_TUBE_RIGHT_UP:              return GFX_TUBE_RIGHT_UP;
3286     case EL_TUBE_RIGHT_DOWN:            return GFX_TUBE_RIGHT_DOWN;
3287     case EL_SPRING:                     return GFX_SPRING;
3288     case EL_SPRING_MOVING:              return GFX_SPRING;
3289     case EL_TRAP:                       return GFX_TRAP_INACTIVE;
3290     case EL_TRAP_ACTIVE:                return GFX_TRAP_ACTIVE;
3291     case EL_BD_WALL:                    return GFX_BD_WALL;
3292     case EL_BD_ROCK:                    return GFX_BD_ROCK;
3293     case EL_DX_SUPABOMB:                return GFX_DX_SUPABOMB;
3294     case EL_SP_MURPHY_CLONE:            return GFX_SP_MURPHY_CLONE;
3295
3296     default:
3297     {
3298       if (IS_CHAR(element))
3299         return GFX_CHAR_START + (element - EL_CHAR_START);
3300       else if (element >= EL_SP_START && element <= EL_SP_END)
3301       {
3302         int nr_element = element - EL_SP_START;
3303         int gfx_per_line = 8;
3304         int nr_graphic =
3305           (nr_element / gfx_per_line) * SP_PER_LINE +
3306           (nr_element % gfx_per_line);
3307
3308         return GFX_START_ROCKSSP + nr_graphic;
3309       }
3310       else
3311         return -1;
3312     }
3313   }
3314 }
3315
3316 int el2gfx(int element)
3317 {
3318   int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3319
3320 #if DEBUG
3321   int graphic_OLD = el2gfx_OLD(element);
3322
3323   if (element >= MAX_ELEMENTS)
3324   {
3325     Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
3326   }
3327
3328   if (graphic_NEW != graphic_OLD)
3329   {
3330     Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
3331           graphic_NEW, graphic_OLD);
3332   }
3333 #endif
3334
3335   return graphic_NEW;
3336 }
3337
3338 int el2img(int element)
3339 {
3340   switch(element)
3341   {
3342     case EL_BD_BUTTERFLY:       return IMG_BD_BUTTERFLY;
3343     case EL_BD_FIREFLY:         return IMG_BD_FIREFLY;
3344     case EL_SP_ELECTRON:        return IMG_SP_ELECTRON;
3345
3346     default:
3347       break;
3348   }
3349
3350   return IMG_EMPTY_SPACE;
3351 }
3352
3353 int el_dir2img(int element, int direction)
3354 {
3355   if (element_info[element].has_direction_graphic[GFX_ACTION_DEFAULT])
3356   {
3357     int i = LOG_MV_DIR(direction);
3358
3359     return element_info[element].direction_graphic[GFX_ACTION_DEFAULT][i];
3360   }
3361   else
3362     return el2img(element);
3363 }