1 /***********************************************************
2 * Mirror Magic -- McDuffin's Revenge                       *
3 *----------------------------------------------------------*
4 * (c) 1994-2001 Artsoft Entertainment                      *
5 *               Holger Schemel                             *
6 *               Detmolder Strasse 189                      *
7 *               33604 Bielefeld                            *
8 *               Germany                                    *
9 *               e-mail: info@artsoft.org                   *
10 *----------------------------------------------------------*
11 * tools.c                                                  *
12 ***********************************************************/
13 
14 #include <stdarg.h>
15 
16 #ifdef __FreeBSD__
17 #include <sys/joystick.h>
18 #endif
19 
20 #include "libgame/libgame.h"
21 
22 #include "tools.h"
23 #include "game.h"
24 #include "events.h"
25 #include "cartoons.h"
26 
27 #ifdef MSDOS
28 extern boolean wait_for_vsync;
29 #endif
30 
31 /* tool button identifiers */
32 #define TOOL_CTRL_ID_YES	0
33 #define TOOL_CTRL_ID_NO		1
34 #define TOOL_CTRL_ID_CONFIRM	2
35 
36 #define NUM_TOOL_BUTTONS	3
37 
38 /* forward declaration for internal use */
39 static int getGraphicAnimationPhase(int, int, int);
40 static void UnmapToolButtons();
41 static void HandleToolButtons(struct GadgetInfo *);
42 
43 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
44 static int request_gadget_id = -1;
45 
SetDrawtoField(int mode)46 void SetDrawtoField(int mode)
47 {
48   /* DRAW_DIRECT, DRAW_BACKBUFFER */
49 
50   FX = SX;
51   FY = SY;
52   BX1 = 0;
53   BY1 = 0;
54   BX2 = SCR_FIELDX - 1;
55   BY2 = SCR_FIELDY - 1;
56   redraw_x1 = 0;
57   redraw_y1 = 0;
58 
59   drawto_field = backbuffer;
60 }
61 
BackToFront()62 void BackToFront()
63 {
64   int x,y;
65   DrawBuffer *buffer = drawto_field;
66 
67   if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
68     redraw_mask |= REDRAW_FIELD;
69 
70   if (redraw_mask & REDRAW_FIELD)
71     redraw_mask &= ~REDRAW_TILES;
72 
73   if (!redraw_mask)
74     return;
75 
76   if (global.fps_slowdown && game_status == PLAYING)
77   {
78     static boolean last_frame_skipped = FALSE;
79     boolean skip_even_when_not_scrolling = TRUE;
80     boolean just_scrolling = (ScreenMovDir != 0);
81     boolean verbose = FALSE;
82 
83     if (global.fps_slowdown_factor > 1 &&
84 	(FrameCounter % global.fps_slowdown_factor) &&
85 	(just_scrolling || skip_even_when_not_scrolling))
86     {
87       redraw_mask &= ~REDRAW_MAIN;
88 
89       last_frame_skipped = TRUE;
90 
91       if (verbose)
92 	printf("FRAME SKIPPED\n");
93     }
94     else
95     {
96       if (last_frame_skipped)
97 	redraw_mask |= REDRAW_FIELD;
98 
99       last_frame_skipped = FALSE;
100 
101       if (verbose)
102 	printf("frame not skipped\n");
103     }
104   }
105 
106   /* synchronize X11 graphics at this point; if we would synchronize the
107      display immediately after the buffer switching (after the XFlush),
108      this could mean that we have to wait for the graphics to complete,
109      although we could go on doing calculations for the next frame */
110 
111   SyncDisplay();
112 
113   if (redraw_mask & REDRAW_ALL)
114   {
115     BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
116     redraw_mask = 0;
117   }
118 
119   if (redraw_mask & REDRAW_FIELD)
120   {
121     BlitBitmap(backbuffer, window,
122 	       REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
123 
124     redraw_mask &= ~REDRAW_MAIN;
125   }
126 
127   if (redraw_mask & REDRAW_DOORS)
128   {
129     if (redraw_mask & REDRAW_DOOR_1)
130       BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
131     redraw_mask &= ~REDRAW_DOORS;
132   }
133 
134   if (redraw_mask & REDRAW_MICROLEVEL)
135   {
136     BlitBitmap(backbuffer, window,
137 	       MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
138 	       MICROLEV_XPOS, MICROLEV_YPOS);
139 
140     redraw_mask &= ~REDRAW_MICROLEVEL;
141   }
142 
143   if (redraw_mask & REDRAW_MICROLABEL)
144   {
145     BlitBitmap(backbuffer, window,
146 	       MICROLABEL_XPOS, MICROLABEL_YPOS,
147 	       MICROLABEL_XSIZE, MICROLABEL_YSIZE,
148 	       MICROLABEL_XPOS, MICROLABEL_YPOS);
149 
150     redraw_mask &= ~REDRAW_MICROLABEL;
151   }
152 
153   if (redraw_mask & REDRAW_TILES)
154   {
155     for(x=0; x<SCR_FIELDX; x++)
156       for(y=0; y<SCR_FIELDY; y++)
157 	if (redraw[redraw_x1 + x][redraw_y1 + y])
158 	  BlitBitmap(buffer, window,
159 		     FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
160 		     SX + x * TILEX, SY + y * TILEY);
161   }
162 
163   if (redraw_mask & REDRAW_FPS)		/* display frames per second */
164   {
165     char text[100];
166     char info1[100];
167 
168     sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
169     if (!global.fps_slowdown)
170       info1[0] = '\0';
171 
172     sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
173     DrawTextExt(window, SX, SY, text, FS_SMALL, FC_YELLOW);
174   }
175 
176   FlushDisplay();
177 
178   for(x=0; x<MAX_BUF_XSIZE; x++)
179     for(y=0; y<MAX_BUF_YSIZE; y++)
180       redraw[x][y] = 0;
181   redraw_tiles = 0;
182   redraw_mask = 0;
183 }
184 
FadeToFront()185 void FadeToFront()
186 {
187 #if 0
188   long fading_delay = 300;
189 
190   if (setup.fading && (redraw_mask & REDRAW_FIELD))
191   {
192 #endif
193 
194 #if 0
195     int x,y;
196 
197     ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
198     FlushDisplay();
199 
200     for(i=0;i<2*FULL_SYSIZE;i++)
201     {
202       for(y=0;y<FULL_SYSIZE;y++)
203       {
204 	BlitBitmap(backbuffer, window,
205 		   REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
206       }
207       FlushDisplay();
208       Delay(10);
209     }
210 #endif
211 
212 #if 0
213     for(i=1;i<FULL_SYSIZE;i+=2)
214       BlitBitmap(backbuffer, window,
215 		 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
216     FlushDisplay();
217     Delay(fading_delay);
218 #endif
219 
220 #if 0
221     SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
222     BlitBitmapMasked(backbuffer, window,
223 		     REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
224 		     REAL_SX,REAL_SY);
225     FlushDisplay();
226     Delay(fading_delay);
227 
228     SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
229     BlitBitmapMasked(backbuffer, window,
230 		     REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
231 		     REAL_SX,REAL_SY);
232     FlushDisplay();
233     Delay(fading_delay);
234 
235     SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
236     BlitBitmapMasked(backbuffer, window,
237 		     REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
238 		     REAL_SX,REAL_SY);
239     FlushDisplay();
240     Delay(fading_delay);
241 
242     SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
243     BlitBitmapMasked(backbuffer, window,
244 		     REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
245 		     REAL_SX,REAL_SY);
246     FlushDisplay();
247     Delay(fading_delay);
248 
249     redraw_mask &= ~REDRAW_MAIN;
250   }
251 #endif
252 
253   BackToFront();
254 }
255 
ClearWindow()256 void ClearWindow()
257 {
258   ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
259 
260   SetDrawtoField(DRAW_BACKBUFFER);
261 
262   redraw_mask |= REDRAW_FIELD;
263 }
264 
MarkTileDirty(int x,int y)265 void MarkTileDirty(int x, int y)
266 {
267   int xx = redraw_x1 + x;
268   int yy = redraw_y1 + y;
269 
270   if (!redraw[xx][yy])
271     redraw_tiles++;
272 
273   redraw[xx][yy] = TRUE;
274   redraw_mask |= REDRAW_TILES;
275 }
276 
getGraphicAnimationPhase(int frames,int delay,int mode)277 static int getGraphicAnimationPhase(int frames, int delay, int mode)
278 {
279   int phase;
280 
281   if (mode == ANIM_OSCILLATE)
282   {
283     int max_anim_frames = 2 * frames - 2;
284     phase = (FrameCounter % (delay * max_anim_frames)) / delay;
285     phase = (phase < frames ? phase : max_anim_frames - phase);
286   }
287   else
288     phase = (FrameCounter % (delay * frames)) / delay;
289 
290   if (mode == ANIM_REVERSE)
291     phase = -phase;
292 
293   return(phase);
294 }
295 
DrawGraphicAnimationExt(int x,int y,int graphic,int frames,int delay,int mode,int mask_mode)296 void DrawGraphicAnimationExt(int x, int y, int graphic,
297 			     int frames, int delay, int mode, int mask_mode)
298 {
299   int phase = getGraphicAnimationPhase(frames, delay, mode);
300 
301   if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
302   {
303     if (mask_mode == USE_MASKING)
304       DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
305     else
306       DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
307   }
308 }
309 
DrawGraphicAnimation(int x,int y,int graphic,int frames,int delay,int mode)310 void DrawGraphicAnimation(int x, int y, int graphic,
311 			  int frames, int delay, int mode)
312 {
313   DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
314 }
315 
DrawGraphicAnimationThruMask(int x,int y,int graphic,int frames,int delay,int mode)316 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
317 				  int frames, int delay, int mode)
318 {
319   DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
320 }
321 
getGraphicSource(int graphic,int * bitmap_nr,int * x,int * y)322 void getGraphicSource(int graphic, int *bitmap_nr, int *x, int *y)
323 {
324   if (graphic >= GFX_START_MIRRORSCREEN && graphic <= GFX_END_MIRRORSCREEN)
325   {
326     graphic -= GFX_START_MIRRORSCREEN;
327     *bitmap_nr = PIX_BACK;
328     *x = SX + (graphic % GFX_PER_LINE) * TILEX;
329     *y = SY + (graphic / GFX_PER_LINE) * TILEY;
330   }
331   else if (graphic >= GFX_START_MIRRORFONT && graphic <= GFX_END_MIRRORFONT)
332   {
333     graphic -= GFX_START_MIRRORFONT;
334     *bitmap_nr = PIX_BIGFONT;
335     *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
336     *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
337 	  FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
338   }
339   else if (graphic >= GFX_START_MIRRORDF && graphic <= GFX_END_MIRRORDF)
340   {
341     graphic -= GFX_START_MIRRORDF;
342     *bitmap_nr = PIX_DF;
343     *x = (graphic % DF_PER_LINE) * TILEX;
344     *y = (graphic / DF_PER_LINE) * TILEY;
345   }
346   else
347   {
348     *bitmap_nr = PIX_BIGFONT;
349     *x = 0;
350     *y = 0;
351   }
352 }
353 
DrawGraphic(int x,int y,int graphic)354 void DrawGraphic(int x, int y, int graphic)
355 {
356 #if DEBUG
357   if (!IN_SCR_FIELD(x,y))
358   {
359     printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
360     printf("DrawGraphic(): This should never happen!\n");
361 
362 #if 1
363     {
364       int i=0;
365       i=i/i;
366     }
367 #endif
368 
369     return;
370   }
371 #endif
372 
373   DrawGraphicExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
374   MarkTileDirty(x, y);
375 }
376 
DrawGraphicExt(DrawBuffer * d,int x,int y,int graphic)377 void DrawGraphicExt(DrawBuffer *d, int x, int y, int graphic)
378 {
379   int bitmap_nr;
380   int src_x, src_y;
381 
382   getGraphicSource(graphic, &bitmap_nr, &src_x, &src_y);
383   BlitBitmap(pix[bitmap_nr], d, src_x, src_y, TILEX, TILEY, x, y);
384 }
385 
DrawGraphicThruMask(int x,int y,int graphic)386 void DrawGraphicThruMask(int x, int y, int graphic)
387 {
388 #if DEBUG
389   if (!IN_SCR_FIELD(x,y))
390   {
391     printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
392     printf("DrawGraphicThruMask(): This should never happen!\n");
393     return;
394   }
395 #endif
396 
397   DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
398   MarkTileDirty(x,y);
399 }
400 
DrawGraphicThruMaskExt(DrawBuffer * d,int dest_x,int dest_y,int graphic)401 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
402 {
403   int tile = graphic;
404   int bitmap_nr;
405   int src_x, src_y;
406   Bitmap *src_bitmap;
407   GC drawing_gc;
408 
409   if (graphic == GFX_EMPTY)
410     return;
411 
412   getGraphicSource(graphic, &bitmap_nr, &src_x, &src_y);
413   src_bitmap = pix[bitmap_nr];
414   drawing_gc = pix[bitmap_nr]->stored_clip_gc;
415 
416   if (tile_clipmask[tile] != None)
417   {
418     SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
419     SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
420     BlitBitmapMasked(src_bitmap, d,
421 		     src_x, src_y, TILEX, TILEY, dest_x, dest_y);
422   }
423   else
424   {
425 #if DEBUG
426 #ifndef TARGET_SDL
427     printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
428 #endif
429 #endif
430 
431     SetClipOrigin(src_bitmap, drawing_gc, dest_x-src_x, dest_y-src_y);
432     BlitBitmapMasked(src_bitmap, d,
433 		     src_x, src_y, TILEX, TILEY, dest_x, dest_y);
434   }
435 }
436 
DrawMiniGraphic(int x,int y,int graphic)437 void DrawMiniGraphic(int x, int y, int graphic)
438 {
439   DrawMiniGraphicExt(drawto, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
440   MarkTileDirty(x/2, y/2);
441 }
442 
getMiniGraphicSource(int graphic,Bitmap ** bitmap,int * x,int * y)443 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
444 {
445   if (graphic >= GFX_START_MIRRORSCREEN && graphic <= GFX_END_MIRRORSCREEN)
446   {
447     graphic -= GFX_START_MIRRORSCREEN;
448     *bitmap = pix[PIX_BACK];
449     *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
450     *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
451   }
452   else if (graphic >= GFX_START_PSEUDO && graphic <= GFX_END_PSEUDO)
453   {
454     if (graphic == GFX_DF_WALL_STEEL || graphic == GFX_DF_WALL_WOOD)
455     {
456       int graphic2 = GFX_DF_WALL_SEVERAL - GFX_START_MIRRORDF;
457       *bitmap = pix[PIX_DF];
458       *x = (graphic2 % DF_PER_LINE) * TILEX;
459       *y = (graphic2 / DF_PER_LINE) * TILEY;
460 
461       if (graphic == GFX_DF_WALL_WOOD)
462 	*x += MINI_TILEX;
463     }
464     else
465     {
466       int graphic2 = GFX_WALL_SEVERAL - GFX_START_MIRRORSCREEN;
467       *bitmap = pix[PIX_BACK];
468       *x = GFX_STARTX + (graphic2 % GFX_PER_LINE) * TILEX;
469       *y = GFX_STARTY + (graphic2 / GFX_PER_LINE) * TILEY;
470 
471       if (graphic == GFX_WALL_WOOD || graphic == GFX_WALL_AMOEBA)
472 	*x += MINI_TILEX;
473       if (graphic == GFX_WALL_ICE || graphic == GFX_WALL_AMOEBA)
474 	*y += MINI_TILEY;
475     }
476   }
477   else if (graphic >= GFX_START_MIRRORFONT && graphic <= GFX_END_MIRRORFONT)
478   {
479     graphic -= GFX_START_MIRRORFONT;
480     *bitmap = pix[PIX_SMALLFONT];
481     *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
482     *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
483 	      FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
484   }
485   else if (graphic >= GFX_START_MIRRORDF && graphic <= GFX_END_MIRRORDF)
486   {
487     graphic -= GFX_START_MIRRORDF;
488     *bitmap = pix[PIX_DF];
489     *x = MINI_DF_STARTX + (graphic % MINI_DF_PER_LINE) * MINI_TILEX;
490     *y = MINI_DF_STARTY + (graphic / MINI_DF_PER_LINE) * MINI_TILEY;
491   }
492   else
493   {
494     *bitmap = pix[PIX_BIGFONT];
495     *x = 0;
496     *y = 0;
497   }
498 }
499 
getMicroGraphicSource(int graphic,Bitmap ** bitmap,int * x,int * y)500 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
501 {
502   if (graphic >= GFX_START_MIRRORSCREEN && graphic <= GFX_END_MIRRORSCREEN)
503   {
504     graphic -= GFX_START_MIRRORSCREEN;
505     *bitmap = pix[PIX_BACK];
506     *x = MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX;
507     *y = MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY;
508   }
509   else if (graphic >= GFX_START_PSEUDO && graphic <= GFX_END_PSEUDO)
510   {
511     if (graphic == GFX_DF_WALL_STEEL || graphic == GFX_DF_WALL_WOOD)
512     {
513       int graphic2 = GFX_DF_WALL_SEVERAL - GFX_START_MIRRORDF;
514       *bitmap = pix[PIX_DF];
515       *x = MICRO_DF_STARTX + (graphic2 % MICRO_DF_PER_LINE) * MICRO_TILEX;
516       *y = MICRO_DF_STARTY + (graphic2 / MICRO_DF_PER_LINE) * MICRO_TILEY;
517 
518       if (graphic == GFX_DF_WALL_WOOD)
519 	*x += MICRO_WALLX;
520     }
521     else
522     {
523       int graphic2 = GFX_WALL_SEVERAL - GFX_START_MIRRORSCREEN;
524       *bitmap = pix[PIX_BACK];
525       *x = MICRO_GFX_STARTX + (graphic2 % MICRO_GFX_PER_LINE) * MICRO_TILEX;
526       *y = MICRO_GFX_STARTY + (graphic2 / MICRO_GFX_PER_LINE) * MICRO_TILEY;
527 
528       if (graphic == GFX_WALL_WOOD || graphic == GFX_WALL_AMOEBA)
529 	*x += MICRO_WALLX;
530       if (graphic == GFX_WALL_ICE || graphic == GFX_WALL_AMOEBA)
531 	*y += MICRO_WALLY;
532     }
533   }
534   else if (graphic >= GFX_START_MIRRORFONT && graphic <= GFX_END_MIRRORFONT)
535   {
536     graphic -= GFX_START_MIRRORFONT;
537     *bitmap = pix[PIX_DF];
538     *x = MICRO_FONT_STARTX + (graphic % MICRO_FONT_PER_LINE) * MICRO_TILEX;
539     *y = MICRO_FONT_STARTY + (graphic / MICRO_FONT_PER_LINE) * MICRO_TILEY;
540   }
541   else if (graphic >= GFX_START_MIRRORDF && graphic <= GFX_END_MIRRORDF)
542   {
543     graphic -= GFX_START_MIRRORDF;
544     *bitmap = pix[PIX_DF];
545     *x = MICRO_DF_STARTX + (graphic % MICRO_DF_PER_LINE) * MICRO_TILEX;
546     *y = MICRO_DF_STARTY + (graphic / MICRO_DF_PER_LINE) * MICRO_TILEY;
547   }
548   else
549   {
550     *bitmap = pix[PIX_BIGFONT];
551     *x = 0;
552     *y = 0;
553   }
554 }
555 
DrawMiniGraphicExt(DrawBuffer * d,int x,int y,int graphic)556 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
557 {
558   Bitmap *bitmap;
559   int src_x, src_y;
560 
561   getMiniGraphicSource(graphic, &bitmap, &src_x, &src_y);
562   BlitBitmap(bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
563 }
564 
DrawGraphicShifted(int x,int y,int dx,int dy,int graphic,int cut_mode,int mask_mode)565 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
566 			int cut_mode, int mask_mode)
567 {
568   int width = TILEX, height = TILEY;
569   int cx = 0, cy = 0;
570   int src_x, src_y, dest_x, dest_y;
571   int tile = graphic;
572   int bitmap_nr;
573   Bitmap *src_bitmap;
574   GC drawing_gc;
575 
576   if (graphic < 0)
577   {
578     DrawGraphic(x, y, graphic);
579     return;
580   }
581 
582   if (dx || dy)			/* Verschiebung der Grafik? */
583   {
584     if (x < BX1)		/* Element kommt von links ins Bild */
585     {
586       x = BX1;
587       width = dx;
588       cx = TILEX - dx;
589       dx = 0;
590     }
591     else if (x > BX2)		/* Element kommt von rechts ins Bild */
592     {
593       x = BX2;
594       width = -dx;
595       dx = TILEX + dx;
596     }
597     else if (x==BX1 && dx < 0)	/* Element verl��t links das Bild */
598     {
599       width += dx;
600       cx = -dx;
601       dx = 0;
602     }
603     else if (x==BX2 && dx > 0)	/* Element verl��t rechts das Bild */
604       width -= dx;
605     else if (dx)		/* allg. Bewegung in x-Richtung */
606       MarkTileDirty(x + SIGN(dx), y);
607 
608     if (y < BY1)		/* Element kommt von oben ins Bild */
609     {
610       if (cut_mode==CUT_BELOW)	/* Element oberhalb des Bildes */
611 	return;
612 
613       y = BY1;
614       height = dy;
615       cy = TILEY - dy;
616       dy = 0;
617     }
618     else if (y > BY2)		/* Element kommt von unten ins Bild */
619     {
620       y = BY2;
621       height = -dy;
622       dy = TILEY + dy;
623     }
624     else if (y==BY1 && dy < 0)	/* Element verl��t oben das Bild */
625     {
626       height += dy;
627       cy = -dy;
628       dy = 0;
629     }
630     else if (dy > 0 && cut_mode == CUT_ABOVE)
631     {
632       if (y == BY2)		/* Element unterhalb des Bildes */
633 	return;
634 
635       height = dy;
636       cy = TILEY - dy;
637       dy = TILEY;
638       MarkTileDirty(x, y + 1);
639     }				/* Element verl��t unten das Bild */
640     else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
641       height -= dy;
642     else if (dy)		/* allg. Bewegung in y-Richtung */
643       MarkTileDirty(x, y + SIGN(dy));
644   }
645 
646   getGraphicSource(graphic, &bitmap_nr, &src_x, &src_y);
647   src_bitmap = pix[bitmap_nr];
648   drawing_gc = pix[bitmap_nr]->stored_clip_gc;
649 
650   src_x += cx;
651   src_y += cy;
652 
653   dest_x = FX + x * TILEX + dx;
654   dest_y = FY + y * TILEY + dy;
655 
656 #if DEBUG
657   if (!IN_SCR_FIELD(x,y))
658   {
659     printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
660     printf("DrawGraphicShifted(): This should never happen!\n");
661     return;
662   }
663 #endif
664 
665   if (mask_mode == USE_MASKING)
666   {
667     if (tile_clipmask[tile] != None)
668     {
669       SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
670       SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
671       BlitBitmapMasked(src_bitmap, drawto_field,
672 		       src_x, src_y, TILEX, TILEY, dest_x, dest_y);
673     }
674     else
675     {
676 #if DEBUG
677 #ifndef	TARGET_SDL
678       printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
679 #endif
680 #endif
681 
682       SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
683       BlitBitmapMasked(src_bitmap, drawto_field,
684 		       src_x, src_y, width, height, dest_x, dest_y);
685     }
686   }
687   else
688     BlitBitmap(pix[bitmap_nr], drawto_field,
689 	       src_x, src_y, width, height, dest_x, dest_y);
690 
691   MarkTileDirty(x,y);
692 }
693 
DrawGraphicShiftedThruMask(int x,int y,int dx,int dy,int graphic,int cut_mode)694 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
695 				int cut_mode)
696 {
697   DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
698 }
699 
DrawScreenElementExt(int x,int y,int dx,int dy,int element,int cut_mode,int mask_mode)700 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
701 			  int cut_mode, int mask_mode)
702 {
703   int ux = LEVELX(x), uy = LEVELY(y);
704   int graphic = el2gfx(element);
705   int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
706   int phase2  = phase8 / 4;
707   int dir = MovDir[ux][uy];
708 
709   if (element == EL_PACMAN)
710   {
711     graphic += 4 * !phase2;
712 
713     if (dir == MV_UP)
714       graphic += 1;
715     else if (dir == MV_LEFT)
716       graphic += 2;
717     else if (dir == MV_DOWN)
718       graphic += 3;
719   }
720 
721   if (dx || dy)
722     DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
723   else if (mask_mode == USE_MASKING)
724     DrawGraphicThruMask(x, y, graphic);
725   else
726     DrawGraphic(x, y, graphic);
727 }
728 
DrawLevelElementExt(int x,int y,int dx,int dy,int element,int cut_mode,int mask_mode)729 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
730 			 int cut_mode, int mask_mode)
731 {
732   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
733     DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
734 			 cut_mode, mask_mode);
735 }
736 
DrawScreenElementShifted(int x,int y,int dx,int dy,int element,int cut_mode)737 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
738 			      int cut_mode)
739 {
740   DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
741 }
742 
DrawLevelElementShifted(int x,int y,int dx,int dy,int element,int cut_mode)743 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
744 			     int cut_mode)
745 {
746   DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
747 }
748 
DrawScreenElementThruMask(int x,int y,int element)749 void DrawScreenElementThruMask(int x, int y, int element)
750 {
751   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
752 }
753 
DrawLevelElementThruMask(int x,int y,int element)754 void DrawLevelElementThruMask(int x, int y, int element)
755 {
756   DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
757 }
758 
DrawLevelFieldThruMask(int x,int y)759 void DrawLevelFieldThruMask(int x, int y)
760 {
761   DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
762 }
763 
DrawScreenElement(int x,int y,int element)764 void DrawScreenElement(int x, int y, int element)
765 {
766   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
767 }
768 
DrawLevelElement(int x,int y,int element)769 void DrawLevelElement(int x, int y, int element)
770 {
771   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
772     DrawScreenElement(SCREENX(x), SCREENY(y), element);
773 }
774 
DrawScreenField(int x,int y)775 void DrawScreenField(int x, int y)
776 {
777   int element = Feld[x][y];
778 
779   if (!IN_LEV_FIELD(x, y))
780     return;
781 
782   if (IS_MOVING(x, y))
783   {
784     int horiz_move = (MovDir[x][y] == MV_LEFT || MovDir[x][y] == MV_RIGHT);
785 
786     DrawScreenElement(x, y, EL_EMPTY);
787 
788     if (horiz_move)
789       DrawScreenElementShifted(x, y, MovPos[x][y], 0, element, NO_CUTTING);
790     else
791       DrawScreenElementShifted(x, y, 0, MovPos[x][y], element, NO_CUTTING);
792   }
793   else if (IS_BLOCKED(x, y))
794   {
795     int oldx, oldy;
796     int sx, sy;
797     int horiz_move;
798 
799     Blocked2Moving(x, y, &oldx, &oldy);
800     sx = SCREENX(oldx);
801     sy = SCREENY(oldy);
802     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
803 		  MovDir[oldx][oldy] == MV_RIGHT);
804 
805     DrawScreenElement(x, y, EL_EMPTY);
806     element = Feld[oldx][oldy];
807 
808     if (horiz_move)
809       DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
810     else
811       DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,NO_CUTTING);
812   }
813   else if (IS_DRAWABLE(element))
814     DrawScreenElement(x, y, element);
815   else
816     DrawScreenElement(x, y, EL_EMPTY);
817 }
818 
DrawLevelField(int x,int y)819 void DrawLevelField(int x, int y)
820 {
821   DrawScreenField(x, y);
822 }
823 
DrawMiniElement(int x,int y,int element)824 void DrawMiniElement(int x, int y, int element)
825 {
826   int graphic;
827 
828   if (!element)
829   {
830     DrawMiniGraphic(x, y, GFX_EMPTY);
831     return;
832   }
833 
834   graphic = el2gfx(element);
835   DrawMiniGraphic(x, y, graphic);
836 }
837 
DrawMiniElementOrWall(int sx,int sy,int scroll_x,int scroll_y)838 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
839 {
840   int x = sx + scroll_x, y = sy + scroll_y;
841 
842   if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
843     DrawMiniElement(sx, sy, EL_EMPTY);
844   else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
845     DrawMiniElement(sx, sy, Feld[x][y]);
846 }
847 
848 
849 #if 0
850 void DrawMicroElement(int xpos, int ypos, int element)
851 {
852   int graphic;
853 
854   if (element == EL_LEERRAUM)
855     return;
856 
857   graphic = el2gfx(element);
858 
859   BlitBitmap(pix[PIX_BACK], drawto,
860 	     MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
861 	     MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
862 	     MICRO_TILEX, MICRO_TILEY, xpos, ypos);
863 }
864 
865 void DrawLevel()
866 {
867   int x,y;
868 
869   ClearWindow();
870 
871   for(x=BX1; x<=BX2; x++)
872     for(y=BY1; y<=BY2; y++)
873       DrawScreenField(x, y);
874 
875   redraw_mask |= REDRAW_FIELD;
876 }
877 #endif
878 
DrawField(int x,int y)879 void DrawField(int x, int y)
880 {
881   int element = Feld[x][y];
882 
883   DrawElement(x, y, element);
884 }
885 
DrawLevel()886 void DrawLevel()
887 {
888   int x,y;
889 
890   ClearWindow();
891 
892   for (x=0; x<lev_fieldx; x++)
893     for (y=0; y<lev_fieldy; y++)
894       DrawField(x, y);
895 
896   redraw_mask |= REDRAW_FIELD;
897 }
898 
DrawWallsExt(int x,int y,int element,int draw_mask)899 void DrawWallsExt(int x, int y, int element, int draw_mask)
900 {
901   Bitmap *bitmap;
902   int graphic = el2gfx(WALL_BASE(element));
903   int gx, gy;
904   int i;
905 
906   getMiniGraphicSource(graphic, &bitmap, &gx, &gy);
907 
908   if (game_status != LEVELED || !editor.draw_walls_masked)
909     DrawGraphic(x, y, GFX_EMPTY);
910 
911   /*
912   if (IS_WALL_WOOD(element) || IS_WALL_AMOEBA(element) ||
913       IS_DF_WALL_WOOD(element))
914     gx += MINI_TILEX;
915   if (IS_WALL_ICE(element) || IS_WALL_AMOEBA(element))
916     gy += MINI_TILEY;
917   */
918 
919   for(i=0; i<4; i++)
920   {
921     int dest_x = SX + x * TILEX + MINI_TILEX * (i % 2);
922     int dest_y = SY + y * TILEY + MINI_TILEY * (i / 2);
923 
924     if (!((1 << i) & draw_mask))
925       continue;
926 
927     if (element & (1 << i))
928       BlitBitmap(bitmap, drawto, gx, gy, MINI_TILEX, MINI_TILEY,
929 		 dest_x, dest_y);
930     else if (!editor.draw_walls_masked)
931       ClearRectangle(drawto, dest_x, dest_y, MINI_TILEX, MINI_TILEY);
932   }
933 
934   MarkTileDirty(x, y);
935 }
936 
DrawWalls(int x,int y,int element)937 void DrawWalls(int x, int y, int element)
938 {
939   DrawWallsExt(x, y, element, HIT_MASK_ALL);
940 }
941 
DrawWallsAnimation(int x,int y,int element,int phase,int bit_mask)942 void DrawWallsAnimation(int x, int y, int element, int phase, int bit_mask)
943 {
944   int graphic = GFX_WALL_SEVERAL;
945   int graphic_anim = graphic + (phase + 1) / 2;
946   int dx = (IS_WALL_AMOEBA(element) ? MINI_TILEX : 0);
947   int dy = MINI_TILEY;
948   int dx_anim = dx;
949   int dy_anim = ((phase + 1) % 2) * MINI_TILEY;
950   int i;
951 
952   if (phase == 0)
953   {
954     DrawWalls(x, y, element);
955     return;
956   }
957 
958   for(i=0; i<4; i++)
959   {
960     if (element & (1 << i))
961     {
962       int dest_x = SX + x * TILEX + MINI_TILEX * (i % 2);
963       int dest_y = SY + y * TILEY + MINI_TILEY * (i / 2);
964       int gx, gy;
965 
966       if (bit_mask & (1 << i))
967       {
968 	gx = SX + ((graphic_anim) % GFX_PER_LINE) * TILEX + dx_anim;
969 	gy = SY + ((graphic_anim) / GFX_PER_LINE) * TILEY + dy_anim;
970       }
971       else
972       {
973 	gx = SX + (graphic % GFX_PER_LINE) * TILEX + dx;
974 	gy = SY + (graphic / GFX_PER_LINE) * TILEY + dy;
975       }
976 
977       BlitBitmap(pix[PIX_BACK], drawto, gx, gy, MINI_TILEX, MINI_TILEY,
978 		 dest_x, dest_y);
979     }
980   }
981 
982   MarkTileDirty(x, y);
983 }
984 
DrawElement(int x,int y,int element)985 void DrawElement(int x, int y, int element)
986 {
987   if (element == EL_EMPTY)
988     DrawGraphic(x, y, GFX_EMPTY);
989   else if (IS_WALL(element))
990     DrawWalls(x, y, element);
991 #if 0
992   else if (IS_WALL_CHANGING(element) && IS_WALL_CHANGING(Feld[x][y]))
993   {
994     int wall_element = Feld[x][y] - EL_WALL_CHANGING + Store[x][y];
995 
996     DrawWalls(x, y, wall_element);
997   }
998 #endif
999   else if (element == EL_PACMAN)
1000     DrawLevelField(x, y);
1001   else
1002     DrawGraphic(x, y, el2gfx(element));
1003 }
1004 
DrawMicroWalls(int x,int y,int element)1005 void DrawMicroWalls(int x, int y, int element)
1006 {
1007   Bitmap *bitmap;
1008   int graphic = el2gfx(WALL_BASE(element));
1009   int gx, gy;
1010   int i;
1011 
1012   getMicroGraphicSource(graphic, &bitmap, &gx, &gy);
1013 
1014   for (i=0; i<4; i++)
1015   {
1016     int xpos = MICROLEV_XPOS + x * MICRO_TILEX + MICRO_WALLX * (i % 2);
1017     int ypos = MICROLEV_YPOS + y * MICRO_TILEY + MICRO_WALLY * (i / 2);
1018 
1019     if (element & (1 << i))
1020       BlitBitmap(bitmap, drawto, gx, gy, MICRO_WALLX, MICRO_WALLY, xpos, ypos);
1021     else
1022       ClearRectangle(drawto, xpos, ypos, MICRO_WALLX, MICRO_WALLY);
1023   }
1024 }
1025 
DrawMicroElement(int x,int y,int element)1026 void DrawMicroElement(int x, int y, int element)
1027 {
1028   Bitmap *bitmap;
1029   int graphic = el2gfx(element);
1030   int gx, gy;
1031 
1032   if (element == EL_EMPTY)
1033     return;
1034 
1035   if (IS_WALL(element))
1036   {
1037     DrawMicroWalls(x, y, element);
1038     return;
1039   }
1040 
1041   getMicroGraphicSource(graphic, &bitmap, &gx, &gy);
1042 
1043   BlitBitmap(bitmap, drawto, gx, gy, MICRO_TILEX, MICRO_TILEY,
1044 	     MICROLEV_XPOS + x * MICRO_TILEX, MICROLEV_YPOS + y * MICRO_TILEY);
1045 }
1046 
DrawMicroLevelExt(int xpos,int ypos)1047 void DrawMicroLevelExt(int xpos, int ypos)
1048 {
1049   int x,y;
1050 
1051   ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1052 
1053   for (x=0; x<STD_LEV_FIELDX; x++)
1054     for (y=0; y<STD_LEV_FIELDY; y++)
1055       DrawMicroElement(x, y, Ur[x][y]);
1056 
1057   redraw_mask |= REDRAW_MICROLEVEL;
1058 }
1059 
DrawMiniLevel(int size_x,int size_y,int scroll_x,int scroll_y)1060 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1061 {
1062   int x,y;
1063 
1064   for(x=0; x<size_x; x++)
1065     for(y=0; y<size_y; y++)
1066       DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1067 
1068   redraw_mask |= REDRAW_FIELD;
1069 }
1070 
1071 #define MICROLABEL_EMPTY		0
1072 #define MICROLABEL_LEVEL_NAME		1
1073 #define MICROLABEL_CREATED_BY		2
1074 #define MICROLABEL_LEVEL_AUTHOR		3
1075 #define MICROLABEL_IMPORTED_FROM	4
1076 #define MICROLABEL_LEVEL_IMPORT_INFO	5
1077 
1078 #define MAX_MICROLABEL_SIZE		(SXSIZE / FONT4_XSIZE)
1079 
DrawMicroLevelLabelExt(int mode)1080 static void DrawMicroLevelLabelExt(int mode)
1081 {
1082   char label_text[MAX_MICROLABEL_SIZE + 1];
1083 
1084   ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1085 
1086   strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1087 		       mode == MICROLABEL_CREATED_BY ? "created by" :
1088 		       mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1089 		       mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1090 		       mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1091 		       leveldir_current->imported_from : ""),
1092 	  MAX_MICROLABEL_SIZE);
1093   label_text[MAX_MICROLABEL_SIZE] = '\0';
1094 
1095   if (strlen(label_text) > 0)
1096   {
1097     int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1098     int lypos = MICROLABEL_YPOS;
1099 
1100     DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1101   }
1102 
1103   redraw_mask |= REDRAW_MICROLABEL;
1104 }
1105 
DrawMicroLevel(int xpos,int ypos,boolean restart)1106 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1107 {
1108   static unsigned long scroll_delay = 0;
1109   static unsigned long label_delay = 0;
1110   static int label_state, label_counter;
1111 
1112   if (restart)
1113   {
1114     label_state = 1;
1115     label_counter = 0;
1116 
1117     DrawMicroLevelExt(xpos, ypos);
1118     DrawMicroLevelLabelExt(label_state);
1119 
1120     /* initialize delay counters */
1121     DelayReached(&scroll_delay, 0);
1122     DelayReached(&label_delay, 0);
1123 
1124     return;
1125   }
1126 
1127   /* redraw micro level label, if needed */
1128   if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1129       strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1130       strcmp(level.author, leveldir_current->name) != 0 &&
1131       DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1132   {
1133     int max_label_counter = 23;
1134 
1135     if (leveldir_current->imported_from != NULL)
1136       max_label_counter += 14;
1137 
1138     label_counter = (label_counter + 1) % max_label_counter;
1139     label_state = (label_counter >= 0 && label_counter <= 7 ?
1140 		   MICROLABEL_LEVEL_NAME :
1141 		   label_counter >= 9 && label_counter <= 12 ?
1142 		   MICROLABEL_CREATED_BY :
1143 		   label_counter >= 14 && label_counter <= 21 ?
1144 		   MICROLABEL_LEVEL_AUTHOR :
1145 		   label_counter >= 23 && label_counter <= 26 ?
1146 		   MICROLABEL_IMPORTED_FROM :
1147 		   label_counter >= 28 && label_counter <= 35 ?
1148 		   MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1149     DrawMicroLevelLabelExt(label_state);
1150   }
1151 }
1152 
REQ_in_range(int x,int y)1153 int REQ_in_range(int x, int y)
1154 {
1155   if (y > DY+249 && y < DY+278)
1156   {
1157     if (x > DX+1 && x < DX+48)
1158       return 1;
1159     else if (x > DX+51 && x < DX+98)
1160       return 2;
1161   }
1162   return 0;
1163 }
1164 
Request(char * text,unsigned int req_state)1165 boolean Request(char *text, unsigned int req_state)
1166 {
1167   int mx, my, ty, result = -1;
1168   unsigned int old_door_state;
1169 
1170   old_door_state = GetDoorState();
1171 
1172   UnmapAllGadgets();
1173 
1174   CloseDoor(DOOR_CLOSE_1);
1175 
1176   /* save old door content */
1177   BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
1178 	     DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1179 	     DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1180 
1181   /* clear door drawing field */
1182   ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
1183 
1184   /* write text for request */
1185   for(ty=0; ty<13; ty++)
1186   {
1187     int tx, tl, tc;
1188     char txt[256];
1189 
1190     if (!*text)
1191       break;
1192 
1193     for(tl=0,tx=0; tx<7; tl++,tx++)
1194     {
1195       tc = *(text + tx);
1196       if (!tc || tc == 32)
1197 	break;
1198     }
1199     if (!tl)
1200     {
1201       text++;
1202       ty--;
1203       continue;
1204     }
1205     sprintf(txt, text);
1206     txt[tl] = 0;
1207     DrawTextExt(drawto,
1208 		DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1209 		txt, FS_SMALL, FC_YELLOW);
1210     text += tl + (tc == 32 ? 1 : 0);
1211   }
1212 
1213   if (req_state & REQ_ASK)
1214   {
1215     MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1216     MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1217   }
1218   else if (req_state & REQ_CONFIRM)
1219   {
1220     MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1221   }
1222 
1223   /* copy request gadgets to door backbuffer */
1224   BlitBitmap(drawto, pix[PIX_DB_DOOR],
1225 	     DX, DY, DXSIZE, DYSIZE,
1226 	     DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1227 
1228   OpenDoor(DOOR_OPEN_1);
1229 
1230 #if 0
1231   ClearEventQueue();
1232 #endif
1233 
1234   if (!(req_state & REQUEST_WAIT_FOR))
1235     return(FALSE);
1236 
1237   if (game_status != MAINMENU)
1238     InitAnimation();
1239 
1240   button_status = MB_RELEASED;
1241 
1242   request_gadget_id = -1;
1243 
1244   while(result < 0)
1245   {
1246     if (PendingEvent())
1247     {
1248       Event event;
1249 
1250       NextEvent(&event);
1251 
1252       switch(event.type)
1253       {
1254 	case EVENT_BUTTONPRESS:
1255 	case EVENT_BUTTONRELEASE:
1256 	case EVENT_MOTIONNOTIFY:
1257 	{
1258 	  if (event.type == EVENT_MOTIONNOTIFY)
1259 	  {
1260 	    if (!PointerInWindow(window))
1261 	      continue;	/* window and pointer are on different screens */
1262 
1263 	    if (!button_status)
1264 	      continue;
1265 
1266 	    motion_status = TRUE;
1267 	    mx = ((MotionEvent *) &event)->x;
1268 	    my = ((MotionEvent *) &event)->y;
1269 	  }
1270 	  else
1271 	  {
1272 	    motion_status = FALSE;
1273 	    mx = ((ButtonEvent *) &event)->x;
1274 	    my = ((ButtonEvent *) &event)->y;
1275 	    if (event.type == EVENT_BUTTONPRESS)
1276 	      button_status = ((ButtonEvent *) &event)->button;
1277 	    else
1278 	      button_status = MB_RELEASED;
1279 	  }
1280 
1281 	  /* this sets 'request_gadget_id' */
1282 	  HandleGadgets(mx, my, button_status);
1283 
1284 	  switch(request_gadget_id)
1285 	  {
1286 	    case TOOL_CTRL_ID_YES:
1287 	      result = TRUE;
1288 	      break;
1289 	    case TOOL_CTRL_ID_NO:
1290 	      result = FALSE;
1291 	      break;
1292 	    case TOOL_CTRL_ID_CONFIRM:
1293 	      result = TRUE | FALSE;
1294 	      break;
1295 
1296 	    default:
1297 	      break;
1298 	  }
1299 
1300 	  break;
1301 	}
1302 
1303 	case EVENT_KEYPRESS:
1304 	  switch(GetEventKey((KeyEvent *)&event, TRUE))
1305 	  {
1306 	    case KSYM_Return:
1307 	      result = 1;
1308 	      break;
1309 
1310 	    case KSYM_Escape:
1311 	      result = 0;
1312 	      break;
1313 
1314 	    default:
1315 	      break;
1316 	  }
1317 	  break;
1318 
1319 	case EVENT_KEYRELEASE:
1320 	  key_joystick_mapping = 0;
1321 	  break;
1322 
1323 	default:
1324 	  HandleOtherEvents(&event);
1325 	  break;
1326       }
1327     }
1328 
1329     DoAnimation();
1330 
1331     /* don't eat all CPU time */
1332     Delay(10);
1333   }
1334 
1335   if (game_status != MAINMENU)
1336     StopAnimation();
1337 
1338   UnmapToolButtons();
1339 
1340   if (!(req_state & REQ_STAY_OPEN))
1341   {
1342     CloseDoor(DOOR_CLOSE_1);
1343 
1344     if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1345     {
1346       BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
1347 		 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1348 		 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1349       OpenDoor(DOOR_OPEN_1);
1350     }
1351   }
1352 
1353   RemapAllGadgets();
1354 
1355   return(result);
1356 }
1357 
OpenDoor(unsigned int door_state)1358 unsigned int OpenDoor(unsigned int door_state)
1359 {
1360   unsigned int new_door_state;
1361 
1362   if (door_state & DOOR_COPY_BACK)
1363   {
1364     BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
1365 	       DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1366 	       DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1367     door_state &= ~DOOR_COPY_BACK;
1368   }
1369 
1370   new_door_state = MoveDoor(door_state);
1371 
1372   return(new_door_state);
1373 }
1374 
CloseDoor(unsigned int door_state)1375 unsigned int CloseDoor(unsigned int door_state)
1376 {
1377   unsigned int new_door_state;
1378 
1379   BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
1380 	     DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1381 
1382   new_door_state = MoveDoor(door_state);
1383 
1384   return(new_door_state);
1385 }
1386 
GetDoorState()1387 unsigned int GetDoorState()
1388 {
1389   return(MoveDoor(DOOR_GET_STATE));
1390 }
1391 
MoveDoor(unsigned int door_state)1392 unsigned int MoveDoor(unsigned int door_state)
1393 {
1394   static int door1 = DOOR_OPEN_1;
1395   static int door2 = DOOR_CLOSE_2;
1396   static unsigned long door_delay = 0;
1397   int x, start, stepsize = 2;
1398   unsigned long door_delay_value = stepsize * 5;
1399 
1400   /* there is no second door */
1401   door_state &= ~DOOR_ACTION_2;
1402 
1403   if (door_state == DOOR_GET_STATE)
1404     return(door1 | door2);
1405 
1406   if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1407     door_state &= ~DOOR_OPEN_1;
1408   else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1409     door_state &= ~DOOR_CLOSE_1;
1410   if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1411     door_state &= ~DOOR_OPEN_2;
1412   else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1413     door_state &= ~DOOR_CLOSE_2;
1414 
1415   if (setup.quick_doors)
1416   {
1417     stepsize = 20;
1418     door_delay_value = 0;
1419     StopSound(SND_OEFFNEN);
1420   }
1421 
1422   if (door_state & DOOR_ACTION)
1423   {
1424     if (door_state & DOOR_ACTION_1)
1425     {
1426       if (door_state & DOOR_OPEN_1)
1427       {
1428 	BlitBitmap(pix[PIX_DOOR], pix[PIX_DOOR], 104,136, 8,8, 146,136);
1429 	BlitBitmap(pix[PIX_DOOR], window, 104,136, 8,8, DX + 46,DY + 136);
1430 	redraw_mask &= ~REDRAW_DOOR_1;
1431 
1432 	if (!setup.quick_doors)
1433 	{
1434 #if 0
1435 	  int i;
1436 
1437 	  for (i=0; i<30; i++)
1438 	  {
1439 	    ColorCycling();
1440 	    if (game_status == MAINMENU)
1441 	      DoAnimation();
1442 	    Delay(10);
1443 	  }
1444 #else
1445 	  Delay(100);
1446 #endif
1447 	}
1448 
1449       }
1450       else
1451 	BlitBitmap(pix[PIX_DOOR], pix[PIX_DOOR], 88,136, 8,8, 146,136);
1452 
1453       if (!(door_state & DOOR_NO_DELAY))
1454 	PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1455     }
1456 
1457     start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1458 
1459     for(x=start; x<=DXSIZE; x+=stepsize)
1460     {
1461       Bitmap *bitmap = pix[PIX_DOOR];
1462       GC gc = bitmap->stored_clip_gc;
1463 
1464       WaitUntilDelayReached(&door_delay, door_delay_value);
1465 
1466       if (door_state & DOOR_ACTION_1)
1467       {
1468 	int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1469 
1470 	if (x < DXSIZE || door_state & DOOR_OPEN_1)
1471 	{
1472 	  BlitBitmap(pix[PIX_DB_DOOR], drawto,
1473 		     DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1474 		     DXSIZE,DYSIZE - i/2, DX, DY);
1475 
1476 	  ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE, i/2);
1477 	}
1478 	else
1479 	  ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
1480 
1481 	SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY);
1482 	BlitBitmapMasked(bitmap, drawto,
1483 			 DXSIZE - i, DOOR_GFX_PAGEY1, i, 30,
1484 			 DX, DY);
1485 	BlitBitmapMasked(bitmap, drawto,
1486 			 DXSIZE - i, DOOR_GFX_PAGEY1 + DYSIZE - 30, i, 30,
1487 			 DX, DY + DYSIZE - 30);
1488 	SetClipOrigin(bitmap, gc, DX - i, DY);
1489 	BlitBitmapMasked(bitmap, drawto,
1490 			 DXSIZE, DOOR_GFX_PAGEY1, i, 30,
1491 			 DX + DXSIZE - i, DY);
1492 	BlitBitmapMasked(bitmap, drawto,
1493 			 DXSIZE, DOOR_GFX_PAGEY1 + DYSIZE - 30, i, 30,
1494 			 DX + DXSIZE - i, DY + DYSIZE - 30);
1495 
1496 	if (i > 14)
1497 	{
1498 	  SetClipOrigin(bitmap, gc, DX - i, DY);
1499 	  BlitBitmapMasked(bitmap, drawto,
1500 			   DXSIZE + 14, DOOR_GFX_PAGEY1 + 30,
1501 			   i - 14, DYSIZE - 60,
1502 			   DX + DXSIZE + 14 - i, DY + 30);
1503 	  SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY);
1504 	  BlitBitmapMasked(bitmap, drawto,
1505 			   DXSIZE - i, DOOR_GFX_PAGEY1 + 30,
1506 			   i - 14, DYSIZE - 60,
1507 			   DX, DY + 30);
1508 	}
1509 
1510 	redraw_mask |= REDRAW_DOOR_1;
1511       }
1512 
1513       BackToFront();
1514 
1515       if (game_status == MAINMENU)
1516 	DoAnimation();
1517     }
1518   }
1519 
1520   if (setup.quick_doors)
1521     StopSound(SND_OEFFNEN);
1522 
1523   if (door_state & DOOR_ACTION_1)
1524     door1 = door_state & DOOR_ACTION_1;
1525   if (door_state & DOOR_ACTION_2)
1526     door2 = door_state & DOOR_ACTION_2;
1527 
1528   return (door1 | door2);
1529 }
1530 
1531 
1532 #if 0
1533 void DrawSpecialEditorDoor()
1534 {
1535   /* draw bigger toolbox window */
1536   BlitBitmap(pix[PIX_DOOR], drawto,
1537 	     DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
1538 
1539   redraw_mask |= REDRAW_ALL;
1540 }
1541 
1542 void UndrawSpecialEditorDoor()
1543 {
1544   /* draw normal tape recorder window */
1545   BlitBitmap(pix[PIX_BACK], drawto,
1546 	     562, 344, 108, 56, EX - 4, EY - 12);
1547 
1548   redraw_mask |= REDRAW_ALL;
1549 }
1550 #endif
1551 
ReadPixel(DrawBuffer * bitmap,int x,int y)1552 Pixel ReadPixel(DrawBuffer *bitmap, int x, int y)
1553 {
1554 #if defined(TARGET_SDL) || defined(TARGET_ALLEGRO)
1555   return GetPixel(bitmap, x, y);
1556 #else
1557   /* GetPixel() does also work for X11, but we use some optimization here */
1558   unsigned long pixel_value;
1559 
1560   if (bitmap == pix[PIX_BACK])
1561   {
1562     /* when reading pixel values from images, it is much faster to use
1563        client side images (XImage) than server side images (Pixmap) */
1564     static XImage *client_image = NULL;
1565 
1566     if (client_image == NULL)	/* init image cache, if not existing */
1567       client_image = XGetImage(display, bitmap->drawable,
1568 			       0,0, WIN_XSIZE,WIN_YSIZE, AllPlanes, ZPixmap);
1569 
1570     pixel_value = XGetPixel(client_image, x, y);
1571   }
1572   else
1573   {
1574     XImage *pixel_image;
1575 
1576     pixel_image = XGetImage(display, bitmap->drawable, x, y, 1, 1,
1577 			    AllPlanes, ZPixmap);
1578     pixel_value = XGetPixel(pixel_image, 0, 0);
1579 
1580     XDestroyImage(pixel_image);
1581   }
1582 
1583   return pixel_value;
1584 #endif
1585 }
1586 
SetRGB(unsigned long pixel,unsigned short red,unsigned short green,unsigned short blue)1587 void SetRGB(unsigned long pixel,
1588 	    unsigned short red, unsigned short green, unsigned short blue)
1589 {
1590   return;
1591 
1592 #if 0
1593   XColor color;
1594 
1595   if (color_status==STATIC_COLORS)
1596     return;
1597 
1598   color.pixel = pixel;
1599   color.red = red;
1600   color.green = green;
1601   color.blue = blue;
1602   color.flags = DoRed | DoGreen | DoBlue;
1603   XStoreColor(display, cmap, &color);
1604   XFlush(display);
1605 #endif
1606 }
1607 
1608 /* ---------- new tool button stuff ---------------------------------------- */
1609 
1610 /* graphic position values for tool buttons */
1611 #define TOOL_BUTTON_YES_XPOS		2
1612 #define TOOL_BUTTON_YES_YPOS		250
1613 #define TOOL_BUTTON_YES_GFX_YPOS	0
1614 #define TOOL_BUTTON_YES_XSIZE		46
1615 #define TOOL_BUTTON_YES_YSIZE		28
1616 #define TOOL_BUTTON_NO_XPOS		52
1617 #define TOOL_BUTTON_NO_YPOS		TOOL_BUTTON_YES_YPOS
1618 #define TOOL_BUTTON_NO_GFX_YPOS		TOOL_BUTTON_YES_GFX_YPOS
1619 #define TOOL_BUTTON_NO_XSIZE		TOOL_BUTTON_YES_XSIZE
1620 #define TOOL_BUTTON_NO_YSIZE		TOOL_BUTTON_YES_YSIZE
1621 #define TOOL_BUTTON_CONFIRM_XPOS	TOOL_BUTTON_YES_XPOS
1622 #define TOOL_BUTTON_CONFIRM_YPOS	TOOL_BUTTON_YES_YPOS
1623 #define TOOL_BUTTON_CONFIRM_GFX_YPOS	30
1624 #define TOOL_BUTTON_CONFIRM_XSIZE	96
1625 #define TOOL_BUTTON_CONFIRM_YSIZE	TOOL_BUTTON_YES_YSIZE
1626 
1627 static struct
1628 {
1629   int xpos, ypos;
1630   int x, y;
1631   int width, height;
1632   int gadget_id;
1633   char *infotext;
1634 } toolbutton_info[NUM_TOOL_BUTTONS] =
1635 {
1636   {
1637     TOOL_BUTTON_YES_XPOS,	TOOL_BUTTON_YES_GFX_YPOS,
1638     TOOL_BUTTON_YES_XPOS,	TOOL_BUTTON_YES_YPOS,
1639     TOOL_BUTTON_YES_XSIZE,	TOOL_BUTTON_YES_YSIZE,
1640     TOOL_CTRL_ID_YES,
1641     "yes"
1642   },
1643   {
1644     TOOL_BUTTON_NO_XPOS,	TOOL_BUTTON_NO_GFX_YPOS,
1645     TOOL_BUTTON_NO_XPOS,	TOOL_BUTTON_NO_YPOS,
1646     TOOL_BUTTON_NO_XSIZE,	TOOL_BUTTON_NO_YSIZE,
1647     TOOL_CTRL_ID_NO,
1648     "no"
1649   },
1650   {
1651     TOOL_BUTTON_CONFIRM_XPOS,	TOOL_BUTTON_CONFIRM_GFX_YPOS,
1652     TOOL_BUTTON_CONFIRM_XPOS,	TOOL_BUTTON_CONFIRM_YPOS,
1653     TOOL_BUTTON_CONFIRM_XSIZE,	TOOL_BUTTON_CONFIRM_YSIZE,
1654     TOOL_CTRL_ID_CONFIRM,
1655     "confirm"
1656   }
1657 };
1658 
DoNotDisplayInfoText(void * ptr)1659 static void DoNotDisplayInfoText(void *ptr)
1660 {
1661   return;
1662 }
1663 
CreateToolButtons()1664 void CreateToolButtons()
1665 {
1666   int i;
1667 
1668   for (i=0; i<NUM_TOOL_BUTTONS; i++)
1669   {
1670     Bitmap *gd_bitmap = pix[PIX_DOOR];
1671     Bitmap *deco_bitmap = None;
1672     int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
1673     struct GadgetInfo *gi;
1674     unsigned long event_mask;
1675     int gd_xoffset, gd_yoffset;
1676     int gd_x1, gd_x2, gd_y;
1677     int id = i;
1678 
1679     event_mask = GD_EVENT_RELEASED;
1680 
1681     gd_xoffset = toolbutton_info[i].xpos;
1682     gd_yoffset = toolbutton_info[i].ypos;
1683     gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
1684     gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
1685     gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
1686 
1687     gi = CreateGadget(GDI_CUSTOM_ID, id,
1688 		      GDI_INFO_TEXT, toolbutton_info[i].infotext,
1689 		      GDI_X, DX + toolbutton_info[i].x,
1690 		      GDI_Y, DY + toolbutton_info[i].y,
1691 		      GDI_WIDTH, toolbutton_info[i].width,
1692 		      GDI_HEIGHT, toolbutton_info[i].height,
1693 		      GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
1694 		      GDI_STATE, GD_BUTTON_UNPRESSED,
1695 		      GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
1696 		      GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
1697 		      GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
1698 		      GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
1699 		      GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
1700 		      GDI_DECORATION_SHIFTING, 1, 1,
1701 		      GDI_EVENT_MASK, event_mask,
1702 		      GDI_CALLBACK_ACTION, HandleToolButtons,
1703 		      GDI_CALLBACK_INFO, DoNotDisplayInfoText,
1704 		      GDI_END);
1705 
1706     if (gi == NULL)
1707       Error(ERR_EXIT, "cannot create gadget");
1708 
1709     tool_gadget[id] = gi;
1710   }
1711 }
1712 
UnmapToolButtons()1713 static void UnmapToolButtons()
1714 {
1715   int i;
1716 
1717   for (i=0; i<NUM_TOOL_BUTTONS; i++)
1718     UnmapGadget(tool_gadget[i]);
1719 }
1720 
HandleToolButtons(struct GadgetInfo * gi)1721 static void HandleToolButtons(struct GadgetInfo *gi)
1722 {
1723   request_gadget_id = gi->custom_id;
1724 }
1725 
1726 /* ------------------------------------------------------------------------- */
1727 
get_base_element(int element)1728 int get_base_element(int element)
1729 {
1730   if (IS_MIRROR(element))
1731     return EL_MIRROR_START;
1732   else if (IS_MIRROR_FIXED(element))
1733     return EL_MIRROR_FIXED_START;
1734   else if (IS_POLAR(element))
1735     return EL_POLAR_START;
1736   else if (IS_POLAR_CROSS(element))
1737     return EL_POLAR_CROSS_START;
1738   else if (IS_BEAMER(element))
1739     return EL_BEAMER_RED_START + BEAMER_NR(element) * 16;
1740   else if (IS_FIBRE_OPTIC(element))
1741     return EL_FIBRE_OPTIC_START + FIBRE_OPTIC_NR(element) * 2;
1742   else if (IS_MCDUFFIN(element))
1743     return EL_MCDUFFIN_START;
1744   else if (IS_LASER(element))
1745     return EL_LASER_START;
1746   else if (IS_RECEIVER(element))
1747     return EL_RECEIVER_START;
1748   else if (IS_DF_MIRROR(element))
1749     return EL_DF_MIRROR_START;
1750   else if (IS_DF_MIRROR_AUTO(element))
1751     return EL_DF_MIRROR_AUTO_START;
1752   else if (IS_PACMAN(element))
1753     return EL_PACMAN_START;
1754   else if (IS_GRID_STEEL(element))
1755     return EL_GRID_STEEL_START;
1756   else if (IS_GRID_WOOD(element))
1757     return EL_GRID_WOOD_START;
1758   else if (IS_GRID_STEEL_FIXED(element))
1759     return EL_GRID_STEEL_FIXED_START;
1760   else if (IS_GRID_WOOD_FIXED(element))
1761     return EL_GRID_WOOD_FIXED_START;
1762   else if (IS_GRID_STEEL_AUTO(element))
1763     return EL_GRID_STEEL_AUTO_START;
1764   else if (IS_GRID_WOOD_AUTO(element))
1765     return EL_GRID_WOOD_AUTO_START;
1766   else if (IS_WALL_STEEL(element))
1767     return EL_WALL_STEEL_START;
1768   else if (IS_WALL_WOOD(element))
1769     return EL_WALL_WOOD_START;
1770   else if (IS_WALL_ICE(element))
1771     return EL_WALL_ICE_START;
1772   else if (IS_WALL_AMOEBA(element))
1773     return EL_WALL_AMOEBA_START;
1774   else if (IS_DF_WALL_STEEL(element))
1775     return EL_DF_WALL_STEEL_START;
1776   else if (IS_DF_WALL_WOOD(element))
1777     return EL_DF_WALL_WOOD_START;
1778   else if (IS_CHAR(element))
1779     return EL_CHAR_START;
1780   else
1781     return element;
1782 }
1783 
get_element_phase(int element)1784 int get_element_phase(int element)
1785 {
1786   return element - get_base_element(element);
1787 }
1788 
get_num_elements(int element)1789 int get_num_elements(int element)
1790 {
1791   if (IS_MIRROR(element) ||
1792       IS_POLAR(element) ||
1793       IS_BEAMER(element) ||
1794       IS_DF_MIRROR(element) ||
1795       IS_DF_MIRROR_AUTO(element))
1796     return 16;
1797   else if (IS_GRID_STEEL_FIXED(element) ||
1798 	   IS_GRID_WOOD_FIXED(element) ||
1799 	   IS_GRID_STEEL_AUTO(element) ||
1800 	   IS_GRID_WOOD_AUTO(element))
1801     return 8;
1802   else if (IS_MIRROR_FIXED(element) ||
1803 	   IS_POLAR_CROSS(element) ||
1804 	   IS_MCDUFFIN(element) ||
1805 	   IS_LASER(element) ||
1806 	   IS_RECEIVER(element) ||
1807 	   IS_PACMAN(element) ||
1808 	   IS_GRID_STEEL(element) ||
1809 	   IS_GRID_WOOD(element))
1810     return 4;
1811   else
1812     return 1;
1813 }
1814 
get_rotated_element(int element,int step)1815 int get_rotated_element(int element, int step)
1816 {
1817   int base_element = get_base_element(element);
1818   int num_elements = get_num_elements(element);
1819   int element_phase = element - base_element;
1820 
1821   return base_element + (element_phase + step + num_elements) % num_elements;
1822 }
1823 
el2gfx(int element)1824 int el2gfx(int element)
1825 {
1826   switch(element)
1827   {
1828     case EL_EMPTY:		return -1;
1829     case EL_GRID_STEEL_00:	return GFX_GRID_STEEL_00;
1830     case EL_GRID_STEEL_01:	return GFX_GRID_STEEL_01;
1831     case EL_GRID_STEEL_02:	return GFX_GRID_STEEL_02;
1832     case EL_GRID_STEEL_03:	return GFX_GRID_STEEL_03;
1833     case EL_MCDUFFIN_RIGHT:	return GFX_MCDUFFIN_RIGHT;
1834     case EL_MCDUFFIN_UP:	return GFX_MCDUFFIN_UP;
1835     case EL_MCDUFFIN_LEFT:	return GFX_MCDUFFIN_LEFT;
1836     case EL_MCDUFFIN_DOWN:	return GFX_MCDUFFIN_DOWN;
1837     case EL_EXIT_CLOSED:	return GFX_EXIT_CLOSED;
1838     case EL_EXIT_OPENING_1:	return GFX_EXIT_OPENING_1;
1839     case EL_EXIT_OPENING_2:	return GFX_EXIT_OPENING_2;
1840     case EL_EXIT_OPEN:		return GFX_EXIT_OPEN;
1841     case EL_KETTLE:		return GFX_KETTLE;
1842     case EL_BOMB:		return GFX_BOMB;
1843     case EL_PRISM:		return GFX_PRISM;
1844     case EL_BLOCK_WOOD:		return GFX_BLOCK_WOOD;
1845     case EL_BALL_GRAY:		return GFX_BALL_GRAY;
1846     case EL_FUSE_ON:		return GFX_FUSE_ON;
1847     case EL_PACMAN_RIGHT:	return GFX_PACMAN_RIGHT;
1848     case EL_PACMAN_UP:		return GFX_PACMAN_UP;
1849     case EL_PACMAN_LEFT:	return GFX_PACMAN_LEFT;
1850     case EL_PACMAN_DOWN:	return GFX_PACMAN_DOWN;
1851     case EL_POLAR_CROSS_00:	return GFX_POLAR_CROSS_00;
1852     case EL_POLAR_CROSS_01:	return GFX_POLAR_CROSS_01;
1853     case EL_POLAR_CROSS_02:	return GFX_POLAR_CROSS_02;
1854     case EL_POLAR_CROSS_03:	return GFX_POLAR_CROSS_03;
1855     case EL_MIRROR_FIXED_00:	return GFX_MIRROR_FIXED_00;
1856     case EL_MIRROR_FIXED_01:	return GFX_MIRROR_FIXED_01;
1857     case EL_MIRROR_FIXED_02:	return GFX_MIRROR_FIXED_02;
1858     case EL_MIRROR_FIXED_03:	return GFX_MIRROR_FIXED_03;
1859     case EL_GATE_STONE:		return GFX_GATE_STONE;
1860     case EL_KEY:		return GFX_KEY;
1861     case EL_LIGHTBULB_ON:	return GFX_LIGHTBULB_ON;
1862     case EL_LIGHTBULB_OFF:	return GFX_LIGHTBULB_OFF;
1863     case EL_LIGHTBALL:		return GFX_BALL_RED + RND(3);;
1864     case EL_BLOCK_STONE:	return GFX_BLOCK_STONE;
1865     case EL_GATE_WOOD:		return GFX_GATE_WOOD;
1866     case EL_FUEL_FULL:		return GFX_FUEL_FULL;
1867     case EL_GRID_WOOD_00:	return GFX_GRID_WOOD_00;
1868     case EL_GRID_WOOD_01:	return GFX_GRID_WOOD_01;
1869     case EL_GRID_WOOD_02:	return GFX_GRID_WOOD_02;
1870     case EL_GRID_WOOD_03:	return GFX_GRID_WOOD_03;
1871     case EL_FUEL_EMPTY:		return GFX_FUEL_EMPTY;
1872     case EL_FUSE_OFF:		return GFX_FUSE_OFF;
1873     case EL_PACMAN:		return GFX_PACMAN;
1874     case EL_REFRACTOR:		return GFX_REFRACTOR;
1875     case EL_CELL:		return GFX_CELL;
1876     case EL_MINE:		return GFX_MINE;
1877 
1878     /* pseudo-graphics; will be mapped to other graphics */
1879     case EL_WALL_STEEL:		return GFX_WALL_STEEL;
1880     case EL_WALL_WOOD:		return GFX_WALL_WOOD;
1881     case EL_WALL_ICE:		return GFX_WALL_ICE;
1882     case EL_WALL_AMOEBA:	return GFX_WALL_AMOEBA;
1883     case EL_DF_WALL_STEEL:	return GFX_DF_WALL_STEEL;
1884     case EL_DF_WALL_WOOD:	return GFX_DF_WALL_WOOD;
1885 
1886     default:
1887     {
1888       boolean ed = (game_status == LEVELED);
1889       int base_element = get_base_element(element);
1890       int element_phase = element - base_element;
1891       int base_graphic;
1892 
1893       if (IS_BEAMER(element))
1894 	element_phase = element - EL_BEAMER_RED_START;
1895       else if (IS_FIBRE_OPTIC(element))
1896 	element_phase = element - EL_FIBRE_OPTIC_START;
1897 
1898       if (IS_MIRROR(element))
1899 	base_graphic = GFX_MIRROR_START;
1900       else if (IS_BEAMER_OLD(element))
1901 	base_graphic = GFX_BEAMER_START;
1902       else if (IS_POLAR(element))
1903 	base_graphic = GFX_POLAR_START;
1904       else if (IS_CHAR(element))
1905 	base_graphic = GFX_CHAR_START;
1906       else if (IS_GRID_WOOD_FIXED(element))
1907 	base_graphic = GFX_GRID_WOOD_FIXED_00;
1908       else if (IS_GRID_STEEL_FIXED(element))
1909 	base_graphic = GFX_GRID_STEEL_FIXED_00;
1910       else if (IS_DF_MIRROR(element))
1911 	base_graphic = GFX_DF_MIRROR_00;
1912       else if (IS_LASER(element))
1913 	base_graphic = GFX_LASER_RIGHT;
1914       else if (IS_RECEIVER(element))
1915 	base_graphic = GFX_RECEIVER_RIGHT;
1916       else if (IS_DF_MIRROR(element))
1917 	base_graphic = GFX_DF_MIRROR_00;
1918       else if (IS_FIBRE_OPTIC(element))
1919 	base_graphic = (ed ? GFX_FIBRE_OPTIC_ED_00 : GFX_FIBRE_OPTIC_00);
1920       else if (IS_GRID_WOOD_AUTO(element))
1921 	base_graphic = (ed ? GFX_GRID_WOOD_AUTO_00 : GFX_GRID_WOOD_FIXED_00);
1922       else if (IS_GRID_STEEL_AUTO(element))
1923 	base_graphic = (ed ? GFX_GRID_STEEL_AUTO_00 : GFX_GRID_STEEL_FIXED_00);
1924       else if (IS_DF_MIRROR_AUTO(element))
1925 	base_graphic = (ed ? GFX_DF_MIRROR_AUTO_00 : GFX_DF_MIRROR_00);
1926       else if (IS_BEAMER(element))
1927 	base_graphic = GFX_BEAMER_RED_START;
1928       else
1929 	return GFX_EMPTY;
1930 
1931       return base_graphic + element_phase;
1932     }
1933   }
1934 }
1935