rnd-20020519-2-src
[rocksndiamonds.git] / src / tools.c
1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back!               *
3 *----------------------------------------------------------*
4 * (c) 1995-2001 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     phase = (FrameCounter % (delay * max_anim_frames)) / delay;
697     phase = (phase < frames ? phase : max_anim_frames - phase);
698   }
699   else
700     phase = (FrameCounter % (delay * frames)) / delay;
701
702   if (mode == ANIM_REVERSE)
703     phase = -phase;
704
705   return(phase);
706 }
707
708 void DrawGraphicAnimationExt(int x, int y, int graphic,
709                              int frames, int delay, int mode, int mask_mode)
710 {
711   int phase = getGraphicAnimationPhase(frames, delay, mode);
712
713   if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
714   {
715     if (mask_mode == USE_MASKING)
716       DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
717     else
718       DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
719   }
720 }
721
722 void DrawGraphicAnimation(int x, int y, int graphic,
723                           int frames, int delay, int mode)
724 {
725   DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
726 }
727
728 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
729                                   int frames, int delay, int mode)
730 {
731   DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
732 }
733
734 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
735                                                 int sxx, int syy,
736                                                 int graphic,
737                                                 int frames, int delay,
738                                                 int mode)
739 {
740   int phase = getGraphicAnimationPhase(frames, delay, mode);
741
742   DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
743 }
744
745 void getGraphicSource(int graphic, int *bitmap_nr, int *x, int *y)
746 {
747   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
748   {
749     graphic -= GFX_START_ROCKSSCREEN;
750     *bitmap_nr = PIX_BACK;
751     *x = SX + (graphic % GFX_PER_LINE) * TILEX;
752     *y = SY + (graphic / GFX_PER_LINE) * TILEY;
753   }
754   else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
755   {
756     graphic -= GFX_START_ROCKSHEROES;
757     *bitmap_nr = PIX_HEROES;
758     *x = (graphic % HEROES_PER_LINE) * TILEX;
759     *y = (graphic / HEROES_PER_LINE) * TILEY;
760   }
761   else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
762   {
763     graphic -= GFX_START_ROCKSSP;
764     *bitmap_nr = PIX_SP;
765     *x = (graphic % SP_PER_LINE) * TILEX;
766     *y = (graphic / SP_PER_LINE) * TILEY;
767   }
768   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
769   {
770     graphic -= GFX_START_ROCKSDC;
771     *bitmap_nr = PIX_DC;
772     *x = (graphic % DC_PER_LINE) * TILEX;
773     *y = (graphic / DC_PER_LINE) * TILEY;
774   }
775   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
776   {
777     graphic -= GFX_START_ROCKSMORE;
778     *bitmap_nr = PIX_MORE;
779     *x = (graphic % MORE_PER_LINE) * TILEX;
780     *y = (graphic / MORE_PER_LINE) * TILEY;
781   }
782   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
783   {
784     graphic -= GFX_START_ROCKSFONT;
785     *bitmap_nr = PIX_BIGFONT;
786     *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
787     *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
788           FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
789   }
790   else
791   {
792     *bitmap_nr = PIX_SP;
793     *x = 0;
794     *y = 0;
795   }
796 }
797
798 void DrawGraphic(int x, int y, int graphic)
799 {
800 #if DEBUG
801   if (!IN_SCR_FIELD(x,y))
802   {
803     printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
804     printf("DrawGraphic(): This should never happen!\n");
805     return;
806   }
807 #endif
808
809   DrawGraphicExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
810   MarkTileDirty(x,y);
811 }
812
813 void DrawGraphicExt(DrawBuffer *bitmap, int x, int y, int graphic)
814 {
815   int bitmap_nr;
816   int src_x, src_y;
817
818   getGraphicSource(graphic, &bitmap_nr, &src_x, &src_y);
819   BlitBitmap(pix[bitmap_nr], bitmap, src_x, src_y, TILEX, TILEY, x, y);
820 }
821
822 void DrawGraphicThruMask(int x, int y, int graphic)
823 {
824 #if DEBUG
825   if (!IN_SCR_FIELD(x,y))
826   {
827     printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
828     printf("DrawGraphicThruMask(): This should never happen!\n");
829     return;
830   }
831 #endif
832
833   DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
834   MarkTileDirty(x,y);
835 }
836
837 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
838 {
839   int tile = graphic;
840   int bitmap_nr;
841   int src_x, src_y;
842   Bitmap *src_bitmap;
843   GC drawing_gc;
844
845   if (graphic == GFX_LEERRAUM)
846     return;
847
848   getGraphicSource(graphic, &bitmap_nr, &src_x, &src_y);
849   src_bitmap = pix[bitmap_nr];
850   drawing_gc = pix[bitmap_nr]->stored_clip_gc;
851
852   if (tile_clipmask[tile] != None)
853   {
854     SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
855     SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
856     BlitBitmapMasked(src_bitmap, d,
857                      src_x, src_y, TILEX, TILEY, dest_x, dest_y);
858   }
859   else
860   {
861 #if DEBUG
862 #ifndef TARGET_SDL
863     printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
864 #endif
865 #endif
866
867     SetClipOrigin(src_bitmap, drawing_gc, dest_x-src_x, dest_y-src_y);
868     BlitBitmapMasked(src_bitmap, d,
869                      src_x, src_y, TILEX, TILEY, dest_x, dest_y);
870   }
871 }
872
873 void DrawMiniGraphic(int x, int y, int graphic)
874 {
875   DrawMiniGraphicExt(drawto, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
876   MarkTileDirty(x/2, y/2);
877 }
878
879 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
880 {
881   if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
882   {
883     graphic -= GFX_START_ROCKSSCREEN;
884     *bitmap = pix[PIX_BACK];
885     *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
886     *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
887   }
888   else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
889   {
890     graphic -= GFX_START_ROCKSSP;
891     graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
892     *bitmap = pix[PIX_SP];
893     *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
894     *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
895   }
896   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
897   {
898     graphic -= GFX_START_ROCKSDC;
899     *bitmap = pix[PIX_DC];
900     *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
901     *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
902   }
903   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
904   {
905     graphic -= GFX_START_ROCKSMORE;
906     *bitmap = pix[PIX_MORE];
907     *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
908     *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
909   }
910   else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
911   {
912     graphic -= GFX_START_ROCKSFONT;
913     *bitmap = pix[PIX_SMALLFONT];
914     *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
915     *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
916               FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
917   }
918   else
919   {
920     *bitmap = pix[PIX_SP];
921     *x = MINI_SP_STARTX;
922     *y = MINI_SP_STARTY;
923   }
924 }
925
926 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
927 {
928   Bitmap *bitmap;
929   int src_x, src_y;
930
931   getMiniGraphicSource(graphic, &bitmap, &src_x, &src_y);
932   BlitBitmap(bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
933 }
934
935 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
936                         int cut_mode, int mask_mode)
937 {
938   int width = TILEX, height = TILEY;
939   int cx = 0, cy = 0;
940   int src_x, src_y, dest_x, dest_y;
941   int tile = graphic;
942   int bitmap_nr;
943   Bitmap *src_bitmap;
944   GC drawing_gc;
945
946   if (graphic < 0)
947   {
948     DrawGraphic(x, y, graphic);
949     return;
950   }
951
952   if (dx || dy)                 /* Verschiebung der Grafik? */
953   {
954     if (x < BX1)                /* Element kommt von links ins Bild */
955     {
956       x = BX1;
957       width = dx;
958       cx = TILEX - dx;
959       dx = 0;
960     }
961     else if (x > BX2)           /* Element kommt von rechts ins Bild */
962     {
963       x = BX2;
964       width = -dx;
965       dx = TILEX + dx;
966     }
967     else if (x==BX1 && dx < 0)  /* Element verläßt links das Bild */
968     {
969       width += dx;
970       cx = -dx;
971       dx = 0;
972     }
973     else if (x==BX2 && dx > 0)  /* Element verläßt rechts das Bild */
974       width -= dx;
975     else if (dx)                /* allg. Bewegung in x-Richtung */
976       MarkTileDirty(x + SIGN(dx), y);
977
978     if (y < BY1)                /* Element kommt von oben ins Bild */
979     {
980       if (cut_mode==CUT_BELOW)  /* Element oberhalb des Bildes */
981         return;
982
983       y = BY1;
984       height = dy;
985       cy = TILEY - dy;
986       dy = 0;
987     }
988     else if (y > BY2)           /* Element kommt von unten ins Bild */
989     {
990       y = BY2;
991       height = -dy;
992       dy = TILEY + dy;
993     }
994     else if (y==BY1 && dy < 0)  /* Element verläßt oben das Bild */
995     {
996       height += dy;
997       cy = -dy;
998       dy = 0;
999     }
1000     else if (dy > 0 && cut_mode == CUT_ABOVE)
1001     {
1002       if (y == BY2)             /* Element unterhalb des Bildes */
1003         return;
1004
1005       height = dy;
1006       cy = TILEY - dy;
1007       dy = TILEY;
1008       MarkTileDirty(x, y + 1);
1009     }                           /* Element verläßt unten das Bild */
1010     else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1011       height -= dy;
1012     else if (dy)                /* allg. Bewegung in y-Richtung */
1013       MarkTileDirty(x, y + SIGN(dy));
1014   }
1015
1016   getGraphicSource(graphic, &bitmap_nr, &src_x, &src_y);
1017   src_bitmap = pix[bitmap_nr];
1018   drawing_gc = pix[bitmap_nr]->stored_clip_gc;
1019
1020   src_x += cx;
1021   src_y += cy;
1022
1023   dest_x = FX + x * TILEX + dx;
1024   dest_y = FY + y * TILEY + dy;
1025
1026 #if DEBUG
1027   if (!IN_SCR_FIELD(x,y))
1028   {
1029     printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1030     printf("DrawGraphicShifted(): This should never happen!\n");
1031     return;
1032   }
1033 #endif
1034
1035   if (mask_mode == USE_MASKING)
1036   {
1037     if (tile_clipmask[tile] != None)
1038     {
1039       SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
1040       SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
1041       BlitBitmapMasked(src_bitmap, drawto_field,
1042                        src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1043     }
1044     else
1045     {
1046 #if DEBUG
1047 #ifndef TARGET_SDL
1048       printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1049 #endif
1050 #endif
1051
1052       SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1053       BlitBitmapMasked(src_bitmap, drawto_field,
1054                        src_x, src_y, width, height, dest_x, dest_y);
1055     }
1056   }
1057   else
1058     BlitBitmap(pix[bitmap_nr], drawto_field,
1059                src_x, src_y, width, height, dest_x, dest_y);
1060
1061   MarkTileDirty(x,y);
1062 }
1063
1064 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1065                                 int cut_mode)
1066 {
1067   DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1068 }
1069
1070 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1071                           int cut_mode, int mask_mode)
1072 {
1073   int ux = LEVELX(x), uy = LEVELY(y);
1074   int graphic = el2gfx(element);
1075   int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1076   int phase4 = phase8 / 2;
1077   int phase2  = phase8 / 4;
1078   int dir = MovDir[ux][uy];
1079
1080   if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1081   {
1082     graphic += 4 * !phase2;
1083
1084     if (dir == MV_UP)
1085       graphic += 1;
1086     else if (dir == MV_LEFT)
1087       graphic += 2;
1088     else if (dir == MV_DOWN)
1089       graphic += 3;
1090   }
1091   else if (element == EL_SP_SNIKSNAK)
1092   {
1093     if (dir == MV_LEFT)
1094       graphic = GFX_SP_SNIKSNAK_LEFT;
1095     else if (dir == MV_RIGHT)
1096       graphic = GFX_SP_SNIKSNAK_RIGHT;
1097     else if (dir == MV_UP)
1098       graphic = GFX_SP_SNIKSNAK_UP;
1099     else
1100       graphic = GFX_SP_SNIKSNAK_DOWN;
1101
1102     graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1103   }
1104   else if (element == EL_SP_ELECTRON)
1105   {
1106     graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1107   }
1108   else if (element == EL_MOLE || element == EL_PINGUIN ||
1109            element == EL_SCHWEIN || element == EL_DRACHE)
1110   {
1111     if (dir == MV_LEFT)
1112       graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1113                  element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1114                  element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1115     else if (dir == MV_RIGHT)
1116       graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1117                  element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1118                  element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1119     else if (dir == MV_UP)
1120       graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1121                  element == EL_PINGUIN ? GFX_PINGUIN_UP :
1122                  element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1123     else
1124       graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1125                  element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1126                  element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1127
1128     graphic += phase4;
1129   }
1130   else if (element == EL_SONDE)
1131   {
1132     graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1133   }
1134   else if (element == EL_SALZSAEURE)
1135   {
1136     graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1137   }
1138   else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1139   {
1140     graphic += !phase2;
1141   }
1142   else if (element == EL_BALLOON)
1143   {
1144     graphic += phase4;
1145   }
1146   else if ((element == EL_FELSBROCKEN ||
1147             element == EL_SP_ZONK ||
1148             element == EL_BD_ROCK ||
1149             element == EL_SP_INFOTRON ||
1150             IS_GEM(element))
1151            && !cut_mode)
1152   {
1153     if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1154     {
1155       if (element == EL_FELSBROCKEN ||
1156           element == EL_SP_ZONK ||
1157           element == EL_BD_ROCK)
1158       {
1159         if (dir == MV_LEFT)
1160           graphic += (4 - phase4) % 4;
1161         else if (dir == MV_RIGHT)
1162           graphic += phase4;
1163         else
1164           graphic += phase2 * 2;
1165       }
1166       else if (element != EL_SP_INFOTRON)
1167         graphic += phase2;
1168     }
1169   }
1170   else if (element == EL_MAGIC_WALL_EMPTY ||
1171            element == EL_MAGIC_WALL_EMPTYING ||
1172            element == EL_MAGIC_WALL_BD_EMPTY ||
1173            element == EL_MAGIC_WALL_BD_EMPTYING ||
1174            element == EL_MAGIC_WALL_FULL ||
1175            element == EL_MAGIC_WALL_BD_FULL)
1176   {
1177     graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1178   }
1179   else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1180   {
1181     graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1182     graphic += (x + 2 * y + 4) % 4;
1183   }
1184   else if (element == EL_MAUER_LEBT)
1185   {
1186     boolean links_massiv = FALSE, rechts_massiv = FALSE;
1187
1188     if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1189       links_massiv = TRUE;
1190     if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1191       rechts_massiv = TRUE;
1192
1193     if (links_massiv && rechts_massiv)
1194       graphic = GFX_MAUERWERK;
1195     else if (links_massiv)
1196       graphic = GFX_MAUER_R;
1197     else if (rechts_massiv)
1198       graphic = GFX_MAUER_L;
1199   }
1200   else if ((element == EL_INVISIBLE_STEEL ||
1201             element == EL_UNSICHTBAR ||
1202             element == EL_SAND_INVISIBLE) && game.light_time_left)
1203   {
1204     graphic = (element == EL_INVISIBLE_STEEL ? GFX_INVISIBLE_STEEL_ON :
1205                element == EL_UNSICHTBAR ? GFX_UNSICHTBAR_ON :
1206                GFX_SAND_INVISIBLE_ON);
1207   }
1208
1209   if (dx || dy)
1210     DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1211   else if (mask_mode == USE_MASKING)
1212     DrawGraphicThruMask(x, y, graphic);
1213   else
1214     DrawGraphic(x, y, graphic);
1215 }
1216
1217 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1218                          int cut_mode, int mask_mode)
1219 {
1220   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1221     DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1222                          cut_mode, mask_mode);
1223 }
1224
1225 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1226                               int cut_mode)
1227 {
1228   DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1229 }
1230
1231 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1232                              int cut_mode)
1233 {
1234   DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1235 }
1236
1237 void DrawScreenElementThruMask(int x, int y, int element)
1238 {
1239   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1240 }
1241
1242 void DrawLevelElementThruMask(int x, int y, int element)
1243 {
1244   DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1245 }
1246
1247 void DrawLevelFieldThruMask(int x, int y)
1248 {
1249   DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1250 }
1251
1252 void ErdreichAnbroeckeln(int x, int y)
1253 {
1254   int i, width, height, cx,cy;
1255   int ux = LEVELX(x), uy = LEVELY(y);
1256   int element, graphic;
1257   int snip = 4;
1258   static int xy[4][2] =
1259   {
1260     { 0, -1 },
1261     { -1, 0 },
1262     { +1, 0 },
1263     { 0, +1 }
1264   };
1265
1266   if (!IN_LEV_FIELD(ux, uy))
1267     return;
1268
1269   element = Feld[ux][uy];
1270
1271   if (element == EL_ERDREICH ||
1272       element == EL_LANDMINE ||
1273       element == EL_TRAP_INACTIVE ||
1274       element == EL_TRAP_ACTIVE)
1275   {
1276     if (!IN_SCR_FIELD(x, y))
1277       return;
1278
1279     graphic = GFX_ERDENRAND;
1280
1281     for(i=0; i<4; i++)
1282     {
1283       int uxx, uyy;
1284
1285       uxx = ux + xy[i][0];
1286       uyy = uy + xy[i][1];
1287       if (!IN_LEV_FIELD(uxx, uyy))
1288         element = EL_BETON;
1289       else
1290         element = Feld[uxx][uyy];
1291
1292       if (element == EL_ERDREICH ||
1293           element == EL_LANDMINE ||
1294           element == EL_TRAP_INACTIVE ||
1295           element == EL_TRAP_ACTIVE)
1296         continue;
1297
1298       if (i == 1 || i == 2)
1299       {
1300         width = snip;
1301         height = TILEY;
1302         cx = (i == 2 ? TILEX - snip : 0);
1303         cy = 0;
1304       }
1305       else
1306       {
1307         width = TILEX;
1308         height = snip;
1309         cx = 0;
1310         cy = (i == 3 ? TILEY - snip : 0);
1311       }
1312
1313       BlitBitmap(pix[PIX_BACK], drawto_field,
1314                  SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1315                  SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1316                  width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1317     }
1318
1319     MarkTileDirty(x, y);
1320   }
1321   else
1322   {
1323     graphic = GFX_ERDENRAND;
1324
1325     for(i=0; i<4; i++)
1326     {
1327       int xx, yy, uxx, uyy;
1328
1329       xx = x + xy[i][0];
1330       yy = y + xy[i][1];
1331       uxx = ux + xy[i][0];
1332       uyy = uy + xy[i][1];
1333
1334       if (!IN_LEV_FIELD(uxx, uyy) ||
1335           (Feld[uxx][uyy] != EL_ERDREICH &&
1336            Feld[uxx][uyy] != EL_LANDMINE &&
1337            Feld[uxx][uyy] != EL_TRAP_INACTIVE &&
1338            Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1339           !IN_SCR_FIELD(xx, yy))
1340         continue;
1341
1342       if (i == 1 || i == 2)
1343       {
1344         width = snip;
1345         height = TILEY;
1346         cx = (i == 1 ? TILEX - snip : 0);
1347         cy = 0;
1348       }
1349       else
1350       {
1351         width = TILEX;
1352         height = snip;
1353         cx = 0;
1354         cy = (i==0 ? TILEY-snip : 0);
1355       }
1356
1357       BlitBitmap(pix[PIX_BACK], drawto_field,
1358                  SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1359                  SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1360                  width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1361
1362       MarkTileDirty(xx, yy);
1363     }
1364   }
1365 }
1366
1367 void DrawScreenElement(int x, int y, int element)
1368 {
1369   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1370   ErdreichAnbroeckeln(x, y);
1371 }
1372
1373 void DrawLevelElement(int x, int y, int element)
1374 {
1375   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1376     DrawScreenElement(SCREENX(x), SCREENY(y), element);
1377 }
1378
1379 void DrawScreenField(int x, int y)
1380 {
1381   int ux = LEVELX(x), uy = LEVELY(y);
1382   int element, content;
1383
1384   if (!IN_LEV_FIELD(ux, uy))
1385   {
1386     if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1387       element = EL_LEERRAUM;
1388     else
1389       element = BorderElement;
1390
1391     DrawScreenElement(x, y, element);
1392     return;
1393   }
1394
1395   element = Feld[ux][uy];
1396   content = Store[ux][uy];
1397
1398   if (IS_MOVING(ux, uy))
1399   {
1400     int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1401     boolean cut_mode = NO_CUTTING;
1402
1403     if (element == EL_QUICKSAND_EMPTYING ||
1404         element == EL_MAGIC_WALL_EMPTYING ||
1405         element == EL_MAGIC_WALL_BD_EMPTYING ||
1406         element == EL_AMOEBA_DRIPPING)
1407       cut_mode = CUT_ABOVE;
1408     else if (element == EL_QUICKSAND_FILLING ||
1409              element == EL_MAGIC_WALL_FILLING ||
1410              element == EL_MAGIC_WALL_BD_FILLING)
1411       cut_mode = CUT_BELOW;
1412
1413     if (cut_mode == CUT_ABOVE)
1414       DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1415     else
1416       DrawScreenElement(x, y, EL_LEERRAUM);
1417
1418     if (horiz_move)
1419       DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1420     else if (cut_mode == NO_CUTTING)
1421       DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1422     else
1423       DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1424
1425     if (content == EL_SALZSAEURE)
1426       DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1427   }
1428   else if (IS_BLOCKED(ux, uy))
1429   {
1430     int oldx, oldy;
1431     int sx, sy;
1432     int horiz_move;
1433     boolean cut_mode = NO_CUTTING;
1434     int element_old, content_old;
1435
1436     Blocked2Moving(ux, uy, &oldx, &oldy);
1437     sx = SCREENX(oldx);
1438     sy = SCREENY(oldy);
1439     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1440                   MovDir[oldx][oldy] == MV_RIGHT);
1441
1442     element_old = Feld[oldx][oldy];
1443     content_old = Store[oldx][oldy];
1444
1445     if (element_old == EL_QUICKSAND_EMPTYING ||
1446         element_old == EL_MAGIC_WALL_EMPTYING ||
1447         element_old == EL_MAGIC_WALL_BD_EMPTYING ||
1448         element_old == EL_AMOEBA_DRIPPING)
1449       cut_mode = CUT_ABOVE;
1450
1451     DrawScreenElement(x, y, EL_LEERRAUM);
1452
1453     if (horiz_move)
1454       DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1455                                NO_CUTTING);
1456     else if (cut_mode == NO_CUTTING)
1457       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1458                                cut_mode);
1459     else
1460       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1461                                cut_mode);
1462   }
1463   else if (IS_DRAWABLE(element))
1464     DrawScreenElement(x, y, element);
1465   else
1466     DrawScreenElement(x, y, EL_LEERRAUM);
1467 }
1468
1469 void DrawLevelField(int x, int y)
1470 {
1471   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1472     DrawScreenField(SCREENX(x), SCREENY(y));
1473   else if (IS_MOVING(x, y))
1474   {
1475     int newx,newy;
1476
1477     Moving2Blocked(x, y, &newx, &newy);
1478     if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1479       DrawScreenField(SCREENX(newx), SCREENY(newy));
1480   }
1481   else if (IS_BLOCKED(x, y))
1482   {
1483     int oldx, oldy;
1484
1485     Blocked2Moving(x, y, &oldx, &oldy);
1486     if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1487       DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1488   }
1489 }
1490
1491 void DrawMiniElement(int x, int y, int element)
1492 {
1493   int graphic;
1494
1495   if (!element)
1496   {
1497     DrawMiniGraphic(x, y, -1);
1498     return;
1499   }
1500
1501   graphic = el2gfx(element);
1502   DrawMiniGraphic(x, y, graphic);
1503 }
1504
1505 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1506 {
1507   int x = sx + scroll_x, y = sy + scroll_y;
1508
1509   if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1510     DrawMiniElement(sx, sy, EL_LEERRAUM);
1511   else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1512     DrawMiniElement(sx, sy, Feld[x][y]);
1513   else
1514   {
1515     int steel_type, steel_position;
1516     int border[6][2] =
1517     {
1518       { GFX_VSTEEL_UPPER_LEFT,  GFX_ISTEEL_UPPER_LEFT  },
1519       { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1520       { GFX_VSTEEL_LOWER_LEFT,  GFX_ISTEEL_LOWER_LEFT  },
1521       { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1522       { GFX_VSTEEL_VERTICAL,    GFX_ISTEEL_VERTICAL    },
1523       { GFX_VSTEEL_HORIZONTAL,  GFX_ISTEEL_HORIZONTAL  }
1524     };
1525
1526     steel_type = (BorderElement == EL_BETON ? 0 : 1);
1527     steel_position = (x == -1 && y == -1                        ? 0 :
1528                       x == lev_fieldx && y == -1                ? 1 :
1529                       x == -1 && y == lev_fieldy                ? 2 :
1530                       x == lev_fieldx && y == lev_fieldy        ? 3 :
1531                       x == -1 || x == lev_fieldx                ? 4 :
1532                       y == -1 || y == lev_fieldy                ? 5 : -1);
1533
1534     if (steel_position != -1)
1535       DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1536   }
1537 }
1538
1539 void DrawMicroElement(int xpos, int ypos, int element)
1540 {
1541   int graphic;
1542
1543   if (element == EL_LEERRAUM)
1544     return;
1545
1546   graphic = el2gfx(element);
1547
1548   if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1549   {
1550     graphic -= GFX_START_ROCKSSP;
1551     graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
1552     BlitBitmap(pix[PIX_SP], drawto,
1553                MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
1554                MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
1555                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1556   }
1557   else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1558   {
1559     graphic -= GFX_START_ROCKSDC;
1560     BlitBitmap(pix[PIX_DC], drawto,
1561                MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
1562                MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
1563                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1564   }
1565   else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1566   {
1567     graphic -= GFX_START_ROCKSMORE;
1568     BlitBitmap(pix[PIX_MORE], drawto,
1569                MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE)*MICRO_TILEX,
1570                MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE)*MICRO_TILEY,
1571                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1572   }
1573   else
1574     BlitBitmap(pix[PIX_BACK], drawto,
1575                MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1576                MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1577                MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1578 }
1579
1580 void DrawLevel()
1581 {
1582   int x,y;
1583
1584   ClearWindow();
1585
1586   for(x=BX1; x<=BX2; x++)
1587     for(y=BY1; y<=BY2; y++)
1588       DrawScreenField(x, y);
1589
1590   redraw_mask |= REDRAW_FIELD;
1591 }
1592
1593 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1594 {
1595   int x,y;
1596
1597   for(x=0; x<size_x; x++)
1598     for(y=0; y<size_y; y++)
1599       DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1600
1601   redraw_mask |= REDRAW_FIELD;
1602 }
1603
1604 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1605 {
1606   int x, y;
1607
1608   ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1609
1610   if (lev_fieldx < STD_LEV_FIELDX)
1611     xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1612   if (lev_fieldy < STD_LEV_FIELDY)
1613     ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1614
1615   xpos += MICRO_TILEX;
1616   ypos += MICRO_TILEY;
1617
1618   for(x=-1; x<=STD_LEV_FIELDX; x++)
1619   {
1620     for(y=-1; y<=STD_LEV_FIELDY; y++)
1621     {
1622       int lx = from_x + x, ly = from_y + y;
1623
1624       if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1625         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1626                          Ur[lx][ly]);
1627       else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1628         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1629                          BorderElement);
1630     }
1631   }
1632
1633   redraw_mask |= REDRAW_MICROLEVEL;
1634 }
1635
1636 #define MICROLABEL_EMPTY                0
1637 #define MICROLABEL_LEVEL_NAME           1
1638 #define MICROLABEL_CREATED_BY           2
1639 #define MICROLABEL_LEVEL_AUTHOR         3
1640 #define MICROLABEL_IMPORTED_FROM        4
1641 #define MICROLABEL_LEVEL_IMPORT_INFO    5
1642
1643 #define MAX_MICROLABEL_SIZE             (SXSIZE / FONT4_XSIZE)
1644
1645 static void DrawMicroLevelLabelExt(int mode)
1646 {
1647   char label_text[MAX_MICROLABEL_SIZE + 1];
1648
1649   ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1650
1651   strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1652                        mode == MICROLABEL_CREATED_BY ? "created by" :
1653                        mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1654                        mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1655                        mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1656                        leveldir_current->imported_from : ""),
1657           MAX_MICROLABEL_SIZE);
1658   label_text[MAX_MICROLABEL_SIZE] = '\0';
1659
1660   if (strlen(label_text) > 0)
1661   {
1662     int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1663     int lypos = MICROLABEL_YPOS;
1664
1665     DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1666   }
1667
1668   redraw_mask |= REDRAW_MICROLEVEL;
1669 }
1670
1671 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1672 {
1673   static unsigned long scroll_delay = 0;
1674   static unsigned long label_delay = 0;
1675   static int from_x, from_y, scroll_direction;
1676   static int label_state, label_counter;
1677
1678   if (restart)
1679   {
1680     from_x = from_y = 0;
1681     scroll_direction = MV_RIGHT;
1682     label_state = 1;
1683     label_counter = 0;
1684
1685     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1686     DrawMicroLevelLabelExt(label_state);
1687
1688     /* initialize delay counters */
1689     DelayReached(&scroll_delay, 0);
1690     DelayReached(&label_delay, 0);
1691
1692     return;
1693   }
1694
1695   /* scroll micro level, if needed */
1696   if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1697       DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1698   {
1699     switch (scroll_direction)
1700     {
1701       case MV_LEFT:
1702         if (from_x > 0)
1703           from_x--;
1704         else
1705           scroll_direction = MV_UP;
1706         break;
1707
1708       case MV_RIGHT:
1709         if (from_x < lev_fieldx - STD_LEV_FIELDX)
1710           from_x++;
1711         else
1712           scroll_direction = MV_DOWN;
1713         break;
1714
1715       case MV_UP:
1716         if (from_y > 0)
1717           from_y--;
1718         else
1719           scroll_direction = MV_RIGHT;
1720         break;
1721
1722       case MV_DOWN:
1723         if (from_y < lev_fieldy - STD_LEV_FIELDY)
1724           from_y++;
1725         else
1726           scroll_direction = MV_LEFT;
1727         break;
1728
1729       default:
1730         break;
1731     }
1732
1733     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1734   }
1735
1736   /* redraw micro level label, if needed */
1737   if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1738       strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1739       strcmp(level.author, leveldir_current->name) != 0 &&
1740       DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1741   {
1742     int max_label_counter = 23;
1743
1744     if (leveldir_current->imported_from != NULL)
1745       max_label_counter += 14;
1746
1747     label_counter = (label_counter + 1) % max_label_counter;
1748     label_state = (label_counter >= 0 && label_counter <= 7 ?
1749                    MICROLABEL_LEVEL_NAME :
1750                    label_counter >= 9 && label_counter <= 12 ?
1751                    MICROLABEL_CREATED_BY :
1752                    label_counter >= 14 && label_counter <= 21 ?
1753                    MICROLABEL_LEVEL_AUTHOR :
1754                    label_counter >= 23 && label_counter <= 26 ?
1755                    MICROLABEL_IMPORTED_FROM :
1756                    label_counter >= 28 && label_counter <= 35 ?
1757                    MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1758     DrawMicroLevelLabelExt(label_state);
1759   }
1760 }
1761
1762 int REQ_in_range(int x, int y)
1763 {
1764   if (y > DY+249 && y < DY+278)
1765   {
1766     if (x > DX+1 && x < DX+48)
1767       return 1;
1768     else if (x > DX+51 && x < DX+98) 
1769       return 2;
1770   }
1771   return 0;
1772 }
1773
1774 #define MAX_REQUEST_LINES               13
1775 #define MAX_REQUEST_LINE_LEN            7
1776
1777 boolean Request(char *text, unsigned int req_state)
1778 {
1779   int mx, my, ty, result = -1;
1780   unsigned int old_door_state;
1781
1782 #if defined(PLATFORM_UNIX)
1783   /* pause network game while waiting for request to answer */
1784   if (options.network &&
1785       game_status == PLAYING &&
1786       req_state & REQUEST_WAIT_FOR)
1787     SendToServer_PausePlaying();
1788 #endif
1789
1790   old_door_state = GetDoorState();
1791
1792   UnmapAllGadgets();
1793
1794   CloseDoor(DOOR_CLOSE_1);
1795
1796   /* save old door content */
1797   BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
1798              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1799              DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1800
1801   /* clear door drawing field */
1802   ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
1803
1804   /* write text for request */
1805   for(ty=0; ty < MAX_REQUEST_LINES; ty++)
1806   {
1807     char text_line[MAX_REQUEST_LINE_LEN + 1];
1808     int tx, tl, tc;
1809
1810     if (!*text)
1811       break;
1812
1813     for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
1814     {
1815       tc = *(text + tx);
1816       if (!tc || tc == ' ')
1817         break;
1818     }
1819
1820     if (!tl)
1821     { 
1822       text++; 
1823       ty--; 
1824       continue; 
1825     }
1826
1827     strncpy(text_line, text, tl);
1828     text_line[tl] = 0;
1829
1830     DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
1831                 text_line, FS_SMALL, FC_YELLOW);
1832
1833     text += tl + (tc == ' ' ? 1 : 0);
1834   }
1835
1836   if (req_state & REQ_ASK)
1837   {
1838     MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1839     MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1840   }
1841   else if (req_state & REQ_CONFIRM)
1842   {
1843     MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1844   }
1845   else if (req_state & REQ_PLAYER)
1846   {
1847     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1848     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1849     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1850     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1851   }
1852
1853   /* copy request gadgets to door backbuffer */
1854   BlitBitmap(drawto, pix[PIX_DB_DOOR],
1855              DX, DY, DXSIZE, DYSIZE,
1856              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1857
1858   OpenDoor(DOOR_OPEN_1);
1859
1860 #if 0
1861   ClearEventQueue();
1862 #endif
1863
1864   if (!(req_state & REQUEST_WAIT_FOR))
1865     return(FALSE);
1866
1867   if (game_status != MAINMENU)
1868     InitAnimation();
1869
1870   button_status = MB_RELEASED;
1871
1872   request_gadget_id = -1;
1873
1874   while(result < 0)
1875   {
1876     if (PendingEvent())
1877     {
1878       Event event;
1879
1880       NextEvent(&event);
1881
1882       switch(event.type)
1883       {
1884         case EVENT_BUTTONPRESS:
1885         case EVENT_BUTTONRELEASE:
1886         case EVENT_MOTIONNOTIFY:
1887         {
1888           if (event.type == EVENT_MOTIONNOTIFY)
1889           {
1890             if (!PointerInWindow(window))
1891               continue; /* window and pointer are on different screens */
1892
1893             if (!button_status)
1894               continue;
1895
1896             motion_status = TRUE;
1897             mx = ((MotionEvent *) &event)->x;
1898             my = ((MotionEvent *) &event)->y;
1899           }
1900           else
1901           {
1902             motion_status = FALSE;
1903             mx = ((ButtonEvent *) &event)->x;
1904             my = ((ButtonEvent *) &event)->y;
1905             if (event.type == EVENT_BUTTONPRESS)
1906               button_status = ((ButtonEvent *) &event)->button;
1907             else
1908               button_status = MB_RELEASED;
1909           }
1910
1911           /* this sets 'request_gadget_id' */
1912           HandleGadgets(mx, my, button_status);
1913
1914           switch(request_gadget_id)
1915           {
1916             case TOOL_CTRL_ID_YES:
1917               result = TRUE;
1918               break;
1919             case TOOL_CTRL_ID_NO:
1920               result = FALSE;
1921               break;
1922             case TOOL_CTRL_ID_CONFIRM:
1923               result = TRUE | FALSE;
1924               break;
1925
1926             case TOOL_CTRL_ID_PLAYER_1:
1927               result = 1;
1928               break;
1929             case TOOL_CTRL_ID_PLAYER_2:
1930               result = 2;
1931               break;
1932             case TOOL_CTRL_ID_PLAYER_3:
1933               result = 3;
1934               break;
1935             case TOOL_CTRL_ID_PLAYER_4:
1936               result = 4;
1937               break;
1938
1939             default:
1940               break;
1941           }
1942
1943           break;
1944         }
1945
1946         case EVENT_KEYPRESS:
1947           switch(GetEventKey((KeyEvent *)&event, TRUE))
1948           {
1949             case KSYM_Return:
1950               result = 1;
1951               break;
1952
1953             case KSYM_Escape:
1954               result = 0;
1955               break;
1956
1957             default:
1958               break;
1959           }
1960           if (req_state & REQ_PLAYER)
1961             result = 0;
1962           break;
1963
1964         case EVENT_KEYRELEASE:
1965           ClearPlayerAction();
1966           break;
1967
1968         default:
1969           HandleOtherEvents(&event);
1970           break;
1971       }
1972     }
1973     else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1974     {
1975       int joy = AnyJoystick();
1976
1977       if (joy & JOY_BUTTON_1)
1978         result = 1;
1979       else if (joy & JOY_BUTTON_2)
1980         result = 0;
1981     }
1982
1983     DoAnimation();
1984
1985     /* don't eat all CPU time */
1986     Delay(10);
1987   }
1988
1989   if (game_status != MAINMENU)
1990     StopAnimation();
1991
1992   UnmapToolButtons();
1993
1994   if (!(req_state & REQ_STAY_OPEN))
1995   {
1996     CloseDoor(DOOR_CLOSE_1);
1997
1998     if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1999     {
2000       BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2001                  DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2002                  DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2003       OpenDoor(DOOR_OPEN_1);
2004     }
2005   }
2006
2007   RemapAllGadgets();
2008
2009 #if defined(PLATFORM_UNIX)
2010   /* continue network game after request */
2011   if (options.network &&
2012       game_status == PLAYING &&
2013       req_state & REQUEST_WAIT_FOR)
2014     SendToServer_ContinuePlaying();
2015 #endif
2016
2017   return(result);
2018 }
2019
2020 unsigned int OpenDoor(unsigned int door_state)
2021 {
2022   unsigned int new_door_state;
2023
2024   if (door_state & DOOR_COPY_BACK)
2025   {
2026     BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2027                DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2028                DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2029     door_state &= ~DOOR_COPY_BACK;
2030   }
2031
2032   new_door_state = MoveDoor(door_state);
2033
2034   return(new_door_state);
2035 }
2036
2037 unsigned int CloseDoor(unsigned int door_state)
2038 {
2039   unsigned int new_door_state;
2040
2041   BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2042              DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2043   BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2044              VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2045
2046   new_door_state = MoveDoor(door_state);
2047
2048   return(new_door_state);
2049 }
2050
2051 unsigned int GetDoorState()
2052 {
2053   return MoveDoor(DOOR_GET_STATE);
2054 }
2055
2056 unsigned int SetDoorState(unsigned int door_state)
2057 {
2058   return MoveDoor(door_state | DOOR_SET_STATE);
2059 }
2060
2061 unsigned int MoveDoor(unsigned int door_state)
2062 {
2063   static int door1 = DOOR_OPEN_1;
2064   static int door2 = DOOR_CLOSE_2;
2065   static unsigned long door_delay = 0;
2066   int x, start, stepsize = 2;
2067   unsigned long door_delay_value = stepsize * 5;
2068
2069   if (door_state == DOOR_GET_STATE)
2070     return(door1 | door2);
2071
2072   if (door_state & DOOR_SET_STATE)
2073   {
2074     if (door_state & DOOR_ACTION_1)
2075       door1 = door_state & DOOR_ACTION_1;
2076     if (door_state & DOOR_ACTION_2)
2077       door2 = door_state & DOOR_ACTION_2;
2078
2079     return(door1 | door2);
2080   }
2081
2082   if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2083     door_state &= ~DOOR_OPEN_1;
2084   else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2085     door_state &= ~DOOR_CLOSE_1;
2086   if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2087     door_state &= ~DOOR_OPEN_2;
2088   else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2089     door_state &= ~DOOR_CLOSE_2;
2090
2091   if (setup.quick_doors)
2092   {
2093     stepsize = 20;
2094     door_delay_value = 0;
2095     StopSound(SND_MENU_DOOR_OPENING);
2096     StopSound(SND_MENU_DOOR_CLOSING);
2097   }
2098
2099   if (door_state & DOOR_ACTION)
2100   {
2101     if (!(door_state & DOOR_NO_DELAY))
2102     {
2103       if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2104         PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2105       if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2106         PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2107     }
2108
2109     start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2110
2111     for(x=start; x<=DXSIZE; x+=stepsize)
2112     {
2113       Bitmap *bitmap = pix[PIX_DOOR];
2114       GC gc = bitmap->stored_clip_gc;
2115
2116       WaitUntilDelayReached(&door_delay, door_delay_value);
2117
2118       if (door_state & DOOR_ACTION_1)
2119       {
2120         int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2121         int j = (DXSIZE - i) / 3;
2122
2123         BlitBitmap(pix[PIX_DB_DOOR], drawto,
2124                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2125                    DXSIZE,DYSIZE - i/2, DX, DY);
2126
2127         ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2128
2129         SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2130         BlitBitmapMasked(bitmap, drawto,
2131                          DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2132                          DX + DXSIZE - i, DY + j);
2133         BlitBitmapMasked(bitmap, drawto,
2134                          DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2135                          DX + DXSIZE - i, DY + 140 + j);
2136         SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2137         BlitBitmapMasked(bitmap, drawto,
2138                          DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2139                          DX, DY);
2140         BlitBitmapMasked(bitmap, drawto,
2141                          DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2142                          DX, DY + 140 - j);
2143
2144         BlitBitmapMasked(bitmap, drawto,
2145                          DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2146                          DX, DY + 77 - j);
2147         BlitBitmapMasked(bitmap, drawto,
2148                          DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2149                          DX, DY + 203 - j);
2150         SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2151         BlitBitmapMasked(bitmap, drawto,
2152                          DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2153                          DX + DXSIZE - i, DY + 77 + j);
2154         BlitBitmapMasked(bitmap, drawto,
2155                          DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2156                          DX + DXSIZE - i, DY + 203 + j);
2157
2158         redraw_mask |= REDRAW_DOOR_1;
2159       }
2160
2161       if (door_state & DOOR_ACTION_2)
2162       {
2163         int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2164         int j = (VXSIZE - i) / 3;
2165
2166         BlitBitmap(pix[PIX_DB_DOOR], drawto,
2167                    DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2168                    VXSIZE, VYSIZE - i/2, VX, VY);
2169
2170         ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2171
2172         SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2173         BlitBitmapMasked(bitmap, drawto,
2174                          VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2175                          VX + VXSIZE-i, VY+j);
2176         SetClipOrigin(bitmap, gc,
2177                       VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2178         BlitBitmapMasked(bitmap, drawto,
2179                          VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2180                          VX, VY);
2181
2182         BlitBitmapMasked(bitmap, drawto,
2183                          VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2184                          i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2185         SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2186         BlitBitmapMasked(bitmap, drawto,
2187                          VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2188                          i, VYSIZE / 2 - j,
2189                          VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2190
2191         redraw_mask |= REDRAW_DOOR_2;
2192       }
2193
2194       BackToFront();
2195
2196       if (game_status == MAINMENU)
2197         DoAnimation();
2198     }
2199   }
2200
2201   if (setup.quick_doors)
2202   {
2203     StopSound(SND_MENU_DOOR_OPENING);
2204     StopSound(SND_MENU_DOOR_CLOSING);
2205   }
2206
2207   if (door_state & DOOR_ACTION_1)
2208     door1 = door_state & DOOR_ACTION_1;
2209   if (door_state & DOOR_ACTION_2)
2210     door2 = door_state & DOOR_ACTION_2;
2211
2212   return (door1 | door2);
2213 }
2214
2215 void DrawSpecialEditorDoor()
2216 {
2217   /* draw bigger toolbox window */
2218   BlitBitmap(pix[PIX_DOOR], drawto,
2219              DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2220
2221   redraw_mask |= REDRAW_ALL;
2222 }
2223
2224 void UndrawSpecialEditorDoor()
2225 {
2226   /* draw normal tape recorder window */
2227   BlitBitmap(pix[PIX_BACK], drawto,
2228              562, 344, 108, 56, EX - 4, EY - 12);
2229
2230   redraw_mask |= REDRAW_ALL;
2231 }
2232
2233 #ifndef TARGET_SDL
2234 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2235 {
2236   XImage *pixel_image;
2237   unsigned long pixel_value;
2238
2239   pixel_image = XGetImage(display, bitmap->drawable,
2240                           x, y, 1, 1, AllPlanes, ZPixmap);
2241   pixel_value = XGetPixel(pixel_image, 0, 0);
2242
2243   XDestroyImage(pixel_image);
2244
2245   return pixel_value;
2246 }
2247 #endif
2248
2249 /* ---------- new tool button stuff ---------------------------------------- */
2250
2251 /* graphic position values for tool buttons */
2252 #define TOOL_BUTTON_YES_XPOS            2
2253 #define TOOL_BUTTON_YES_YPOS            250
2254 #define TOOL_BUTTON_YES_GFX_YPOS        0
2255 #define TOOL_BUTTON_YES_XSIZE           46
2256 #define TOOL_BUTTON_YES_YSIZE           28
2257 #define TOOL_BUTTON_NO_XPOS             52
2258 #define TOOL_BUTTON_NO_YPOS             TOOL_BUTTON_YES_YPOS
2259 #define TOOL_BUTTON_NO_GFX_YPOS         TOOL_BUTTON_YES_GFX_YPOS
2260 #define TOOL_BUTTON_NO_XSIZE            TOOL_BUTTON_YES_XSIZE
2261 #define TOOL_BUTTON_NO_YSIZE            TOOL_BUTTON_YES_YSIZE
2262 #define TOOL_BUTTON_CONFIRM_XPOS        TOOL_BUTTON_YES_XPOS
2263 #define TOOL_BUTTON_CONFIRM_YPOS        TOOL_BUTTON_YES_YPOS
2264 #define TOOL_BUTTON_CONFIRM_GFX_YPOS    30
2265 #define TOOL_BUTTON_CONFIRM_XSIZE       96
2266 #define TOOL_BUTTON_CONFIRM_YSIZE       TOOL_BUTTON_YES_YSIZE
2267 #define TOOL_BUTTON_PLAYER_XSIZE        30
2268 #define TOOL_BUTTON_PLAYER_YSIZE        30
2269 #define TOOL_BUTTON_PLAYER_GFX_XPOS     5
2270 #define TOOL_BUTTON_PLAYER_GFX_YPOS     185
2271 #define TOOL_BUTTON_PLAYER_XPOS         (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2272 #define TOOL_BUTTON_PLAYER_YPOS         (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2273 #define TOOL_BUTTON_PLAYER1_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2274                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2275 #define TOOL_BUTTON_PLAYER2_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2276                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2277 #define TOOL_BUTTON_PLAYER3_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2278                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2279 #define TOOL_BUTTON_PLAYER4_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2280                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2281 #define TOOL_BUTTON_PLAYER1_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2282                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2283 #define TOOL_BUTTON_PLAYER2_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2284                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2285 #define TOOL_BUTTON_PLAYER3_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2286                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2287 #define TOOL_BUTTON_PLAYER4_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2288                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2289
2290 static struct
2291 {
2292   int xpos, ypos;
2293   int x, y;
2294   int width, height;
2295   int gadget_id;
2296   char *infotext;
2297 } toolbutton_info[NUM_TOOL_BUTTONS] =
2298 {
2299   {
2300     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_GFX_YPOS,
2301     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_YPOS,
2302     TOOL_BUTTON_YES_XSIZE,      TOOL_BUTTON_YES_YSIZE,
2303     TOOL_CTRL_ID_YES,
2304     "yes"
2305   },
2306   {
2307     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_GFX_YPOS,
2308     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_YPOS,
2309     TOOL_BUTTON_NO_XSIZE,       TOOL_BUTTON_NO_YSIZE,
2310     TOOL_CTRL_ID_NO,
2311     "no"
2312   },
2313   {
2314     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_GFX_YPOS,
2315     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_YPOS,
2316     TOOL_BUTTON_CONFIRM_XSIZE,  TOOL_BUTTON_CONFIRM_YSIZE,
2317     TOOL_CTRL_ID_CONFIRM,
2318     "confirm"
2319   },
2320   {
2321     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2322     TOOL_BUTTON_PLAYER1_XPOS,   TOOL_BUTTON_PLAYER1_YPOS,
2323     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2324     TOOL_CTRL_ID_PLAYER_1,
2325     "player 1"
2326   },
2327   {
2328     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2329     TOOL_BUTTON_PLAYER2_XPOS,   TOOL_BUTTON_PLAYER2_YPOS,
2330     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2331     TOOL_CTRL_ID_PLAYER_2,
2332     "player 2"
2333   },
2334   {
2335     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2336     TOOL_BUTTON_PLAYER3_XPOS,   TOOL_BUTTON_PLAYER3_YPOS,
2337     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2338     TOOL_CTRL_ID_PLAYER_3,
2339     "player 3"
2340   },
2341   {
2342     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2343     TOOL_BUTTON_PLAYER4_XPOS,   TOOL_BUTTON_PLAYER4_YPOS,
2344     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2345     TOOL_CTRL_ID_PLAYER_4,
2346     "player 4"
2347   }
2348 };
2349
2350 void CreateToolButtons()
2351 {
2352   int i;
2353
2354   for (i=0; i<NUM_TOOL_BUTTONS; i++)
2355   {
2356     Bitmap *gd_bitmap = pix[PIX_DOOR];
2357     Bitmap *deco_bitmap = None;
2358     int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2359     struct GadgetInfo *gi;
2360     unsigned long event_mask;
2361     int gd_xoffset, gd_yoffset;
2362     int gd_x1, gd_x2, gd_y;
2363     int id = i;
2364
2365     event_mask = GD_EVENT_RELEASED;
2366
2367     gd_xoffset = toolbutton_info[i].xpos;
2368     gd_yoffset = toolbutton_info[i].ypos;
2369     gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2370     gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2371     gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2372
2373     if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2374     {
2375       getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2376                            &deco_bitmap, &deco_x, &deco_y);
2377       deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2378       deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2379     }
2380
2381     gi = CreateGadget(GDI_CUSTOM_ID, id,
2382                       GDI_INFO_TEXT, toolbutton_info[i].infotext,
2383                       GDI_X, DX + toolbutton_info[i].x,
2384                       GDI_Y, DY + toolbutton_info[i].y,
2385                       GDI_WIDTH, toolbutton_info[i].width,
2386                       GDI_HEIGHT, toolbutton_info[i].height,
2387                       GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2388                       GDI_STATE, GD_BUTTON_UNPRESSED,
2389                       GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2390                       GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2391                       GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2392                       GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2393                       GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2394                       GDI_DECORATION_SHIFTING, 1, 1,
2395                       GDI_EVENT_MASK, event_mask,
2396                       GDI_CALLBACK_ACTION, HandleToolButtons,
2397                       GDI_END);
2398
2399     if (gi == NULL)
2400       Error(ERR_EXIT, "cannot create gadget");
2401
2402     tool_gadget[id] = gi;
2403   }
2404 }
2405
2406 static void UnmapToolButtons()
2407 {
2408   int i;
2409
2410   for (i=0; i<NUM_TOOL_BUTTONS; i++)
2411     UnmapGadget(tool_gadget[i]);
2412 }
2413
2414 static void HandleToolButtons(struct GadgetInfo *gi)
2415 {
2416   request_gadget_id = gi->custom_id;
2417 }
2418
2419 int get_next_element(int element)
2420 {
2421   switch(element)
2422   {
2423     case EL_QUICKSAND_FILLING:          return EL_MORAST_VOLL;
2424     case EL_QUICKSAND_EMPTYING:         return EL_MORAST_LEER;
2425     case EL_MAGIC_WALL_FILLING:         return EL_MAGIC_WALL_FULL;
2426     case EL_MAGIC_WALL_EMPTYING:        return EL_MAGIC_WALL_EMPTY;
2427     case EL_MAGIC_WALL_BD_FILLING:      return EL_MAGIC_WALL_BD_FULL;
2428     case EL_MAGIC_WALL_BD_EMPTYING:     return EL_MAGIC_WALL_BD_EMPTY;
2429     case EL_AMOEBA_DRIPPING:            return EL_AMOEBE_NASS;
2430
2431     default:                            return element;
2432   }
2433 }
2434
2435 int el2gfx(int element)
2436 {
2437   switch(element)
2438   {
2439     case EL_LEERRAUM:           return -1;
2440     case EL_ERDREICH:           return GFX_ERDREICH;
2441     case EL_MAUERWERK:          return GFX_MAUERWERK;
2442     case EL_FELSBODEN:          return GFX_FELSBODEN;
2443     case EL_FELSBROCKEN:        return GFX_FELSBROCKEN;
2444     case EL_SCHLUESSEL:         return GFX_SCHLUESSEL;
2445     case EL_EDELSTEIN:          return GFX_EDELSTEIN;
2446     case EL_AUSGANG_ZU:         return GFX_AUSGANG_ZU;
2447     case EL_AUSGANG_ACT:        return GFX_AUSGANG_ACT;
2448     case EL_AUSGANG_AUF:        return GFX_AUSGANG_AUF;
2449     case EL_SPIELFIGUR:         return GFX_SPIELFIGUR;
2450     case EL_SPIELER1:           return GFX_SPIELER1;
2451     case EL_SPIELER2:           return GFX_SPIELER2;
2452     case EL_SPIELER3:           return GFX_SPIELER3;
2453     case EL_SPIELER4:           return GFX_SPIELER4;
2454     case EL_KAEFER:             return GFX_KAEFER;
2455     case EL_KAEFER_RIGHT:       return GFX_KAEFER_RIGHT;
2456     case EL_KAEFER_UP:          return GFX_KAEFER_UP;
2457     case EL_KAEFER_LEFT:        return GFX_KAEFER_LEFT;
2458     case EL_KAEFER_DOWN:        return GFX_KAEFER_DOWN;
2459     case EL_FLIEGER:            return GFX_FLIEGER;
2460     case EL_FLIEGER_RIGHT:      return GFX_FLIEGER_RIGHT;
2461     case EL_FLIEGER_UP:         return GFX_FLIEGER_UP;
2462     case EL_FLIEGER_LEFT:       return GFX_FLIEGER_LEFT;
2463     case EL_FLIEGER_DOWN:       return GFX_FLIEGER_DOWN;
2464     case EL_BUTTERFLY:          return GFX_BUTTERFLY;
2465     case EL_BUTTERFLY_RIGHT:    return GFX_BUTTERFLY_RIGHT;
2466     case EL_BUTTERFLY_UP:       return GFX_BUTTERFLY_UP;
2467     case EL_BUTTERFLY_LEFT:     return GFX_BUTTERFLY_LEFT;
2468     case EL_BUTTERFLY_DOWN:     return GFX_BUTTERFLY_DOWN;
2469     case EL_FIREFLY:            return GFX_FIREFLY;
2470     case EL_FIREFLY_RIGHT:      return GFX_FIREFLY_RIGHT;
2471     case EL_FIREFLY_UP:         return GFX_FIREFLY_UP;
2472     case EL_FIREFLY_LEFT:       return GFX_FIREFLY_LEFT;
2473     case EL_FIREFLY_DOWN:       return GFX_FIREFLY_DOWN;
2474     case EL_MAMPFER:            return GFX_MAMPFER;
2475     case EL_ROBOT:              return GFX_ROBOT;
2476     case EL_BETON:              return GFX_BETON;
2477     case EL_DIAMANT:            return GFX_DIAMANT;
2478     case EL_MORAST_LEER:        return GFX_MORAST_LEER;
2479     case EL_MORAST_VOLL:        return GFX_MORAST_VOLL;
2480     case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
2481     case EL_TROPFEN:            return GFX_TROPFEN;
2482     case EL_BOMBE:              return GFX_BOMBE;
2483     case EL_MAGIC_WALL_OFF:     return GFX_MAGIC_WALL_OFF;
2484     case EL_MAGIC_WALL_EMPTY:   return GFX_MAGIC_WALL_EMPTY;
2485     case EL_MAGIC_WALL_EMPTYING:return GFX_MAGIC_WALL_EMPTY;
2486     case EL_MAGIC_WALL_FULL:    return GFX_MAGIC_WALL_FULL;
2487     case EL_MAGIC_WALL_DEAD:    return GFX_MAGIC_WALL_DEAD;
2488     case EL_SALZSAEURE:         return GFX_SALZSAEURE;
2489     case EL_AMOEBE_TOT:         return GFX_AMOEBE_TOT;
2490     case EL_AMOEBE_NASS:        return GFX_AMOEBE_NASS;
2491     case EL_AMOEBE_NORM:        return GFX_AMOEBE_NORM;
2492     case EL_AMOEBE_VOLL:        return GFX_AMOEBE_VOLL;
2493     case EL_AMOEBE_BD:          return GFX_AMOEBE_BD;
2494     case EL_AMOEBA2DIAM:        return GFX_AMOEBA2DIAM;
2495     case EL_AMOEBA_DRIPPING:    return GFX_AMOEBE_NASS;
2496     case EL_KOKOSNUSS:          return GFX_KOKOSNUSS;
2497     case EL_LIFE:               return GFX_LIFE;
2498     case EL_LIFE_ASYNC:         return GFX_LIFE_ASYNC;
2499     case EL_DYNAMITE_ACTIVE:    return GFX_DYNAMIT;
2500     case EL_BADEWANNE:          return GFX_BADEWANNE;
2501     case EL_BADEWANNE1:         return GFX_BADEWANNE1;
2502     case EL_BADEWANNE2:         return GFX_BADEWANNE2;
2503     case EL_BADEWANNE3:         return GFX_BADEWANNE3;
2504     case EL_BADEWANNE4:         return GFX_BADEWANNE4;
2505     case EL_BADEWANNE5:         return GFX_BADEWANNE5;
2506     case EL_ABLENK_AUS:         return GFX_ABLENK_AUS;
2507     case EL_ABLENK_EIN:         return GFX_ABLENK_EIN;
2508     case EL_SCHLUESSEL1:        return GFX_SCHLUESSEL1;
2509     case EL_SCHLUESSEL2:        return GFX_SCHLUESSEL2;
2510     case EL_SCHLUESSEL3:        return GFX_SCHLUESSEL3;
2511     case EL_SCHLUESSEL4:        return GFX_SCHLUESSEL4;
2512     case EL_PFORTE1:            return GFX_PFORTE1;
2513     case EL_PFORTE2:            return GFX_PFORTE2;
2514     case EL_PFORTE3:            return GFX_PFORTE3;
2515     case EL_PFORTE4:            return GFX_PFORTE4;
2516     case EL_PFORTE1X:           return GFX_PFORTE1X;
2517     case EL_PFORTE2X:           return GFX_PFORTE2X;
2518     case EL_PFORTE3X:           return GFX_PFORTE3X;
2519     case EL_PFORTE4X:           return GFX_PFORTE4X;
2520     case EL_DYNAMITE_INACTIVE:  return GFX_DYNAMIT_AUS;
2521     case EL_PACMAN:             return GFX_PACMAN;
2522     case EL_PACMAN_RIGHT:       return GFX_PACMAN_RIGHT;
2523     case EL_PACMAN_UP:          return GFX_PACMAN_UP;
2524     case EL_PACMAN_LEFT:        return GFX_PACMAN_LEFT;
2525     case EL_PACMAN_DOWN:        return GFX_PACMAN_DOWN;
2526     case EL_UNSICHTBAR:         return GFX_UNSICHTBAR;
2527     case EL_ERZ_EDEL:           return GFX_ERZ_EDEL;
2528     case EL_ERZ_DIAM:           return GFX_ERZ_DIAM;
2529     case EL_BIRNE_AUS:          return GFX_BIRNE_AUS;
2530     case EL_BIRNE_EIN:          return GFX_BIRNE_EIN;
2531     case EL_ZEIT_VOLL:          return GFX_ZEIT_VOLL;
2532     case EL_ZEIT_LEER:          return GFX_ZEIT_LEER;
2533     case EL_MAUER_LEBT:         return GFX_MAUER_LEBT;
2534     case EL_MAUER_X:            return GFX_MAUER_X;
2535     case EL_MAUER_Y:            return GFX_MAUER_Y;
2536     case EL_MAUER_XY:           return GFX_MAUER_XY;
2537     case EL_EDELSTEIN_BD:       return GFX_EDELSTEIN_BD;
2538     case EL_EDELSTEIN_GELB:     return GFX_EDELSTEIN_GELB;
2539     case EL_EDELSTEIN_ROT:      return GFX_EDELSTEIN_ROT;
2540     case EL_EDELSTEIN_LILA:     return GFX_EDELSTEIN_LILA;
2541     case EL_ERZ_EDEL_BD:        return GFX_ERZ_EDEL_BD;
2542     case EL_ERZ_EDEL_GELB:      return GFX_ERZ_EDEL_GELB;
2543     case EL_ERZ_EDEL_ROT:       return GFX_ERZ_EDEL_ROT;
2544     case EL_ERZ_EDEL_LILA:      return GFX_ERZ_EDEL_LILA;
2545     case EL_MAMPFER2:           return GFX_MAMPFER2;
2546     case EL_MAGIC_WALL_BD_OFF:  return GFX_MAGIC_WALL_BD_OFF;
2547     case EL_MAGIC_WALL_BD_EMPTY:return GFX_MAGIC_WALL_BD_EMPTY;
2548     case EL_MAGIC_WALL_BD_EMPTYING:return GFX_MAGIC_WALL_BD_EMPTY;
2549     case EL_MAGIC_WALL_BD_FULL: return GFX_MAGIC_WALL_BD_FULL;
2550     case EL_MAGIC_WALL_BD_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
2551     case EL_DYNABOMB_ACTIVE_1:  return GFX_DYNABOMB;
2552     case EL_DYNABOMB_ACTIVE_2:  return GFX_DYNABOMB;
2553     case EL_DYNABOMB_ACTIVE_3:  return GFX_DYNABOMB;
2554     case EL_DYNABOMB_ACTIVE_4:  return GFX_DYNABOMB;
2555     case EL_DYNABOMB_NR:        return GFX_DYNABOMB_NR;
2556     case EL_DYNABOMB_SZ:        return GFX_DYNABOMB_SZ;
2557     case EL_DYNABOMB_XL:        return GFX_DYNABOMB_XL;
2558     case EL_SOKOBAN_OBJEKT:     return GFX_SOKOBAN_OBJEKT;
2559     case EL_SOKOBAN_FELD_LEER:  return GFX_SOKOBAN_FELD_LEER;
2560     case EL_SOKOBAN_FELD_VOLL:  return GFX_SOKOBAN_FELD_VOLL;
2561     case EL_MOLE:               return GFX_MOLE;
2562     case EL_PINGUIN:            return GFX_PINGUIN;
2563     case EL_SCHWEIN:            return GFX_SCHWEIN;
2564     case EL_DRACHE:             return GFX_DRACHE;
2565     case EL_SONDE:              return GFX_SONDE;
2566     case EL_PFEIL_LEFT:         return GFX_PFEIL_LEFT;
2567     case EL_PFEIL_RIGHT:        return GFX_PFEIL_RIGHT;
2568     case EL_PFEIL_UP:           return GFX_PFEIL_UP;
2569     case EL_PFEIL_DOWN:         return GFX_PFEIL_DOWN;
2570     case EL_SPEED_PILL:         return GFX_SPEED_PILL;
2571     case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2572     case EL_SP_BUG_ACTIVE:      return GFX_SP_BUG_ACTIVE;
2573     case EL_SP_ZONK:            return GFX_SP_ZONK;
2574       /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2575     case EL_INVISIBLE_STEEL:    return GFX_INVISIBLE_STEEL;
2576     case EL_BLACK_ORB:          return GFX_BLACK_ORB;
2577     case EL_EM_GATE_1:          return GFX_EM_GATE_1;
2578     case EL_EM_GATE_2:          return GFX_EM_GATE_2;
2579     case EL_EM_GATE_3:          return GFX_EM_GATE_3;
2580     case EL_EM_GATE_4:          return GFX_EM_GATE_4;
2581     case EL_EM_GATE_1X:         return GFX_EM_GATE_1X;
2582     case EL_EM_GATE_2X:         return GFX_EM_GATE_2X;
2583     case EL_EM_GATE_3X:         return GFX_EM_GATE_3X;
2584     case EL_EM_GATE_4X:         return GFX_EM_GATE_4X;
2585     case EL_EM_KEY_1_FILE:      return GFX_EM_KEY_1;
2586     case EL_EM_KEY_2_FILE:      return GFX_EM_KEY_2;
2587     case EL_EM_KEY_3_FILE:      return GFX_EM_KEY_3;
2588     case EL_EM_KEY_4_FILE:      return GFX_EM_KEY_4;
2589     case EL_EM_KEY_1:           return GFX_EM_KEY_1;
2590     case EL_EM_KEY_2:           return GFX_EM_KEY_2;
2591     case EL_EM_KEY_3:           return GFX_EM_KEY_3;
2592     case EL_EM_KEY_4:           return GFX_EM_KEY_4;
2593     case EL_PEARL:              return GFX_PEARL;
2594     case EL_CRYSTAL:            return GFX_CRYSTAL;
2595     case EL_WALL_PEARL:         return GFX_WALL_PEARL;
2596     case EL_WALL_CRYSTAL:       return GFX_WALL_CRYSTAL;
2597     case EL_DOOR_WHITE:         return GFX_DOOR_WHITE;
2598     case EL_DOOR_WHITE_GRAY:    return GFX_DOOR_WHITE_GRAY;
2599     case EL_KEY_WHITE:          return GFX_KEY_WHITE;
2600     case EL_SHIELD_PASSIVE:     return GFX_SHIELD_PASSIVE;
2601     case EL_SHIELD_ACTIVE:      return GFX_SHIELD_ACTIVE;
2602     case EL_EXTRA_TIME:         return GFX_EXTRA_TIME;
2603     case EL_SWITCHGATE_OPEN:    return GFX_SWITCHGATE_OPEN;
2604     case EL_SWITCHGATE_CLOSED:  return GFX_SWITCHGATE_CLOSED;
2605     case EL_SWITCHGATE_SWITCH_1:return GFX_SWITCHGATE_SWITCH_1;
2606     case EL_SWITCHGATE_SWITCH_2:return GFX_SWITCHGATE_SWITCH_2;
2607     case EL_BELT1_LEFT:         return GFX_BELT1_LEFT;
2608     case EL_BELT1_MIDDLE:       return GFX_BELT1_MIDDLE;
2609     case EL_BELT1_RIGHT:        return GFX_BELT1_RIGHT;
2610     case EL_BELT1_SWITCH_LEFT:  return GFX_BELT1_SWITCH_LEFT;
2611     case EL_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2612     case EL_BELT1_SWITCH_RIGHT: return GFX_BELT1_SWITCH_RIGHT;
2613     case EL_BELT2_LEFT:         return GFX_BELT2_LEFT;
2614     case EL_BELT2_MIDDLE:       return GFX_BELT2_MIDDLE;
2615     case EL_BELT2_RIGHT:        return GFX_BELT2_RIGHT;
2616     case EL_BELT2_SWITCH_LEFT:  return GFX_BELT2_SWITCH_LEFT;
2617     case EL_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2618     case EL_BELT2_SWITCH_RIGHT: return GFX_BELT2_SWITCH_RIGHT;
2619     case EL_BELT3_LEFT:         return GFX_BELT3_LEFT;
2620     case EL_BELT3_MIDDLE:       return GFX_BELT3_MIDDLE;
2621     case EL_BELT3_RIGHT:        return GFX_BELT3_RIGHT;
2622     case EL_BELT3_SWITCH_LEFT:  return GFX_BELT3_SWITCH_LEFT;
2623     case EL_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2624     case EL_BELT3_SWITCH_RIGHT: return GFX_BELT3_SWITCH_RIGHT;
2625     case EL_BELT4_LEFT:         return GFX_BELT4_LEFT;
2626     case EL_BELT4_MIDDLE:       return GFX_BELT4_MIDDLE;
2627     case EL_BELT4_RIGHT:        return GFX_BELT4_RIGHT;
2628     case EL_BELT4_SWITCH_LEFT:  return GFX_BELT4_SWITCH_LEFT;
2629     case EL_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2630     case EL_BELT4_SWITCH_RIGHT: return GFX_BELT4_SWITCH_RIGHT;
2631     case EL_LANDMINE:           return GFX_LANDMINE;
2632     case EL_ENVELOPE:           return GFX_ENVELOPE;
2633     case EL_LIGHT_SWITCH_OFF:   return GFX_LIGHT_SWITCH_OFF;
2634     case EL_LIGHT_SWITCH_ON:    return GFX_LIGHT_SWITCH_ON;
2635     case EL_SIGN_EXCLAMATION:   return GFX_SIGN_EXCLAMATION;
2636     case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2637     case EL_SIGN_STOP:          return GFX_SIGN_STOP;
2638     case EL_SIGN_WHEELCHAIR:    return GFX_SIGN_WHEELCHAIR;
2639     case EL_SIGN_PARKING:       return GFX_SIGN_PARKING;
2640     case EL_SIGN_ONEWAY:        return GFX_SIGN_ONEWAY;
2641     case EL_SIGN_HEART:         return GFX_SIGN_HEART;
2642     case EL_SIGN_TRIANGLE:      return GFX_SIGN_TRIANGLE;
2643     case EL_SIGN_ROUND:         return GFX_SIGN_ROUND;
2644     case EL_SIGN_EXIT:          return GFX_SIGN_EXIT;
2645     case EL_SIGN_YINYANG:       return GFX_SIGN_YINYANG;
2646     case EL_SIGN_OTHER:         return GFX_SIGN_OTHER;
2647     case EL_MOLE_LEFT:          return GFX_MOLE_LEFT;
2648     case EL_MOLE_RIGHT:         return GFX_MOLE_RIGHT;
2649     case EL_MOLE_UP:            return GFX_MOLE_UP;
2650     case EL_MOLE_DOWN:          return GFX_MOLE_DOWN;
2651     case EL_STEEL_SLANTED:      return GFX_STEEL_SLANTED;
2652     case EL_SAND_INVISIBLE:     return GFX_SAND_INVISIBLE;
2653     case EL_DX_UNKNOWN_15:      return GFX_DX_UNKNOWN_15;
2654     case EL_DX_UNKNOWN_42:      return GFX_DX_UNKNOWN_42;
2655     case EL_TIMEGATE_OPEN:      return GFX_TIMEGATE_OPEN;
2656     case EL_TIMEGATE_CLOSED:    return GFX_TIMEGATE_CLOSED;
2657     case EL_TIMEGATE_SWITCH_ON: return GFX_TIMEGATE_SWITCH;
2658     case EL_TIMEGATE_SWITCH_OFF:return GFX_TIMEGATE_SWITCH;
2659     case EL_BALLOON:            return GFX_BALLOON;
2660     case EL_BALLOON_SEND_LEFT:  return GFX_BALLOON_SEND_LEFT;
2661     case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2662     case EL_BALLOON_SEND_UP:    return GFX_BALLOON_SEND_UP;
2663     case EL_BALLOON_SEND_DOWN:  return GFX_BALLOON_SEND_DOWN;
2664     case EL_BALLOON_SEND_ANY:   return GFX_BALLOON_SEND_ANY;
2665     case EL_EMC_STEEL_WALL_1:   return GFX_EMC_STEEL_WALL_1;
2666     case EL_EMC_STEEL_WALL_2:   return GFX_EMC_STEEL_WALL_2;
2667     case EL_EMC_STEEL_WALL_3:   return GFX_EMC_STEEL_WALL_3;
2668     case EL_EMC_STEEL_WALL_4:   return GFX_EMC_STEEL_WALL_4;
2669     case EL_EMC_WALL_1:         return GFX_EMC_WALL_1;
2670     case EL_EMC_WALL_2:         return GFX_EMC_WALL_2;
2671     case EL_EMC_WALL_3:         return GFX_EMC_WALL_3;
2672     case EL_EMC_WALL_4:         return GFX_EMC_WALL_4;
2673     case EL_EMC_WALL_5:         return GFX_EMC_WALL_5;
2674     case EL_EMC_WALL_6:         return GFX_EMC_WALL_6;
2675     case EL_EMC_WALL_7:         return GFX_EMC_WALL_7;
2676     case EL_EMC_WALL_8:         return GFX_EMC_WALL_8;
2677     case EL_TUBE_CROSS:         return GFX_TUBE_CROSS;
2678     case EL_TUBE_VERTICAL:      return GFX_TUBE_VERTICAL;
2679     case EL_TUBE_HORIZONTAL:    return GFX_TUBE_HORIZONTAL;
2680     case EL_TUBE_VERT_LEFT:     return GFX_TUBE_VERT_LEFT;
2681     case EL_TUBE_VERT_RIGHT:    return GFX_TUBE_VERT_RIGHT;
2682     case EL_TUBE_HORIZ_UP:      return GFX_TUBE_HORIZ_UP;
2683     case EL_TUBE_HORIZ_DOWN:    return GFX_TUBE_HORIZ_DOWN;
2684     case EL_TUBE_LEFT_UP:       return GFX_TUBE_LEFT_UP;
2685     case EL_TUBE_LEFT_DOWN:     return GFX_TUBE_LEFT_DOWN;
2686     case EL_TUBE_RIGHT_UP:      return GFX_TUBE_RIGHT_UP;
2687     case EL_TUBE_RIGHT_DOWN:    return GFX_TUBE_RIGHT_DOWN;
2688     case EL_SPRING:             return GFX_SPRING;
2689     case EL_SPRING_MOVING:      return GFX_SPRING;
2690     case EL_TRAP_INACTIVE:      return GFX_TRAP_INACTIVE;
2691     case EL_TRAP_ACTIVE:        return GFX_TRAP_ACTIVE;
2692     case EL_BD_WALL:            return GFX_BD_WALL;
2693     case EL_BD_ROCK:            return GFX_BD_ROCK;
2694     case EL_DX_SUPABOMB:        return GFX_DX_SUPABOMB;
2695     case EL_SP_MURPHY_CLONE:    return GFX_SP_MURPHY_CLONE;
2696
2697     default:
2698     {
2699       if (IS_CHAR(element))
2700         return GFX_CHAR_START + (element - EL_CHAR_START);
2701       else if (element >= EL_SP_START && element <= EL_SP_END)
2702       {
2703         int nr_element = element - EL_SP_START;
2704         int gfx_per_line = 8;
2705         int nr_graphic =
2706           (nr_element / gfx_per_line) * SP_PER_LINE +
2707           (nr_element % gfx_per_line);
2708
2709         return GFX_START_ROCKSSP + nr_graphic;
2710       }
2711       else
2712         return -1;
2713     }
2714   }
2715 }