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