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