1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-98 Artsoft Entertainment *
8 * phone: ++49 +521 290471 *
9 * email: aeglos@valinor.owl.de *
10 *----------------------------------------------------------*
12 ***********************************************************/
17 #include <machine/joystick.h>
31 extern boolean wait_for_vsync;
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
43 #define NUM_TOOL_BUTTONS 7
45 /* forward declaration for internal use */
46 static int getGraphicAnimationPhase(int, int, int);
47 static void UnmapToolButtons();
48 static void HandleToolButtons(struct GadgetInfo *);
50 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
51 static int request_gadget_id = -1;
53 void SetDrawtoField(int mode)
55 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
66 drawto_field = fieldbuffer;
68 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
79 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
86 Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
88 if (setup.direct_draw && game_status == PLAYING)
89 redraw_mask &= ~REDRAW_MAIN;
91 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
92 redraw_mask |= REDRAW_FIELD;
94 if (redraw_mask & REDRAW_FIELD)
95 redraw_mask &= ~REDRAW_TILES;
100 /* synchronize X11 graphics at this point; if we would synchronize the
101 display immediately after the buffer switching (after the XFlush),
102 this could mean that we have to wait for the graphics to complete,
103 although we could go on doing calculations for the next frame */
105 XSync(display, FALSE);
107 if (redraw_mask & REDRAW_ALL)
109 XCopyArea(display, backbuffer, window, gc,
110 0, 0, WIN_XSIZE, WIN_YSIZE,
115 if (redraw_mask & REDRAW_FIELD)
117 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
119 XCopyArea(display, backbuffer, window, gc,
120 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
125 int fx = FX, fy = FY;
127 if (setup.soft_scrolling)
129 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
130 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
133 if (setup.soft_scrolling ||
134 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
135 ABS(ScreenMovPos) == ScrollStepSize ||
136 redraw_tiles > REDRAWTILES_THRESHOLD)
138 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
142 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
144 (setup.soft_scrolling ?
145 "setup.soft_scrolling" :
146 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
147 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
148 ABS(ScreenGfxPos) == ScrollStepSize ?
149 "ABS(ScreenGfxPos) == ScrollStepSize" :
150 "redraw_tiles > REDRAWTILES_THRESHOLD"));
155 redraw_mask &= ~REDRAW_MAIN;
158 if (redraw_mask & REDRAW_DOORS)
160 if (redraw_mask & REDRAW_DOOR_1)
161 XCopyArea(display, backbuffer, window, gc,
162 DX, DY, DXSIZE, DYSIZE,
164 if (redraw_mask & REDRAW_DOOR_2)
166 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
167 XCopyArea(display,backbuffer,window,gc,
168 VX,VY, VXSIZE,VYSIZE,
172 if (redraw_mask & REDRAW_VIDEO_1)
173 XCopyArea(display,backbuffer,window,gc,
174 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
175 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
176 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
177 if (redraw_mask & REDRAW_VIDEO_2)
178 XCopyArea(display,backbuffer,window,gc,
179 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
180 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
181 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
182 if (redraw_mask & REDRAW_VIDEO_3)
183 XCopyArea(display,backbuffer,window,gc,
184 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
185 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
186 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
189 if (redraw_mask & REDRAW_DOOR_3)
190 XCopyArea(display, backbuffer, window, gc,
191 EX, EY, EXSIZE, EYSIZE,
193 redraw_mask &= ~REDRAW_DOORS;
196 if (redraw_mask & REDRAW_MICROLEVEL)
198 XCopyArea(display,backbuffer,window,gc,
199 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
200 MICROLEV_XPOS, MICROLEV_YPOS);
201 XCopyArea(display,backbuffer,window,gc,
202 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
203 SX, MICROLABEL_YPOS);
204 redraw_mask &= ~REDRAW_MICROLEVEL;
207 if (redraw_mask & REDRAW_TILES)
209 for(x=0; x<SCR_FIELDX; x++)
210 for(y=0; y<SCR_FIELDY; y++)
211 if (redraw[redraw_x1 + x][redraw_y1 + y])
212 XCopyArea(display, buffer, window, gc,
213 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
214 SX + x * TILEX, SY + y * TILEY);
219 for(x=0; x<MAX_BUF_XSIZE; x++)
220 for(y=0; y<MAX_BUF_YSIZE; y++)
229 long fading_delay = 300;
231 if (setup.fading && (redraw_mask & REDRAW_FIELD))
238 XFillRectangle(display,window,gc,
239 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
242 for(i=0;i<2*FULL_SYSIZE;i++)
244 for(y=0;y<FULL_SYSIZE;y++)
246 XCopyArea(display,backbuffer,window,gc,
247 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
255 for(i=1;i<FULL_SYSIZE;i+=2)
256 XCopyArea(display,backbuffer,window,gc,
257 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
263 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
264 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
265 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
269 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
270 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
271 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
275 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
276 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
277 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
281 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
282 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
283 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
287 redraw_mask &= ~REDRAW_MAIN;
296 XFillRectangle(display, backbuffer, gc,
297 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
299 if (setup.soft_scrolling && game_status == PLAYING)
301 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
302 SetDrawtoField(DRAW_BUFFERED);
305 SetDrawtoField(DRAW_BACKBUFFER);
307 if (setup.direct_draw && game_status == PLAYING)
309 XFillRectangle(display, window, gc,
310 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
311 SetDrawtoField(DRAW_DIRECT);
314 redraw_mask |= REDRAW_FIELD;
317 int getFontWidth(int font_size, int font_type)
319 return (font_size == FS_BIG ? FONT1_XSIZE :
320 font_type == FC_SPECIAL1 ? FONT3_XSIZE :
321 font_type == FC_SPECIAL2 ? FONT4_XSIZE :
322 font_type == FC_SPECIAL3 ? FONT5_XSIZE :
326 int getFontHeight(int font_size, int font_type)
328 return (font_size == FS_BIG ? FONT1_YSIZE :
329 font_type == FC_SPECIAL1 ? FONT3_YSIZE :
330 font_type == FC_SPECIAL2 ? FONT4_YSIZE :
331 font_type == FC_SPECIAL3 ? FONT5_YSIZE :
335 void DrawTextFCentered(int y, int font_type, char *format, ...)
337 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
338 int font_width = getFontWidth(FS_SMALL, font_type);
341 va_start(ap, format);
342 vsprintf(buffer, format, ap);
345 DrawText(SX + (SXSIZE - strlen(buffer) * font_width) / 2, SY + y,
346 buffer, FS_SMALL, font_type);
349 void DrawTextF(int x, int y, int font_type, char *format, ...)
351 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
354 va_start(ap, format);
355 vsprintf(buffer, format, ap);
358 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
361 void DrawText(int x, int y, char *text, int font_size, int font_type)
363 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
366 redraw_mask |= REDRAW_FIELD;
368 redraw_mask |= REDRAW_DOOR_1;
371 void DrawTextExt(Drawable d, GC gc, int x, int y,
372 char *text, int font_size, int font_type)
374 int font_width, font_height, font_start;
376 boolean print_inverse = FALSE;
378 if (font_size != FS_SMALL && font_size != FS_BIG)
379 font_size = FS_SMALL;
380 if (font_type < FC_RED || font_type > FC_SPECIAL3)
383 font_width = getFontWidth(font_size, font_type);
384 font_height = getFontHeight(font_size, font_type);
386 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
387 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
388 FONT_LINES_PER_FONT);
390 if (font_type == FC_SPECIAL3)
391 font_start += (FONT4_YSIZE - FONT2_YSIZE) * FONT_LINES_PER_FONT;
397 if (c == '~' && font_size == FS_SMALL)
399 print_inverse = TRUE;
403 if (c >= 'a' && c <= 'z')
405 else if (c == 'ä' || c == 'Ä')
407 else if (c == 'ö' || c == 'Ö')
409 else if (c == 'ü' || c == 'Ü')
412 if (c >= 32 && c <= 95)
414 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
415 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
416 int dest_x = x, dest_y = y;
420 XCopyArea(display, pix[font_pixmap], d, gc,
421 FONT_CHARS_PER_LINE * font_width,
422 3 * font_height + font_start,
423 font_width, font_height, x, y);
425 XSetClipOrigin(display, clip_gc[font_pixmap],
426 dest_x - src_x, dest_y - src_y);
427 XCopyArea(display, pix[font_pixmap], d, clip_gc[font_pixmap],
428 0, 0, font_width, font_height, dest_x, dest_y);
431 XCopyArea(display, pix[font_pixmap], d, gc,
432 src_x, src_y, font_width, font_height, dest_x, dest_y);
439 void DrawAllPlayers()
443 for(i=0; i<MAX_PLAYERS; i++)
444 if (stored_player[i].active)
445 DrawPlayer(&stored_player[i]);
448 void DrawPlayerField(int x, int y)
450 if (!IS_PLAYER(x, y))
453 DrawPlayer(PLAYERINFO(x, y));
456 void DrawPlayer(struct PlayerInfo *player)
458 int jx = player->jx, jy = player->jy;
459 int last_jx = player->last_jx, last_jy = player->last_jy;
460 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
461 int sx = SCREENX(jx), sy = SCREENY(jy);
462 int sxx = 0, syy = 0;
463 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
465 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
467 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
471 if (!IN_LEV_FIELD(jx,jy))
473 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
474 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
475 printf("DrawPlayerField(): This should never happen!\n");
480 if (element == EL_EXPLODING)
483 /* draw things in the field the player is leaving, if needed */
485 if (player_is_moving)
487 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
489 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
490 DrawLevelFieldThruMask(last_jx, last_jy);
492 else if (last_element == EL_DYNAMITE_ACTIVE)
493 DrawDynamite(last_jx, last_jy);
495 DrawLevelField(last_jx, last_jy);
497 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
501 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
502 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
504 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
507 DrawLevelField(next_jx, next_jy);
511 if (!IN_SCR_FIELD(sx, sy))
514 if (setup.direct_draw)
515 SetDrawtoField(DRAW_BUFFERED);
517 /* draw things behind the player, if needed */
520 DrawLevelElement(jx, jy, Store[jx][jy]);
521 else if (!IS_ACTIVE_BOMB(element))
522 DrawLevelField(jx, jy);
524 /* draw player himself */
526 if (game.emulation == EMU_SUPAPLEX)
528 static int last_dir = MV_LEFT;
529 int action = (player->programmed_action ? player->programmed_action :
531 boolean action_moving =
533 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
534 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
536 graphic = GFX_SP_MURPHY;
540 if (player->MovDir == MV_LEFT)
541 graphic = GFX_MURPHY_PUSH_LEFT;
542 else if (player->MovDir == MV_RIGHT)
543 graphic = GFX_MURPHY_PUSH_RIGHT;
544 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
545 graphic = GFX_MURPHY_PUSH_LEFT;
546 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
547 graphic = GFX_MURPHY_PUSH_RIGHT;
549 else if (player->snapped)
551 if (player->MovDir == MV_LEFT)
552 graphic = GFX_MURPHY_SNAP_LEFT;
553 else if (player->MovDir == MV_RIGHT)
554 graphic = GFX_MURPHY_SNAP_RIGHT;
555 else if (player->MovDir == MV_UP)
556 graphic = GFX_MURPHY_SNAP_UP;
557 else if (player->MovDir == MV_DOWN)
558 graphic = GFX_MURPHY_SNAP_DOWN;
560 else if (action_moving)
562 if (player->MovDir == MV_LEFT)
563 graphic = GFX_MURPHY_GO_LEFT;
564 else if (player->MovDir == MV_RIGHT)
565 graphic = GFX_MURPHY_GO_RIGHT;
566 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
567 graphic = GFX_MURPHY_GO_LEFT;
568 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
569 graphic = GFX_MURPHY_GO_RIGHT;
571 graphic += getGraphicAnimationPhase(3, 2, ANIM_OSCILLATE);
574 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
575 last_dir = player->MovDir;
579 if (player->MovDir == MV_LEFT)
581 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
582 else if (player->MovDir == MV_RIGHT)
584 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
585 else if (player->MovDir == MV_UP)
586 graphic = GFX_SPIELER1_UP;
587 else /* MV_DOWN || MV_NO_MOVING */
588 graphic = GFX_SPIELER1_DOWN;
590 graphic += player->index_nr * 3 * HEROES_PER_LINE;
591 graphic += player->Frame;
596 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
597 sxx = player->GfxPos;
599 syy = player->GfxPos;
602 if (!setup.soft_scrolling && ScreenMovPos)
605 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
607 if (player->Pushing && player->GfxPos)
609 int px = SCREENX(next_jx), py = SCREENY(next_jy);
611 if (element == EL_SOKOBAN_FELD_LEER ||
612 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
613 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
617 int element = Feld[next_jx][next_jy];
618 int graphic = el2gfx(element);
620 if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK) && sxx)
622 int phase = (player->GfxPos / (TILEX / 4));
624 if (player->MovDir == MV_LEFT)
627 graphic += (phase + 4) % 4;
630 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
634 /* draw things in front of player (active dynamite or dynabombs) */
636 if (IS_ACTIVE_BOMB(element))
638 graphic = el2gfx(element);
640 if (element == EL_DYNAMITE_ACTIVE)
642 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
647 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
651 if (game.emulation == EMU_SUPAPLEX)
652 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
654 DrawGraphicThruMask(sx, sy, graphic + phase);
657 if (player_is_moving && last_element == EL_EXPLODING)
659 int phase = Frame[last_jx][last_jy];
663 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
664 GFX_EXPLOSION + ((phase - 1) / delay - 1));
667 /* draw elements that stay over the player */
668 /* handle the field the player is leaving ... */
669 if (player_is_moving && IS_OVER_PLAYER(last_element))
670 DrawLevelField(last_jx, last_jy);
671 /* ... and the field the player is entering */
672 if (IS_OVER_PLAYER(element))
673 DrawLevelField(jx, jy);
675 if (setup.direct_draw)
677 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
678 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
679 int x_size = TILEX * (1 + ABS(jx - last_jx));
680 int y_size = TILEY * (1 + ABS(jy - last_jy));
682 XCopyArea(display, drawto_field, window, gc,
683 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
684 SetDrawtoField(DRAW_DIRECT);
687 MarkTileDirty(sx,sy);
690 static int getGraphicAnimationPhase(int frames, int delay, int mode)
694 if (mode == ANIM_OSCILLATE)
696 int max_anim_frames = 2 * frames - 2;
697 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
698 phase = (phase < frames ? phase : max_anim_frames - phase);
701 phase = (FrameCounter % (delay * frames)) / delay;
703 if (mode == ANIM_REVERSE)
709 void DrawGraphicAnimationExt(int x, int y, int graphic,
710 int frames, int delay, int mode, int mask_mode)
712 int phase = getGraphicAnimationPhase(frames, delay, mode);
714 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
716 if (mask_mode == USE_MASKING)
717 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
719 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
723 void DrawGraphicAnimation(int x, int y, int graphic,
724 int frames, int delay, int mode)
726 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
729 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
730 int frames, int delay, int mode)
732 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
735 void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
737 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
739 graphic -= GFX_START_ROCKSSCREEN;
740 *pixmap_nr = PIX_BACK;
741 *x = SX + (graphic % GFX_PER_LINE) * TILEX;
742 *y = SY + (graphic / GFX_PER_LINE) * TILEY;
744 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
746 graphic -= GFX_START_ROCKSMORE;
747 *pixmap_nr = PIX_MORE;
748 *x = (graphic % MORE_PER_LINE) * TILEX;
749 *y = (graphic / MORE_PER_LINE) * TILEY;
751 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
753 graphic -= GFX_START_ROCKSHEROES;
754 *pixmap_nr = PIX_HEROES;
755 *x = (graphic % HEROES_PER_LINE) * TILEX;
756 *y = (graphic / HEROES_PER_LINE) * TILEY;
758 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
760 graphic -= GFX_START_ROCKSFONT;
761 *pixmap_nr = PIX_BIGFONT;
762 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
763 *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
764 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
768 *pixmap_nr = PIX_MORE;
774 void DrawGraphic(int x, int y, int graphic)
777 if (!IN_SCR_FIELD(x,y))
779 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
780 printf("DrawGraphic(): This should never happen!\n");
785 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
789 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
794 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
795 XCopyArea(display, pix[pixmap_nr], d, gc,
796 src_x, src_y, TILEX, TILEY, x, y);
799 void DrawGraphicThruMask(int x, int y, int graphic)
802 if (!IN_SCR_FIELD(x,y))
804 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
805 printf("DrawGraphicThruMask(): This should never happen!\n");
810 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
814 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
822 if (graphic == GFX_LEERRAUM)
825 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
826 src_pixmap = pix[pixmap_nr];
827 drawing_gc = clip_gc[pixmap_nr];
829 if (tile_clipmask[tile] != None)
831 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
832 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
833 XCopyArea(display, src_pixmap, d, tile_clip_gc,
834 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
839 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
842 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
843 XCopyArea(display, src_pixmap, d, drawing_gc,
844 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
848 void DrawMiniGraphic(int x, int y, int graphic)
850 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
851 MarkTileDirty(x/2, y/2);
854 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
856 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
858 graphic -= GFX_START_ROCKSSCREEN;
859 *pixmap = pix[PIX_BACK];
860 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
861 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
863 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
865 graphic -= GFX_START_ROCKSMORE;
866 graphic -= ((graphic / MORE_PER_LINE) * MORE_PER_LINE) / 2;
867 *pixmap = pix[PIX_MORE];
868 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
869 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
871 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
873 graphic -= GFX_START_ROCKSFONT;
874 *pixmap = pix[PIX_SMALLFONT];
875 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
876 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
877 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
881 *pixmap = pix[PIX_MORE];
882 *x = MINI_MORE_STARTX;
883 *y = MINI_MORE_STARTY;
887 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
892 getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
893 XCopyArea(display, pixmap, d, gc,
894 src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
897 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
898 int cut_mode, int mask_mode)
900 int width = TILEX, height = TILEY;
902 int src_x, src_y, dest_x, dest_y;
910 DrawGraphic(x, y, graphic);
914 if (dx || dy) /* Verschiebung der Grafik? */
916 if (x < BX1) /* Element kommt von links ins Bild */
923 else if (x > BX2) /* Element kommt von rechts ins Bild */
929 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
935 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
937 else if (dx) /* allg. Bewegung in x-Richtung */
938 MarkTileDirty(x + SIGN(dx), y);
940 if (y < BY1) /* Element kommt von oben ins Bild */
942 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
950 else if (y > BY2) /* Element kommt von unten ins Bild */
956 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
962 else if (dy > 0 && cut_mode == CUT_ABOVE)
964 if (y == BY2) /* Element unterhalb des Bildes */
970 MarkTileDirty(x, y + 1);
971 } /* Element verläßt unten das Bild */
972 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
974 else if (dy) /* allg. Bewegung in y-Richtung */
975 MarkTileDirty(x, y + SIGN(dy));
978 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
979 src_pixmap = pix[pixmap_nr];
980 drawing_gc = clip_gc[pixmap_nr];
985 dest_x = FX + x * TILEX + dx;
986 dest_y = FY + y * TILEY + dy;
989 if (!IN_SCR_FIELD(x,y))
991 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
992 printf("DrawGraphicShifted(): This should never happen!\n");
997 if (mask_mode == USE_MASKING)
999 if (tile_clipmask[tile] != None)
1001 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
1002 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
1003 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
1004 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1009 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1012 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
1013 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
1014 src_x, src_y, width, height, dest_x, dest_y);
1018 XCopyArea(display, src_pixmap, drawto_field, gc,
1019 src_x, src_y, width, height, dest_x, dest_y);
1024 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1027 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1030 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1031 int cut_mode, int mask_mode)
1033 int ux = LEVELX(x), uy = LEVELY(y);
1034 int graphic = el2gfx(element);
1035 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1036 int phase4 = phase8 / 2;
1037 int phase2 = phase8 / 4;
1038 int dir = MovDir[ux][uy];
1040 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1042 graphic += 4 * !phase2;
1046 else if (dir == MV_LEFT)
1048 else if (dir == MV_DOWN)
1051 else if (element == EL_SP_SNIKSNAK)
1054 graphic = GFX_SP_SNIKSNAK_LEFT;
1055 else if (dir == MV_RIGHT)
1056 graphic = GFX_SP_SNIKSNAK_RIGHT;
1057 else if (dir == MV_UP)
1058 graphic = GFX_SP_SNIKSNAK_UP;
1060 graphic = GFX_SP_SNIKSNAK_DOWN;
1062 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1064 else if (element == EL_SP_ELECTRON)
1066 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1068 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1069 element == EL_SCHWEIN || element == EL_DRACHE)
1072 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1073 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1074 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1075 else if (dir == MV_RIGHT)
1076 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1077 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1078 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1079 else if (dir == MV_UP)
1080 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1081 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1082 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1084 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1085 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1086 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1090 else if (element == EL_SONDE)
1092 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1094 else if (element == EL_SALZSAEURE)
1096 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1098 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1102 else if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK ||
1103 IS_GEM(element)) && !cut_mode)
1105 if (element == EL_FELSBROCKEN || element == EL_SP_ZONK)
1108 graphic += (4 - phase4) % 4;
1109 else if (dir == MV_RIGHT)
1112 graphic += phase2 * 2;
1114 else if (element != EL_SP_INFOTRON)
1117 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1118 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1120 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1122 else if (IS_AMOEBOID(element))
1124 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1125 graphic += (x + 2 * y + 4) % 4;
1127 else if (element == EL_MAUER_LEBT)
1129 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1131 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1132 links_massiv = TRUE;
1133 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1134 rechts_massiv = TRUE;
1136 if (links_massiv && rechts_massiv)
1137 graphic = GFX_MAUERWERK;
1138 else if (links_massiv)
1139 graphic = GFX_MAUER_R;
1140 else if (rechts_massiv)
1141 graphic = GFX_MAUER_L;
1145 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1146 else if (mask_mode == USE_MASKING)
1147 DrawGraphicThruMask(x, y, graphic);
1149 DrawGraphic(x, y, graphic);
1152 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1153 int cut_mode, int mask_mode)
1155 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1156 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1157 cut_mode, mask_mode);
1160 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1163 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1166 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1169 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1172 void DrawScreenElementThruMask(int x, int y, int element)
1174 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1177 void DrawLevelElementThruMask(int x, int y, int element)
1179 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1182 void DrawLevelFieldThruMask(int x, int y)
1184 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1187 void ErdreichAnbroeckeln(int x, int y)
1189 int i, width, height, cx,cy;
1190 int ux = LEVELX(x), uy = LEVELY(y);
1191 int element, graphic;
1193 static int xy[4][2] =
1201 if (!IN_LEV_FIELD(ux, uy))
1204 element = Feld[ux][uy];
1206 if (element == EL_ERDREICH)
1208 if (!IN_SCR_FIELD(x, y))
1211 graphic = GFX_ERDENRAND;
1217 uxx = ux + xy[i][0];
1218 uyy = uy + xy[i][1];
1219 if (!IN_LEV_FIELD(uxx, uyy))
1222 element = Feld[uxx][uyy];
1224 if (element == EL_ERDREICH)
1227 if (i == 1 || i == 2)
1231 cx = (i == 2 ? TILEX - snip : 0);
1239 cy = (i == 3 ? TILEY - snip : 0);
1242 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1243 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1244 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1245 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1248 MarkTileDirty(x, y);
1252 graphic = GFX_ERDENRAND;
1256 int xx, yy, uxx, uyy;
1260 uxx = ux + xy[i][0];
1261 uyy = uy + xy[i][1];
1263 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1264 !IN_SCR_FIELD(xx, yy))
1267 if (i == 1 || i == 2)
1271 cx = (i == 1 ? TILEX - snip : 0);
1279 cy = (i==0 ? TILEY-snip : 0);
1282 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1283 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1284 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1285 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1287 MarkTileDirty(xx, yy);
1292 void DrawScreenElement(int x, int y, int element)
1294 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1295 ErdreichAnbroeckeln(x, y);
1298 void DrawLevelElement(int x, int y, int element)
1300 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1301 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1304 void DrawScreenField(int x, int y)
1306 int ux = LEVELX(x), uy = LEVELY(y);
1309 if (!IN_LEV_FIELD(ux, uy))
1311 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1312 element = EL_LEERRAUM;
1314 element = BorderElement;
1316 DrawScreenElement(x, y, element);
1320 element = Feld[ux][uy];
1322 if (IS_MOVING(ux, uy))
1324 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1325 boolean cut_mode = NO_CUTTING;
1327 if (Store[ux][uy] == EL_MORAST_LEER ||
1328 Store[ux][uy] == EL_SIEB_LEER ||
1329 Store[ux][uy] == EL_SIEB2_LEER ||
1330 Store[ux][uy] == EL_AMOEBE_NASS)
1331 cut_mode = CUT_ABOVE;
1332 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1333 Store[ux][uy] == EL_SIEB_VOLL ||
1334 Store[ux][uy] == EL_SIEB2_VOLL)
1335 cut_mode = CUT_BELOW;
1337 if (cut_mode == CUT_ABOVE)
1338 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1340 DrawScreenElement(x, y, EL_LEERRAUM);
1343 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1345 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1347 if (Store[ux][uy] == EL_SALZSAEURE)
1348 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1350 else if (IS_BLOCKED(ux, uy))
1355 boolean cut_mode = NO_CUTTING;
1357 Blocked2Moving(ux, uy, &oldx, &oldy);
1360 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1361 MovDir[oldx][oldy] == MV_RIGHT);
1363 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1364 Store[oldx][oldy] == EL_SIEB_LEER ||
1365 Store[oldx][oldy] == EL_SIEB2_LEER ||
1366 Store[oldx][oldy] == EL_AMOEBE_NASS)
1367 cut_mode = CUT_ABOVE;
1369 DrawScreenElement(x, y, EL_LEERRAUM);
1370 element = Feld[oldx][oldy];
1373 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1375 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1377 else if (IS_DRAWABLE(element))
1378 DrawScreenElement(x, y, element);
1380 DrawScreenElement(x, y, EL_LEERRAUM);
1383 void DrawLevelField(int x, int y)
1385 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1386 DrawScreenField(SCREENX(x), SCREENY(y));
1387 else if (IS_MOVING(x, y))
1391 Moving2Blocked(x, y, &newx, &newy);
1392 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1393 DrawScreenField(SCREENX(newx), SCREENY(newy));
1395 else if (IS_BLOCKED(x, y))
1399 Blocked2Moving(x, y, &oldx, &oldy);
1400 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1401 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1405 void DrawMiniElement(int x, int y, int element)
1411 DrawMiniGraphic(x, y, -1);
1415 graphic = el2gfx(element);
1416 DrawMiniGraphic(x, y, graphic);
1419 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1421 int x = sx + scroll_x, y = sy + scroll_y;
1423 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1424 DrawMiniElement(sx, sy, EL_LEERRAUM);
1425 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1426 DrawMiniElement(sx, sy, Feld[x][y]);
1429 int steel_type, steel_position;
1432 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1433 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1434 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1435 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1436 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1437 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1440 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1441 steel_position = (x == -1 && y == -1 ? 0 :
1442 x == lev_fieldx && y == -1 ? 1 :
1443 x == -1 && y == lev_fieldy ? 2 :
1444 x == lev_fieldx && y == lev_fieldy ? 3 :
1445 x == -1 || x == lev_fieldx ? 4 :
1446 y == -1 || y == lev_fieldy ? 5 : -1);
1448 if (steel_position != -1)
1449 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1453 void DrawMicroElement(int xpos, int ypos, int element)
1457 if (element == EL_LEERRAUM)
1460 graphic = el2gfx(element);
1462 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1464 graphic -= GFX_START_ROCKSMORE;
1465 graphic -= ((graphic / MORE_PER_LINE) * MORE_PER_LINE) / 2;
1466 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1467 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1468 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1469 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1472 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1473 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1474 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1475 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1484 for(x=BX1; x<=BX2; x++)
1485 for(y=BY1; y<=BY2; y++)
1486 DrawScreenField(x, y);
1488 redraw_mask |= REDRAW_FIELD;
1491 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1495 for(x=0; x<size_x; x++)
1496 for(y=0; y<size_y; y++)
1497 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1499 redraw_mask |= REDRAW_FIELD;
1502 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1506 XFillRectangle(display, drawto, gc,
1507 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1509 if (lev_fieldx < STD_LEV_FIELDX)
1510 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1511 if (lev_fieldy < STD_LEV_FIELDY)
1512 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1514 xpos += MICRO_TILEX;
1515 ypos += MICRO_TILEY;
1517 for(x=-1; x<=STD_LEV_FIELDX; x++)
1519 for(y=-1; y<=STD_LEV_FIELDY; y++)
1521 int lx = from_x + x, ly = from_y + y;
1523 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1524 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1526 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1527 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1532 redraw_mask |= REDRAW_MICROLEVEL;
1535 #define MICROLABEL_EMPTY 0
1536 #define MICROLABEL_LEVEL_NAME 1
1537 #define MICROLABEL_CREATED_BY 2
1538 #define MICROLABEL_LEVEL_AUTHOR 3
1539 #define MICROLABEL_IMPORTED_FROM 4
1540 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1542 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1544 static void DrawMicroLevelLabelExt(int mode)
1546 char label_text[MAX_MICROLABEL_SIZE + 1];
1548 XFillRectangle(display, drawto,gc,
1549 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1551 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1552 mode == MICROLABEL_CREATED_BY ? "created by" :
1553 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1554 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1555 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1556 leveldir[leveldir_nr].imported_from : ""),
1557 MAX_MICROLABEL_SIZE);
1558 label_text[MAX_MICROLABEL_SIZE] = '\0';
1560 if (strlen(label_text) > 0)
1562 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1563 int lypos = MICROLABEL_YPOS;
1565 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1568 redraw_mask |= REDRAW_MICROLEVEL;
1571 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1573 static unsigned long scroll_delay = 0;
1574 static unsigned long label_delay = 0;
1575 static int from_x, from_y, scroll_direction;
1576 static int label_state, label_counter;
1580 from_x = from_y = 0;
1581 scroll_direction = MV_RIGHT;
1585 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1586 DrawMicroLevelLabelExt(label_state);
1588 /* initialize delay counters */
1589 DelayReached(&scroll_delay, 0);
1590 DelayReached(&label_delay, 0);
1595 /* scroll micro level, if needed */
1596 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1597 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1599 switch (scroll_direction)
1605 scroll_direction = MV_UP;
1609 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1612 scroll_direction = MV_DOWN;
1619 scroll_direction = MV_RIGHT;
1623 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1626 scroll_direction = MV_LEFT;
1633 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1636 /* redraw micro level label, if needed */
1637 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1638 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1639 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1640 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1642 int max_label_counter = 23;
1644 if (leveldir[leveldir_nr].imported_from != NULL)
1645 max_label_counter += 14;
1647 label_counter = (label_counter + 1) % max_label_counter;
1648 label_state = (label_counter >= 0 && label_counter <= 7 ?
1649 MICROLABEL_LEVEL_NAME :
1650 label_counter >= 9 && label_counter <= 12 ?
1651 MICROLABEL_CREATED_BY :
1652 label_counter >= 14 && label_counter <= 21 ?
1653 MICROLABEL_LEVEL_AUTHOR :
1654 label_counter >= 23 && label_counter <= 26 ?
1655 MICROLABEL_IMPORTED_FROM :
1656 label_counter >= 28 && label_counter <= 35 ?
1657 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1658 DrawMicroLevelLabelExt(label_state);
1662 int REQ_in_range(int x, int y)
1664 if (y > DY+249 && y < DY+278)
1666 if (x > DX+1 && x < DX+48)
1668 else if (x > DX+51 && x < DX+98)
1674 boolean Request(char *text, unsigned int req_state)
1676 int mx, my, ty, result = -1;
1677 unsigned int old_door_state;
1680 /* pause network game while waiting for request to answer */
1681 if (options.network &&
1682 game_status == PLAYING &&
1683 req_state & REQUEST_WAIT_FOR)
1684 SendToServer_PausePlaying();
1687 old_door_state = GetDoorState();
1691 CloseDoor(DOOR_CLOSE_1);
1693 /* save old door content */
1694 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1695 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1696 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1698 /* clear door drawing field */
1699 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1701 /* write text for request */
1702 for(ty=0; ty<13; ty++)
1710 for(tl=0,tx=0; tx<7; tl++,tx++)
1713 if (!tc || tc == 32)
1724 DrawTextExt(drawto, gc,
1725 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1726 txt, FS_SMALL, FC_YELLOW);
1727 text += tl + (tc == 32 ? 1 : 0);
1730 if (req_state & REQ_ASK)
1732 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1733 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1735 else if (req_state & REQ_CONFIRM)
1737 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1739 else if (req_state & REQ_PLAYER)
1741 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1742 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1743 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1744 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1747 /* copy request gadgets to door backbuffer */
1748 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1749 DX, DY, DXSIZE, DYSIZE,
1750 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1752 OpenDoor(DOOR_OPEN_1);
1758 if (!(req_state & REQUEST_WAIT_FOR))
1761 if (game_status != MAINMENU)
1764 button_status = MB_RELEASED;
1766 request_gadget_id = -1;
1770 if (XPending(display))
1774 XNextEvent(display, &event);
1782 if (event.type == MotionNotify)
1789 if (!XQueryPointer(display, window, &root, &child,
1790 &root_x, &root_y, &win_x, &win_y, &mask))
1796 motion_status = TRUE;
1797 mx = ((XMotionEvent *) &event)->x;
1798 my = ((XMotionEvent *) &event)->y;
1802 motion_status = FALSE;
1803 mx = ((XButtonEvent *) &event)->x;
1804 my = ((XButtonEvent *) &event)->y;
1805 if (event.type==ButtonPress)
1806 button_status = ((XButtonEvent *) &event)->button;
1808 button_status = MB_RELEASED;
1811 /* this sets 'request_gadget_id' */
1812 HandleGadgets(mx, my, button_status);
1814 switch(request_gadget_id)
1816 case TOOL_CTRL_ID_YES:
1819 case TOOL_CTRL_ID_NO:
1822 case TOOL_CTRL_ID_CONFIRM:
1823 result = TRUE | FALSE;
1826 case TOOL_CTRL_ID_PLAYER_1:
1829 case TOOL_CTRL_ID_PLAYER_2:
1832 case TOOL_CTRL_ID_PLAYER_3:
1835 case TOOL_CTRL_ID_PLAYER_4:
1847 switch(XLookupKeysym((XKeyEvent *)&event,
1848 ((XKeyEvent *)&event)->state))
1861 if (req_state & REQ_PLAYER)
1866 key_joystick_mapping = 0;
1870 HandleOtherEvents(&event);
1874 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1876 int joy = AnyJoystick();
1878 if (joy & JOY_BUTTON_1)
1880 else if (joy & JOY_BUTTON_2)
1886 /* don't eat all CPU time */
1890 if (game_status != MAINMENU)
1895 if (!(req_state & REQ_STAY_OPEN))
1897 CloseDoor(DOOR_CLOSE_1);
1899 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1901 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1902 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1903 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1904 OpenDoor(DOOR_OPEN_1);
1911 /* continue network game after request */
1912 if (options.network &&
1913 game_status == PLAYING &&
1914 req_state & REQUEST_WAIT_FOR)
1915 SendToServer_ContinuePlaying();
1921 unsigned int OpenDoor(unsigned int door_state)
1923 unsigned int new_door_state;
1925 if (door_state & DOOR_COPY_BACK)
1927 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1928 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1929 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1930 door_state &= ~DOOR_COPY_BACK;
1933 new_door_state = MoveDoor(door_state);
1935 return(new_door_state);
1938 unsigned int CloseDoor(unsigned int door_state)
1940 unsigned int new_door_state;
1942 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1943 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1944 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1945 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1947 new_door_state = MoveDoor(door_state);
1949 return(new_door_state);
1952 unsigned int GetDoorState()
1954 return(MoveDoor(DOOR_GET_STATE));
1957 unsigned int MoveDoor(unsigned int door_state)
1959 static int door1 = DOOR_OPEN_1;
1960 static int door2 = DOOR_CLOSE_2;
1961 static unsigned long door_delay = 0;
1962 int x, start, stepsize = 2;
1963 unsigned long door_delay_value = stepsize * 5;
1965 if (door_state == DOOR_GET_STATE)
1966 return(door1 | door2);
1968 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1969 door_state &= ~DOOR_OPEN_1;
1970 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1971 door_state &= ~DOOR_CLOSE_1;
1972 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1973 door_state &= ~DOOR_OPEN_2;
1974 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1975 door_state &= ~DOOR_CLOSE_2;
1977 if (setup.quick_doors)
1980 door_delay_value = 0;
1981 StopSound(SND_OEFFNEN);
1984 if (door_state & DOOR_ACTION)
1986 if (!(door_state & DOOR_NO_DELAY))
1987 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1989 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1991 for(x=start; x<=DXSIZE; x+=stepsize)
1993 WaitUntilDelayReached(&door_delay, door_delay_value);
1995 if (door_state & DOOR_ACTION_1)
1997 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1998 int j = (DXSIZE - i) / 3;
2000 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2001 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2002 DXSIZE,DYSIZE - i/2, DX, DY);
2004 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2006 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2007 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2008 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2009 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2010 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2011 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2013 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2014 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2015 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2016 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2017 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2018 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2020 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2021 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2023 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2024 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2026 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2027 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2028 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2029 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2030 DX + DXSIZE - i, DY + 77 + j);
2031 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2032 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2033 DX + DXSIZE - i, DY + 203 + j);
2035 redraw_mask |= REDRAW_DOOR_1;
2038 if (door_state & DOOR_ACTION_2)
2040 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2041 int j = (VXSIZE - i) / 3;
2043 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2044 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2045 VXSIZE, VYSIZE - i/2, VX, VY);
2047 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2049 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2050 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2051 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2052 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2053 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2054 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2055 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2056 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2058 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2059 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2060 VX, VY + VYSIZE / 2 - j);
2061 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2062 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2063 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2064 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2065 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2067 redraw_mask |= REDRAW_DOOR_2;
2072 if (game_status == MAINMENU)
2077 if (setup.quick_doors)
2078 StopSound(SND_OEFFNEN);
2080 if (door_state & DOOR_ACTION_1)
2081 door1 = door_state & DOOR_ACTION_1;
2082 if (door_state & DOOR_ACTION_2)
2083 door2 = door_state & DOOR_ACTION_2;
2085 return (door1 | door2);
2088 void DrawSpecialEditorDoor()
2090 /* draw bigger toolbox window */
2091 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2092 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2094 redraw_mask |= REDRAW_ALL;
2097 void UndrawSpecialEditorDoor()
2099 /* draw normal tape recorder window */
2100 XCopyArea(display, pix[PIX_BACK], drawto, gc,
2101 562, 344, 108, 56, EX - 4, EY - 12);
2103 redraw_mask |= REDRAW_ALL;
2106 int ReadPixel(Drawable d, int x, int y)
2108 XImage *pixel_image;
2109 unsigned long pixel_value;
2111 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2112 pixel_value = XGetPixel(pixel_image, 0, 0);
2114 XDestroyImage(pixel_image);
2119 /* ---------- new tool button stuff ---------------------------------------- */
2121 /* graphic position values for tool buttons */
2122 #define TOOL_BUTTON_YES_XPOS 2
2123 #define TOOL_BUTTON_YES_YPOS 250
2124 #define TOOL_BUTTON_YES_GFX_YPOS 0
2125 #define TOOL_BUTTON_YES_XSIZE 46
2126 #define TOOL_BUTTON_YES_YSIZE 28
2127 #define TOOL_BUTTON_NO_XPOS 52
2128 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2129 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2130 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2131 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2132 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2133 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2134 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2135 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2136 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2137 #define TOOL_BUTTON_PLAYER_XSIZE 30
2138 #define TOOL_BUTTON_PLAYER_YSIZE 30
2139 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2140 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2141 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2142 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2143 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2144 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2145 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2146 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2147 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2148 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2149 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2150 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2151 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2152 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2153 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2154 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2155 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2156 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2157 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2158 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2167 } toolbutton_info[NUM_TOOL_BUTTONS] =
2170 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2171 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2172 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2177 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2178 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2179 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2184 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2185 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2186 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2187 TOOL_CTRL_ID_CONFIRM,
2191 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2192 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2193 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2194 TOOL_CTRL_ID_PLAYER_1,
2198 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2199 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2200 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2201 TOOL_CTRL_ID_PLAYER_2,
2205 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2206 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2207 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2208 TOOL_CTRL_ID_PLAYER_3,
2212 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2213 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2214 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2215 TOOL_CTRL_ID_PLAYER_4,
2220 static void DoNotDisplayInfoText(void *ptr)
2225 void CreateToolButtons()
2229 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2231 Pixmap gd_pixmap = pix[PIX_DOOR];
2232 Pixmap deco_pixmap = None;
2233 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2234 struct GadgetInfo *gi;
2235 unsigned long event_mask;
2236 int gd_xoffset, gd_yoffset;
2237 int gd_x1, gd_x2, gd_y;
2240 event_mask = GD_EVENT_RELEASED;
2242 gd_xoffset = toolbutton_info[i].xpos;
2243 gd_yoffset = toolbutton_info[i].ypos;
2244 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2245 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2246 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2248 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2250 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2251 &deco_pixmap, &deco_x, &deco_y);
2252 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2253 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2256 gi = CreateGadget(GDI_CUSTOM_ID, id,
2257 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2258 GDI_X, DX + toolbutton_info[i].x,
2259 GDI_Y, DY + toolbutton_info[i].y,
2260 GDI_WIDTH, toolbutton_info[i].width,
2261 GDI_HEIGHT, toolbutton_info[i].height,
2262 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2263 GDI_STATE, GD_BUTTON_UNPRESSED,
2264 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2265 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2266 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2267 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2268 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2269 GDI_DECORATION_SHIFTING, 1, 1,
2270 GDI_EVENT_MASK, event_mask,
2271 GDI_CALLBACK_ACTION, HandleToolButtons,
2272 GDI_CALLBACK_INFO, DoNotDisplayInfoText,
2276 Error(ERR_EXIT, "cannot create gadget");
2278 tool_gadget[id] = gi;
2282 static void UnmapToolButtons()
2286 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2287 UnmapGadget(tool_gadget[i]);
2290 static void HandleToolButtons(struct GadgetInfo *gi)
2292 request_gadget_id = gi->custom_id;
2295 int el2gfx(int element)
2299 case EL_LEERRAUM: return -1;
2300 case EL_ERDREICH: return GFX_ERDREICH;
2301 case EL_MAUERWERK: return GFX_MAUERWERK;
2302 case EL_FELSBODEN: return GFX_FELSBODEN;
2303 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2304 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2305 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2306 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2307 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2308 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2309 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2310 case EL_SPIELER1: return GFX_SPIELER1;
2311 case EL_SPIELER2: return GFX_SPIELER2;
2312 case EL_SPIELER3: return GFX_SPIELER3;
2313 case EL_SPIELER4: return GFX_SPIELER4;
2314 case EL_KAEFER: return GFX_KAEFER;
2315 case EL_KAEFER_R: return GFX_KAEFER_R;
2316 case EL_KAEFER_O: return GFX_KAEFER_O;
2317 case EL_KAEFER_L: return GFX_KAEFER_L;
2318 case EL_KAEFER_U: return GFX_KAEFER_U;
2319 case EL_FLIEGER: return GFX_FLIEGER;
2320 case EL_FLIEGER_R: return GFX_FLIEGER_R;
2321 case EL_FLIEGER_O: return GFX_FLIEGER_O;
2322 case EL_FLIEGER_L: return GFX_FLIEGER_L;
2323 case EL_FLIEGER_U: return GFX_FLIEGER_U;
2324 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2325 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
2326 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
2327 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
2328 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
2329 case EL_FIREFLY: return GFX_FIREFLY;
2330 case EL_FIREFLY_R: return GFX_FIREFLY_R;
2331 case EL_FIREFLY_O: return GFX_FIREFLY_O;
2332 case EL_FIREFLY_L: return GFX_FIREFLY_L;
2333 case EL_FIREFLY_U: return GFX_FIREFLY_U;
2334 case EL_MAMPFER: return GFX_MAMPFER;
2335 case EL_ROBOT: return GFX_ROBOT;
2336 case EL_BETON: return GFX_BETON;
2337 case EL_DIAMANT: return GFX_DIAMANT;
2338 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2339 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2340 case EL_TROPFEN: return GFX_TROPFEN;
2341 case EL_BOMBE: return GFX_BOMBE;
2342 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2343 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2344 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2345 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2346 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2347 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2348 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2349 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2350 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2351 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2352 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2353 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2354 case EL_LIFE: return GFX_LIFE;
2355 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2356 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2357 case EL_BADEWANNE: return GFX_BADEWANNE;
2358 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2359 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2360 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2361 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2362 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2363 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2364 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2365 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2366 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2367 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2368 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2369 case EL_PFORTE1: return GFX_PFORTE1;
2370 case EL_PFORTE2: return GFX_PFORTE2;
2371 case EL_PFORTE3: return GFX_PFORTE3;
2372 case EL_PFORTE4: return GFX_PFORTE4;
2373 case EL_PFORTE1X: return GFX_PFORTE1X;
2374 case EL_PFORTE2X: return GFX_PFORTE2X;
2375 case EL_PFORTE3X: return GFX_PFORTE3X;
2376 case EL_PFORTE4X: return GFX_PFORTE4X;
2377 case EL_DYNAMITE_INACTIVE: return GFX_DYNAMIT_AUS;
2378 case EL_PACMAN: return GFX_PACMAN;
2379 case EL_PACMAN_R: return GFX_PACMAN_R;
2380 case EL_PACMAN_O: return GFX_PACMAN_O;
2381 case EL_PACMAN_L: return GFX_PACMAN_L;
2382 case EL_PACMAN_U: return GFX_PACMAN_U;
2383 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2384 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2385 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2386 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2387 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2388 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2389 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2390 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2391 case EL_MAUER_X: return GFX_MAUER_X;
2392 case EL_MAUER_Y: return GFX_MAUER_Y;
2393 case EL_MAUER_XY: return GFX_MAUER_XY;
2394 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2395 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2396 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2397 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2398 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2399 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2400 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2401 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2402 case EL_MAMPFER2: return GFX_MAMPFER2;
2403 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2404 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2405 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2406 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2407 case EL_DYNABOMB_ACTIVE_1: return GFX_DYNABOMB;
2408 case EL_DYNABOMB_ACTIVE_2: return GFX_DYNABOMB;
2409 case EL_DYNABOMB_ACTIVE_3: return GFX_DYNABOMB;
2410 case EL_DYNABOMB_ACTIVE_4: return GFX_DYNABOMB;
2411 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2412 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2413 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2414 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2415 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2416 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2417 case EL_MAULWURF: return GFX_MAULWURF;
2418 case EL_PINGUIN: return GFX_PINGUIN;
2419 case EL_SCHWEIN: return GFX_SCHWEIN;
2420 case EL_DRACHE: return GFX_DRACHE;
2421 case EL_SONDE: return GFX_SONDE;
2422 case EL_PFEIL_L: return GFX_PFEIL_L;
2423 case EL_PFEIL_R: return GFX_PFEIL_R;
2424 case EL_PFEIL_O: return GFX_PFEIL_O;
2425 case EL_PFEIL_U: return GFX_PFEIL_U;
2426 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2427 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2428 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2429 case EL_SP_ZONK: return GFX_SP_ZONK;
2430 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2431 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2432 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2433 case EL_EM_GATE_1: return GFX_EM_GATE_1;
2434 case EL_EM_GATE_2: return GFX_EM_GATE_2;
2435 case EL_EM_GATE_3: return GFX_EM_GATE_3;
2436 case EL_EM_GATE_4: return GFX_EM_GATE_4;
2437 case EL_EM_GATE_1X: return GFX_EM_GATE_1X;
2438 case EL_EM_GATE_2X: return GFX_EM_GATE_2X;
2439 case EL_EM_GATE_3X: return GFX_EM_GATE_3X;
2440 case EL_EM_GATE_4X: return GFX_EM_GATE_4X;
2441 case EL_EM_KEY_1_FILE: return GFX_EM_KEY_1;
2442 case EL_EM_KEY_2_FILE: return GFX_EM_KEY_2;
2443 case EL_EM_KEY_3_FILE: return GFX_EM_KEY_3;
2444 case EL_EM_KEY_4_FILE: return GFX_EM_KEY_4;
2445 case EL_EM_KEY_1: return GFX_EM_KEY_1;
2446 case EL_EM_KEY_2: return GFX_EM_KEY_2;
2447 case EL_EM_KEY_3: return GFX_EM_KEY_3;
2448 case EL_EM_KEY_4: return GFX_EM_KEY_4;
2449 case EL_PEARL: return GFX_PEARL;
2450 case EL_CRYSTAL: return GFX_CRYSTAL;
2451 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2452 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2453 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2454 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2455 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2456 case EL_FORCE_FIELD: return GFX_FORCE_FIELD;
2457 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2458 case EL_SWITCH_GATE_OPEN: return GFX_SWITCH_GATE_OPEN;
2459 case EL_SWITCH_GATE_CLOSED: return GFX_SWITCH_GATE_CLOSED;
2460 case EL_SWITCH_GATE_SWITCH: return GFX_SWITCH_GATE_SWITCH;
2461 case EL_TIME_GATE: return GFX_TIME_GATE;
2462 case EL_TIME_GATE_WHEEL: return GFX_TIME_GATE_WHEEL;
2463 case EL_BELT_GREEN_LEFT: return GFX_BELT_GREEN_LEFT;
2464 case EL_BELT_GREEN_MIDDLE: return GFX_BELT_GREEN_MIDDLE;
2465 case EL_BELT_GREEN_RIGHT: return GFX_BELT_GREEN_RIGHT;
2466 case EL_BELT_GREEN_SWITCH: return GFX_BELT_GREEN_SWITCH;
2467 case EL_BELT_RED_LEFT: return GFX_BELT_RED_LEFT;
2468 case EL_BELT_RED_MIDDLE: return GFX_BELT_RED_MIDDLE;
2469 case EL_BELT_RED_RIGHT: return GFX_BELT_RED_RIGHT;
2470 case EL_BELT_RED_SWITCH: return GFX_BELT_RED_SWITCH;
2471 case EL_BELT_BLUE_LEFT: return GFX_BELT_BLUE_LEFT;
2472 case EL_BELT_BLUE_MIDDLE: return GFX_BELT_BLUE_MIDDLE;
2473 case EL_BELT_BLUE_RIGHT: return GFX_BELT_BLUE_RIGHT;
2474 case EL_BELT_BLUE_SWITCH: return GFX_BELT_BLUE_SWITCH;
2475 case EL_LANDMINE: return GFX_LANDMINE;
2476 case EL_ENVELOPE: return GFX_ENVELOPE;
2477 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH;
2478 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2479 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2480 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2481 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2482 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2483 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2484 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2485 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2486 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2487 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2488 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2489 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2490 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2491 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2492 case EL_MOLE_UP: return GFX_MOLE_UP;
2493 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2494 case EL_STEEL_SLANTED: return GFX_STEEL_SLANTED;
2495 case EL_SAND_INVISIBLE: return GFX_SAND_INVISIBLE;
2499 if (IS_CHAR(element))
2500 return GFX_CHAR_START + (element - EL_CHAR_START);
2501 else if (element >= EL_SP_START && element <= EL_SP_END)
2503 int nr_element = element - EL_SP_START;
2504 int gfx_per_line = 8;
2506 (nr_element / gfx_per_line) * MORE_PER_LINE +
2507 (nr_element % gfx_per_line);
2509 return GFX_START_ROCKSMORE + nr_graphic;