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