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