From: Holger Schemel Date: Sat, 2 Dec 2000 02:05:20 +0000 (+0100) Subject: rnd-20001202-2-src X-Git-Tag: 2.0.0^2~22 X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=commitdiff_plain;h=222cd4187e6632bd904a937f167a2f1c70b8f66d rnd-20001202-2-src --- diff --git a/src/init.c b/src/init.c index adfd3f2c..3a0c54ed 100644 --- a/src/init.c +++ b/src/init.c @@ -310,15 +310,19 @@ void InitJoysticks() void InitDisplay() { - char *x11_icon_filename = getPath3(options.ro_base_directory, - GRAPHICS_DIRECTORY, - "rocks_icon.xbm"); - char *x11_iconmask_filename = getPath3(options.ro_base_directory, - GRAPHICS_DIRECTORY, - "rocks_iconmask.xbm"); + char *gfx_dir = getPath2(options.ro_base_directory, GRAPHICS_DIRECTORY); + char *x11_icon_filename = getPath2(gfx_dir, X11_ICON_FILENAME); + char *x11_iconmask_filename = getPath2(gfx_dir, X11_ICONMASK_FILENAME); + char *msdos_pointer_filename = getPath2(gfx_dir, MSDOS_POINTER_FILENAME); + + free(gfx_dir); InitProgramInfo(program_name, PROGRAM_TITLE_STRING, WINDOW_TITLE_STRING, - ICON_TITLE_STRING, x11_icon_filename, x11_iconmask_filename); + ICON_TITLE_STRING, x11_icon_filename, x11_iconmask_filename, + msdos_pointer_filename); + + InitScrollbufferSize(FXSIZE, FYSIZE); /* (only needed for MS-DOS code) */ + InitVideoDisplay(); InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen); diff --git a/src/libgame/Makefile b/src/libgame/Makefile index f096730d..c325fef5 100644 --- a/src/libgame/Makefile +++ b/src/libgame/Makefile @@ -6,7 +6,7 @@ SRCS = libgame.c \ private.c \ system.c \ - buttons.c \ + gadgets.c \ text.c \ sound.c \ pcx.c \ @@ -20,7 +20,7 @@ SRCS = libgame.c \ OBJS = libgame.o \ private.o \ system.o \ - buttons.o \ + gadgets.o \ text.o \ sound.o \ pcx.o \ diff --git a/src/libgame/buttons.c b/src/libgame/buttons.c deleted file mode 100644 index 3fad7560..00000000 --- a/src/libgame/buttons.c +++ /dev/null @@ -1,1349 +0,0 @@ -/*********************************************************** -* Rocks'n'Diamonds -- McDuffin Strikes Back! * -*----------------------------------------------------------* -* (c) 1995-98 Artsoft Entertainment * -* Holger Schemel * -* Oststrasse 11a * -* 33604 Bielefeld * -* phone: ++49 +521 290471 * -* email: aeglos@valinor.owl.de * -*----------------------------------------------------------* -* buttons.c * -***********************************************************/ - -#include - -#include "libgame.h" - -#include "main_TMP.h" - -#include "buttons.h" - -/* some positions in the video tape control window */ -#define VIDEO_DATE_LABEL_XPOS (VIDEO_DISPLAY1_XPOS) -#define VIDEO_DATE_LABEL_YPOS (VIDEO_DISPLAY1_YPOS) -#define VIDEO_DATE_LABEL_XSIZE (VIDEO_DISPLAY_XSIZE) -#define VIDEO_DATE_LABEL_YSIZE (VIDEO_DISPLAY_YSIZE) -#define VIDEO_DATE_XPOS (VIDEO_DISPLAY1_XPOS + 1) -#define VIDEO_DATE_YPOS (VIDEO_DISPLAY1_YPOS + 14) -#define VIDEO_DATE_XSIZE (VIDEO_DISPLAY_XSIZE) -#define VIDEO_DATE_YSIZE 16 -#define VIDEO_REC_LABEL_XPOS (VIDEO_DISPLAY2_XPOS) -#define VIDEO_REC_LABEL_YPOS (VIDEO_DISPLAY2_YPOS) -#define VIDEO_REC_LABEL_XSIZE 20 -#define VIDEO_REC_LABEL_YSIZE 12 -#define VIDEO_REC_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS + 20) -#define VIDEO_REC_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS) -#define VIDEO_REC_SYMBOL_XSIZE 16 -#define VIDEO_REC_SYMBOL_YSIZE 16 -#define VIDEO_PLAY_LABEL_XPOS (VIDEO_DISPLAY2_XPOS + 65) -#define VIDEO_PLAY_LABEL_YPOS (VIDEO_DISPLAY2_YPOS) -#define VIDEO_PLAY_LABEL_XSIZE 22 -#define VIDEO_PLAY_LABEL_YSIZE 12 -#define VIDEO_PLAY_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS + 52) -#define VIDEO_PLAY_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS) -#define VIDEO_PLAY_SYMBOL_XSIZE 11 -#define VIDEO_PLAY_SYMBOL_YSIZE 13 -#define VIDEO_PAUSE_LABEL_XPOS (VIDEO_DISPLAY2_XPOS) -#define VIDEO_PAUSE_LABEL_YPOS (VIDEO_DISPLAY2_YPOS + 20) -#define VIDEO_PAUSE_LABEL_XSIZE 35 -#define VIDEO_PAUSE_LABEL_YSIZE 8 -#define VIDEO_PAUSE_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS + 35) -#define VIDEO_PAUSE_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS) -#define VIDEO_PAUSE_SYMBOL_XSIZE 17 -#define VIDEO_PAUSE_SYMBOL_YSIZE 13 -#define VIDEO_TIME_XPOS (VIDEO_DISPLAY2_XPOS + 38) -#define VIDEO_TIME_YPOS (VIDEO_DISPLAY2_YPOS + 14) -#define VIDEO_TIME_XSIZE 50 -#define VIDEO_TIME_YSIZE 16 - -/* special */ -#define VIDEO_PBEND_LABEL_XPOS 6 -#define VIDEO_PBEND_LABEL_YPOS 220 -#define VIDEO_PBEND_LABEL_XSIZE 35 -#define VIDEO_PBEND_LABEL_YSIZE 30 - -#define VIDEO_STATE_OFF (VIDEO_STATE_PLAY_OFF | \ - VIDEO_STATE_REC_OFF | \ - VIDEO_STATE_PAUSE_OFF | \ - VIDEO_STATE_FFWD_OFF | \ - VIDEO_STATE_PBEND_OFF | \ - VIDEO_STATE_DATE_OFF | \ - VIDEO_STATE_TIME_OFF) -#define VIDEO_PRESS_OFF (VIDEO_PRESS_PLAY_OFF | \ - VIDEO_PRESS_REC_OFF | \ - VIDEO_PRESS_PAUSE_OFF | \ - VIDEO_PRESS_STOP_OFF | \ - VIDEO_PRESS_EJECT_OFF) -#define VIDEO_ALL_OFF (VIDEO_STATE_OFF | VIDEO_PRESS_OFF) - -#define VIDEO_STATE_ON (VIDEO_STATE_PLAY_ON | \ - VIDEO_STATE_REC_ON | \ - VIDEO_STATE_PAUSE_ON | \ - VIDEO_STATE_FFWD_ON | \ - VIDEO_STATE_PBEND_ON | \ - VIDEO_STATE_DATE_ON | \ - VIDEO_STATE_TIME_ON) -#define VIDEO_PRESS_ON (VIDEO_PRESS_PLAY_ON | \ - VIDEO_PRESS_REC_ON | \ - VIDEO_PRESS_PAUSE_ON | \ - VIDEO_PRESS_STOP_ON | \ - VIDEO_PRESS_EJECT_ON) -#define VIDEO_ALL_ON (VIDEO_STATE_ON | VIDEO_PRESS_ON) - -#define VIDEO_STATE (VIDEO_STATE_ON | VIDEO_STATE_OFF) -#define VIDEO_PRESS (VIDEO_PRESS_ON | VIDEO_PRESS_OFF) -#define VIDEO_ALL (VIDEO_ALL_ON | VIDEO_ALL_OFF) - - -void DrawVideoDisplay(unsigned long state, unsigned long value) -{ - int i; - int part_label = 0, part_symbol = 1; - int xpos = 0, ypos = 1, xsize = 2, ysize = 3; - static char *monatsname[12] = - { - "JAN", "FEB", "MAR", "APR", "MAY", "JUN", - "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" - }; - static int video_pos[5][2][4] = - { - {{ VIDEO_PLAY_LABEL_XPOS, VIDEO_PLAY_LABEL_YPOS, - VIDEO_PLAY_LABEL_XSIZE,VIDEO_PLAY_LABEL_YSIZE }, - { VIDEO_PLAY_SYMBOL_XPOS, VIDEO_PLAY_SYMBOL_YPOS, - VIDEO_PLAY_SYMBOL_XSIZE,VIDEO_PLAY_SYMBOL_YSIZE }}, - - {{ VIDEO_REC_LABEL_XPOS, VIDEO_REC_LABEL_YPOS, - VIDEO_REC_LABEL_XSIZE,VIDEO_REC_LABEL_YSIZE }, - { VIDEO_REC_SYMBOL_XPOS, VIDEO_REC_SYMBOL_YPOS, - VIDEO_REC_SYMBOL_XSIZE,VIDEO_REC_SYMBOL_YSIZE }}, - - {{ VIDEO_PAUSE_LABEL_XPOS, VIDEO_PAUSE_LABEL_YPOS, - VIDEO_PAUSE_LABEL_XSIZE,VIDEO_PAUSE_LABEL_YSIZE }, - { VIDEO_PAUSE_SYMBOL_XPOS, VIDEO_PAUSE_SYMBOL_YPOS, - VIDEO_PAUSE_SYMBOL_XSIZE,VIDEO_PAUSE_SYMBOL_YSIZE }}, - - {{ VIDEO_DATE_LABEL_XPOS, VIDEO_DATE_LABEL_YPOS, - VIDEO_DATE_LABEL_XSIZE,VIDEO_DATE_LABEL_YSIZE }, - { VIDEO_DATE_XPOS, VIDEO_DATE_YPOS, - VIDEO_DATE_XSIZE,VIDEO_DATE_YSIZE }}, - - {{ 0,0, - 0,0 }, - { VIDEO_TIME_XPOS, VIDEO_TIME_YPOS, - VIDEO_TIME_XSIZE,VIDEO_TIME_YSIZE }} - }; - - if (state & VIDEO_STATE_PBEND_OFF) - { - int cx = DOOR_GFX_PAGEX3, cy = DOOR_GFX_PAGEY2; - - BlitBitmap(pix[PIX_DOOR], drawto, - cx + VIDEO_REC_LABEL_XPOS, - cy + VIDEO_REC_LABEL_YPOS, - VIDEO_PBEND_LABEL_XSIZE, - VIDEO_PBEND_LABEL_YSIZE, - VX + VIDEO_REC_LABEL_XPOS, - VY + VIDEO_REC_LABEL_YPOS); - } - - for(i=0;i<10;i++) - { - if (state & (1< STATE_ON / PRESS_OFF */ - cx = DOOR_GFX_PAGEX4; - else - cx = DOOR_GFX_PAGEX3; /* i gerade => STATE_OFF / PRESS_ON */ - - if (video_pos[pos][part_label][0] && value != VIDEO_DISPLAY_SYMBOL_ONLY) - BlitBitmap(pix[PIX_DOOR], drawto, - cx + video_pos[pos][part_label][xpos], - cy + video_pos[pos][part_label][ypos], - video_pos[pos][part_label][xsize], - video_pos[pos][part_label][ysize], - VX + video_pos[pos][part_label][xpos], - VY + video_pos[pos][part_label][ypos]); - if (video_pos[pos][part_symbol][0] && value != VIDEO_DISPLAY_LABEL_ONLY) - BlitBitmap(pix[PIX_DOOR], drawto, - cx + video_pos[pos][part_symbol][xpos], - cy + video_pos[pos][part_symbol][ypos], - video_pos[pos][part_symbol][xsize], - video_pos[pos][part_symbol][ysize], - VX + video_pos[pos][part_symbol][xpos], - VY + video_pos[pos][part_symbol][ypos]); - } - } - - if (state & VIDEO_STATE_FFWD_ON) - { - int cx = DOOR_GFX_PAGEX4, cy = DOOR_GFX_PAGEY2; - - BlitBitmap(pix[PIX_DOOR], drawto, - cx + VIDEO_PLAY_SYMBOL_XPOS, - cy + VIDEO_PLAY_SYMBOL_YPOS, - VIDEO_PLAY_SYMBOL_XSIZE - 2, - VIDEO_PLAY_SYMBOL_YSIZE, - VX + VIDEO_PLAY_SYMBOL_XPOS - 9, - VY + VIDEO_PLAY_SYMBOL_YPOS); - } - - if (state & VIDEO_STATE_PBEND_ON) - { - int cx = DOOR_GFX_PAGEX6, cy = DOOR_GFX_PAGEY1; - - BlitBitmap(pix[PIX_DOOR], drawto, - cx + VIDEO_PBEND_LABEL_XPOS, - cy + VIDEO_PBEND_LABEL_YPOS, - VIDEO_PBEND_LABEL_XSIZE, - VIDEO_PBEND_LABEL_YSIZE, - VX + VIDEO_REC_LABEL_XPOS, - VY + VIDEO_REC_LABEL_YPOS); - } - - if (state & VIDEO_STATE_DATE_ON) - { - int tag = value % 100; - int monat = (value/100) % 100; - int jahr = (value/10000); - - DrawText(VX+VIDEO_DATE_XPOS,VY+VIDEO_DATE_YPOS, - int2str(tag,2),FS_SMALL,FC_SPECIAL1); - DrawText(VX+VIDEO_DATE_XPOS+27,VY+VIDEO_DATE_YPOS, - monatsname[monat],FS_SMALL,FC_SPECIAL1); - DrawText(VX+VIDEO_DATE_XPOS+64,VY+VIDEO_DATE_YPOS, - int2str(jahr,2),FS_SMALL,FC_SPECIAL1); - } - - if (state & VIDEO_STATE_TIME_ON) - { - int min = value / 60; - int sec = value % 60; - - DrawText(VX+VIDEO_TIME_XPOS,VY+VIDEO_TIME_YPOS, - int2str(min,2),FS_SMALL,FC_SPECIAL1); - DrawText(VX+VIDEO_TIME_XPOS+27,VY+VIDEO_TIME_YPOS, - int2str(sec,2),FS_SMALL,FC_SPECIAL1); - } - - if (state & VIDEO_STATE_DATE) - redraw_mask |= REDRAW_VIDEO_1; - if ((state & ~VIDEO_STATE_DATE) & VIDEO_STATE) - redraw_mask |= REDRAW_VIDEO_2; - if (state & VIDEO_PRESS) - redraw_mask |= REDRAW_VIDEO_3; -} - -void DrawCompleteVideoDisplay() -{ - BlitBitmap(pix[PIX_DOOR], drawto, - DOOR_GFX_PAGEX3,DOOR_GFX_PAGEY2, VXSIZE,VYSIZE, VX,VY); - BlitBitmap(pix[PIX_DOOR], drawto, - DOOR_GFX_PAGEX4+VIDEO_CONTROL_XPOS, - DOOR_GFX_PAGEY2+VIDEO_CONTROL_YPOS, - VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE, - VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS); - - DrawVideoDisplay(VIDEO_ALL_OFF,0); - if (tape.date && tape.length) - { - DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date); - DrawVideoDisplay(VIDEO_STATE_TIME_ON,tape.length_seconds); - } - - BlitBitmap(drawto, pix[PIX_DB_DOOR], - VX,VY, VXSIZE,VYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2); -} - - -/* NEW GADGET STUFF -------------------------------------------------------- */ - - -/* values for DrawGadget() */ -#define DG_UNPRESSED 0 -#define DG_PRESSED 1 -#define DG_BUFFERED 0 -#define DG_DIRECT 1 - -static struct GadgetInfo *gadget_list_first_entry = NULL; -static struct GadgetInfo *gadget_list_last_entry = NULL; -static int next_free_gadget_id = 1; -static boolean gadget_id_wrapped = FALSE; - -static struct GadgetInfo *getGadgetInfoFromGadgetID(int id) -{ - struct GadgetInfo *gi = gadget_list_first_entry; - - while (gi && gi->id != id) - gi = gi->next; - - return gi; -} - -static int getNewGadgetID() -{ - int id = next_free_gadget_id++; - - if (next_free_gadget_id <= 0) /* counter overrun */ - { - gadget_id_wrapped = TRUE; /* now we must check each ID */ - next_free_gadget_id = 0; - } - - if (gadget_id_wrapped) - { - next_free_gadget_id++; - while (getGadgetInfoFromGadgetID(next_free_gadget_id) != NULL) - next_free_gadget_id++; - } - - if (next_free_gadget_id <= 0) /* cannot get new gadget id */ - Error(ERR_EXIT, "too much gadgets -- this should not happen"); - - return id; -} - -static struct GadgetInfo *getGadgetInfoFromMousePosition(int mx, int my) -{ - struct GadgetInfo *gi = gadget_list_first_entry; - - while (gi) - { - if (gi->mapped && - mx >= gi->x && mx < gi->x + gi->width && - my >= gi->y && my < gi->y + gi->height) - break; - - gi = gi->next; - } - - return gi; -} - -static void default_callback_info(void *ptr) -{ -#if 0 - if (game_status == LEVELED) - HandleEditorGadgetInfoText(ptr); -#endif - - return; -} - -static void default_callback_action(void *ptr) -{ - return; -} - -static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct) -{ - int state = (pressed ? 1 : 0); - struct GadgetDesign *gd = (gi->checked ? - &gi->alt_design[state] : - &gi->design[state]); - - switch (gi->type) - { - case GD_TYPE_NORMAL_BUTTON: - case GD_TYPE_CHECK_BUTTON: - case GD_TYPE_RADIO_BUTTON: - BlitBitmap(gd->bitmap, drawto, - gd->x, gd->y, gi->width, gi->height, gi->x, gi->y); - if (gi->deco.design.bitmap) - BlitBitmap(gi->deco.design.bitmap, drawto, - gi->deco.design.x, gi->deco.design.y, - gi->deco.width, gi->deco.height, - gi->x + gi->deco.x + (pressed ? gi->deco.xshift : 0), - gi->y + gi->deco.y + (pressed ? gi->deco.yshift : 0)); - break; - - case GD_TYPE_TEXTINPUT_ALPHANUMERIC: - case GD_TYPE_TEXTINPUT_NUMERIC: - { - int i; - char cursor_letter; - char cursor_string[3]; - char text[MAX_GADGET_TEXTSIZE + 1]; - int font_type = gi->text.font_type; - int font_width = getFontWidth(FS_SMALL, font_type); - int border = gi->border.size; - strcpy(text, gi->text.value); - strcat(text, " "); - - /* left part of gadget */ - BlitBitmap(gd->bitmap, drawto, - gd->x, gd->y, border, gi->height, gi->x, gi->y); - - /* middle part of gadget */ - for (i=0; i<=gi->text.size; i++) - BlitBitmap(gd->bitmap, drawto, - gd->x + border, gd->y, font_width, gi->height, - gi->x + border + i * font_width, gi->y); - - /* right part of gadget */ - BlitBitmap(gd->bitmap, drawto, - gd->x + gi->border.width - border, gd->y, - border, gi->height, gi->x + gi->width - border, gi->y); - - /* gadget text value */ - DrawText(gi->x + border, gi->y + border, text, FS_SMALL, font_type); - - cursor_letter = gi->text.value[gi->text.cursor_position]; - cursor_string[0] = '~'; - cursor_string[1] = (cursor_letter != '\0' ? cursor_letter : ' '); - cursor_string[2] = '\0'; - - /* draw cursor, if active */ - if (pressed) - DrawText(gi->x + border + gi->text.cursor_position * font_width, - gi->y + border, cursor_string, FS_SMALL, font_type); - } - break; - - case GD_TYPE_SCROLLBAR_VERTICAL: - { - int i; - int xpos = gi->x; - int ypos = gi->y + gi->scrollbar.position; - int design_full = gi->width; - int design_body = design_full - 2 * gi->border.size; - int size_full = gi->scrollbar.size; - int size_body = size_full - 2 * gi->border.size; - int num_steps = size_body / design_body; - int step_size_remain = size_body - num_steps * design_body; - - /* clear scrollbar area */ - ClearRectangle(backbuffer, gi->x, gi->y, gi->width, gi->height); - - /* upper part of gadget */ - BlitBitmap(gd->bitmap, drawto, - gd->x, gd->y, - gi->width, gi->border.size, - xpos, ypos); - - /* middle part of gadget */ - for (i=0; ibitmap, drawto, - gd->x, gd->y + gi->border.size, - gi->width, design_body, - xpos, ypos + gi->border.size + i * design_body); - - /* remaining middle part of gadget */ - if (step_size_remain > 0) - BlitBitmap(gd->bitmap, drawto, - gd->x, gd->y + gi->border.size, - gi->width, step_size_remain, - xpos, ypos + gi->border.size + num_steps * design_body); - - /* lower part of gadget */ - BlitBitmap(gd->bitmap, drawto, - gd->x, gd->y + design_full - gi->border.size, - gi->width, gi->border.size, - xpos, ypos + size_full - gi->border.size); - } - break; - - case GD_TYPE_SCROLLBAR_HORIZONTAL: - { - int i; - int xpos = gi->x + gi->scrollbar.position; - int ypos = gi->y; - int design_full = gi->height; - int design_body = design_full - 2 * gi->border.size; - int size_full = gi->scrollbar.size; - int size_body = size_full - 2 * gi->border.size; - int num_steps = size_body / design_body; - int step_size_remain = size_body - num_steps * design_body; - - /* clear scrollbar area */ - ClearRectangle(backbuffer, gi->x, gi->y, gi->width, gi->height); - - /* left part of gadget */ - BlitBitmap(gd->bitmap, drawto, - gd->x, gd->y, - gi->border.size, gi->height, - xpos, ypos); - - /* middle part of gadget */ - for (i=0; ibitmap, drawto, - gd->x + gi->border.size, gd->y, - design_body, gi->height, - xpos + gi->border.size + i * design_body, ypos); - - /* remaining middle part of gadget */ - if (step_size_remain > 0) - BlitBitmap(gd->bitmap, drawto, - gd->x + gi->border.size, gd->y, - step_size_remain, gi->height, - xpos + gi->border.size + num_steps * design_body, ypos); - - /* right part of gadget */ - BlitBitmap(gd->bitmap, drawto, - gd->x + design_full - gi->border.size, gd->y, - gi->border.size, gi->height, - xpos + size_full - gi->border.size, ypos); - } - break; - - default: - return; - } - - if (direct) - BlitBitmap(drawto, window, - gi->x, gi->y, gi->width, gi->height, gi->x, gi->y); - else - redraw_mask |= (gi->x < SX + SXSIZE ? REDRAW_FIELD : - gi->y < DY + DYSIZE ? REDRAW_DOOR_1 : - gi->y > VY ? REDRAW_DOOR_2 : REDRAW_DOOR_3); -} - -static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap) -{ - int tag = first_tag; - - while (tag != GDI_END) - { - switch(tag) - { - case GDI_CUSTOM_ID: - gi->custom_id = va_arg(ap, int); - break; - - case GDI_CUSTOM_TYPE_ID: - gi->custom_type_id = va_arg(ap, int); - break; - - case GDI_INFO_TEXT: - { - int max_textsize = MAX_INFO_TEXTSIZE - 1; - - strncpy(gi->info_text, va_arg(ap, char *), max_textsize); - gi->info_text[max_textsize] = '\0'; - } - break; - - case GDI_X: - gi->x = va_arg(ap, int); - break; - - case GDI_Y: - gi->y = va_arg(ap, int); - break; - - case GDI_WIDTH: - gi->width = va_arg(ap, int); - break; - - case GDI_HEIGHT: - gi->height = va_arg(ap, int); - break; - - case GDI_TYPE: - gi->type = va_arg(ap, unsigned long); - break; - - case GDI_STATE: - gi->state = va_arg(ap, unsigned long); - break; - - case GDI_CHECKED: - gi->checked = va_arg(ap, boolean); - break; - - case GDI_RADIO_NR: - gi->radio_nr = va_arg(ap, unsigned long); - break; - - case GDI_NUMBER_VALUE: - gi->text.number_value = va_arg(ap, long); - sprintf(gi->text.value, "%d", gi->text.number_value); - gi->text.cursor_position = strlen(gi->text.value); - break; - - case GDI_NUMBER_MIN: - gi->text.number_min = va_arg(ap, long); - if (gi->text.number_value < gi->text.number_min) - { - gi->text.number_value = gi->text.number_min; - sprintf(gi->text.value, "%d", gi->text.number_value); - } - break; - - case GDI_NUMBER_MAX: - gi->text.number_max = va_arg(ap, long); - if (gi->text.number_value > gi->text.number_max) - { - gi->text.number_value = gi->text.number_max; - sprintf(gi->text.value, "%d", gi->text.number_value); - } - break; - - case GDI_TEXT_VALUE: - { - int max_textsize = MAX_GADGET_TEXTSIZE; - - if (gi->text.size) - max_textsize = MIN(gi->text.size, MAX_GADGET_TEXTSIZE - 1); - - strncpy(gi->text.value, va_arg(ap, char *), max_textsize); - gi->text.value[max_textsize] = '\0'; - gi->text.cursor_position = strlen(gi->text.value); - } - break; - - case GDI_TEXT_SIZE: - { - int tag_value = va_arg(ap, int); - int max_textsize = MIN(tag_value, MAX_GADGET_TEXTSIZE - 1); - - gi->text.size = max_textsize; - gi->text.value[max_textsize] = '\0'; - } - break; - - case GDI_TEXT_FONT: - gi->text.font_type = va_arg(ap, int); - break; - - case GDI_DESIGN_UNPRESSED: - gi->design[GD_BUTTON_UNPRESSED].bitmap = va_arg(ap, Bitmap); - gi->design[GD_BUTTON_UNPRESSED].x = va_arg(ap, int); - gi->design[GD_BUTTON_UNPRESSED].y = va_arg(ap, int); - break; - - case GDI_DESIGN_PRESSED: - gi->design[GD_BUTTON_PRESSED].bitmap = va_arg(ap, Bitmap); - gi->design[GD_BUTTON_PRESSED].x = va_arg(ap, int); - gi->design[GD_BUTTON_PRESSED].y = va_arg(ap, int); - break; - - case GDI_ALT_DESIGN_UNPRESSED: - gi->alt_design[GD_BUTTON_UNPRESSED].bitmap= va_arg(ap, Bitmap); - gi->alt_design[GD_BUTTON_UNPRESSED].x = va_arg(ap, int); - gi->alt_design[GD_BUTTON_UNPRESSED].y = va_arg(ap, int); - break; - - case GDI_ALT_DESIGN_PRESSED: - gi->alt_design[GD_BUTTON_PRESSED].bitmap = va_arg(ap, Bitmap); - gi->alt_design[GD_BUTTON_PRESSED].x = va_arg(ap, int); - gi->alt_design[GD_BUTTON_PRESSED].y = va_arg(ap, int); - break; - - case GDI_BORDER_SIZE: - gi->border.size = va_arg(ap, int); - break; - - case GDI_TEXTINPUT_DESIGN_WIDTH: - gi->border.width = va_arg(ap, int); - break; - - case GDI_DECORATION_DESIGN: - gi->deco.design.bitmap = va_arg(ap, Bitmap); - gi->deco.design.x = va_arg(ap, int); - gi->deco.design.y = va_arg(ap, int); - break; - - case GDI_DECORATION_POSITION: - gi->deco.x = va_arg(ap, int); - gi->deco.y = va_arg(ap, int); - break; - - case GDI_DECORATION_SIZE: - gi->deco.width = va_arg(ap, int); - gi->deco.height = va_arg(ap, int); - break; - - case GDI_DECORATION_SHIFTING: - gi->deco.xshift = va_arg(ap, int); - gi->deco.yshift = va_arg(ap, int); - break; - - case GDI_EVENT_MASK: - gi->event_mask = va_arg(ap, unsigned long); - break; - - case GDI_AREA_SIZE: - gi->drawing.area_xsize = va_arg(ap, int); - gi->drawing.area_ysize = va_arg(ap, int); - - /* determine dependent values for drawing area gadget, if needed */ - if (gi->width == 0 && gi->height == 0 && - gi->drawing.item_xsize !=0 && gi->drawing.item_ysize !=0) - { - gi->width = gi->drawing.area_xsize * gi->drawing.item_xsize; - gi->height = gi->drawing.area_ysize * gi->drawing.item_ysize; - } - else if (gi->drawing.item_xsize == 0 && gi->drawing.item_ysize == 0 && - gi->width != 0 && gi->height != 0) - { - gi->drawing.item_xsize = gi->width / gi->drawing.area_xsize; - gi->drawing.item_ysize = gi->height / gi->drawing.area_ysize; - } - break; - - case GDI_ITEM_SIZE: - gi->drawing.item_xsize = va_arg(ap, int); - gi->drawing.item_ysize = va_arg(ap, int); - - /* determine dependent values for drawing area gadget, if needed */ - if (gi->width == 0 && gi->height == 0 && - gi->drawing.area_xsize !=0 && gi->drawing.area_ysize !=0) - { - gi->width = gi->drawing.area_xsize * gi->drawing.item_xsize; - gi->height = gi->drawing.area_ysize * gi->drawing.item_ysize; - } - else if (gi->drawing.area_xsize == 0 && gi->drawing.area_ysize == 0 && - gi->width != 0 && gi->height != 0) - { - gi->drawing.area_xsize = gi->width / gi->drawing.item_xsize; - gi->drawing.area_ysize = gi->height / gi->drawing.item_ysize; - } - break; - - case GDI_SCROLLBAR_ITEMS_MAX: - gi->scrollbar.items_max = va_arg(ap, int); - break; - - case GDI_SCROLLBAR_ITEMS_VISIBLE: - gi->scrollbar.items_visible = va_arg(ap, int); - break; - - case GDI_SCROLLBAR_ITEM_POSITION: - gi->scrollbar.item_position = va_arg(ap, int); - break; - - case GDI_CALLBACK_INFO: - gi->callback_info = va_arg(ap, gadget_function); - break; - - case GDI_CALLBACK_ACTION: - gi->callback_action = va_arg(ap, gadget_function); - break; - - default: - Error(ERR_EXIT, "HandleGadgetTags(): unknown tag %d", tag); - } - - tag = va_arg(ap, int); /* read next tag */ - } - - /* check if gadget complete */ - if (gi->type != GD_TYPE_DRAWING_AREA && - (!gi->design[GD_BUTTON_UNPRESSED].bitmap || - !gi->design[GD_BUTTON_PRESSED].bitmap)) - Error(ERR_EXIT, "gadget incomplete (missing Bitmap)"); - - /* adjust gadget values in relation to other gadget values */ - - if (gi->type & GD_TYPE_TEXTINPUT) - { - int font_width = getFontWidth(FS_SMALL, gi->text.font_type); - int font_height = getFontHeight(FS_SMALL, gi->text.font_type); - - gi->width = 2 * gi->border.size + (gi->text.size + 1) * font_width; - gi->height = 2 * gi->border.size + font_height; - } - - if (gi->type & GD_TYPE_TEXTINPUT_NUMERIC) - { - struct GadgetTextInput *text = &gi->text; - int value = text->number_value; - - text->number_value = (value < text->number_min ? text->number_min : - value > text->number_max ? text->number_max : - value); - - sprintf(text->value, "%d", text->number_value); - } - - if (gi->type & GD_TYPE_SCROLLBAR) - { - struct GadgetScrollbar *gs = &gi->scrollbar; - - if (gi->width == 0 || gi->height == 0 || - gs->items_max == 0 || gs->items_visible == 0) - Error(ERR_EXIT, "scrollbar gadget incomplete (missing tags)"); - - /* calculate internal scrollbar values */ - gs->size_max = (gi->type == GD_TYPE_SCROLLBAR_VERTICAL ? - gi->height : gi->width); - gs->size = gs->size_max * gs->items_visible / gs->items_max; - gs->position = gs->size_max * gs->item_position / gs->items_max; - gs->position_max = gs->size_max - gs->size; - gs->correction = gs->size_max / gs->items_max / 2; - - /* finetuning for maximal right/bottom position */ - if (gs->item_position == gs->items_max - gs->items_visible) - gs->position = gs->position_max; - } -} - -void ModifyGadget(struct GadgetInfo *gi, int first_tag, ...) -{ - va_list ap; - - va_start(ap, first_tag); - HandleGadgetTags(gi, first_tag, ap); - va_end(ap); - - RedrawGadget(gi); -} - -void RedrawGadget(struct GadgetInfo *gi) -{ - if (gi->mapped) - DrawGadget(gi, gi->state, DG_DIRECT); -} - -struct GadgetInfo *CreateGadget(int first_tag, ...) -{ - struct GadgetInfo *new_gadget = checked_malloc(sizeof(struct GadgetInfo)); - va_list ap; - - /* always start with reliable default values */ - memset(new_gadget, 0, sizeof(struct GadgetInfo)); /* zero all fields */ - new_gadget->id = getNewGadgetID(); - new_gadget->callback_info = default_callback_info; - new_gadget->callback_action = default_callback_action; - - va_start(ap, first_tag); - HandleGadgetTags(new_gadget, first_tag, ap); - va_end(ap); - - /* insert new gadget into global gadget list */ - if (gadget_list_last_entry) - { - gadget_list_last_entry->next = new_gadget; - gadget_list_last_entry = gadget_list_last_entry->next; - } - else - gadget_list_first_entry = gadget_list_last_entry = new_gadget; - - return new_gadget; -} - -void FreeGadget(struct GadgetInfo *gi) -{ - struct GadgetInfo *gi_previous = gadget_list_first_entry; - - while (gi_previous && gi_previous->next != gi) - gi_previous = gi_previous->next; - - if (gi == gadget_list_first_entry) - gadget_list_first_entry = gi->next; - - if (gi == gadget_list_last_entry) - gadget_list_last_entry = gi_previous; - - gi_previous->next = gi->next; - free(gi); -} - -static void CheckRangeOfNumericInputGadget(struct GadgetInfo *gi) -{ - if (gi->type != GD_TYPE_TEXTINPUT_NUMERIC) - return; - - gi->text.number_value = atoi(gi->text.value); - - if (gi->text.number_value < gi->text.number_min) - gi->text.number_value = gi->text.number_min; - if (gi->text.number_value > gi->text.number_max) - gi->text.number_value = gi->text.number_max; - - sprintf(gi->text.value, "%d", gi->text.number_value); - - if (gi->text.cursor_position < 0) - gi->text.cursor_position = 0; - else if (gi->text.cursor_position > strlen(gi->text.value)) - gi->text.cursor_position = strlen(gi->text.value); -} - -/* global pointer to gadget actually in use (when mouse button pressed) */ -static struct GadgetInfo *last_gi = NULL; - -static void MapGadgetExt(struct GadgetInfo *gi, boolean redraw) -{ - if (gi == NULL || gi->mapped) - return; - - gi->mapped = TRUE; - - if (redraw) - DrawGadget(gi, DG_UNPRESSED, DG_BUFFERED); -} - -void MapGadget(struct GadgetInfo *gi) -{ - MapGadgetExt(gi, TRUE); -} - -void UnmapGadget(struct GadgetInfo *gi) -{ - if (gi == NULL || !gi->mapped) - return; - - gi->mapped = FALSE; - - if (gi == last_gi) - last_gi = NULL; -} - -#define MAX_NUM_GADGETS 1024 -#define MULTIMAP_UNMAP (1 << 0) -#define MULTIMAP_REMAP (1 << 1) -#define MULTIMAP_REDRAW (1 << 2) -#define MULTIMAP_PLAYFIELD (1 << 3) -#define MULTIMAP_DOOR_1 (1 << 4) -#define MULTIMAP_DOOR_2 (1 << 5) -#define MULTIMAP_ALL (MULTIMAP_PLAYFIELD | \ - MULTIMAP_DOOR_1 | \ - MULTIMAP_DOOR_2) - -static void MultiMapGadgets(int mode) -{ - struct GadgetInfo *gi = gadget_list_first_entry; - static boolean map_state[MAX_NUM_GADGETS]; - int map_count = 0; - - while (gi) - { - if ((mode & MULTIMAP_PLAYFIELD && gi->x < SX + SXSIZE) || - (mode & MULTIMAP_DOOR_1 && gi->x >= DX && gi->y < DY + DYSIZE) || - (mode & MULTIMAP_DOOR_2 && gi->x >= DX && gi->y > DY + DYSIZE) || - (mode & MULTIMAP_ALL) == MULTIMAP_ALL) - { - if (mode & MULTIMAP_UNMAP) - { - map_state[map_count++ % MAX_NUM_GADGETS] = gi->mapped; - UnmapGadget(gi); - } - else - { - if (map_state[map_count++ % MAX_NUM_GADGETS]) - MapGadgetExt(gi, (mode & MULTIMAP_REDRAW)); - } - } - - gi = gi->next; - } -} - -void UnmapAllGadgets() -{ - MultiMapGadgets(MULTIMAP_ALL | MULTIMAP_UNMAP); -} - -void RemapAllGadgets() -{ - MultiMapGadgets(MULTIMAP_ALL | MULTIMAP_REMAP); -} - -boolean anyTextGadgetActive() -{ - return (last_gi && last_gi->type & GD_TYPE_TEXTINPUT && last_gi->mapped); -} - -void ClickOnGadget(struct GadgetInfo *gi, int button) -{ - /* simulate releasing mouse button over last gadget, if still pressed */ - if (button_status) - HandleGadgets(-1, -1, 0); - - /* simulate pressing mouse button over specified gadget */ - HandleGadgets(gi->x, gi->y, button); - - /* simulate releasing mouse button over specified gadget */ - HandleGadgets(gi->x, gi->y, 0); -} - -void HandleGadgets(int mx, int my, int button) -{ - static struct GadgetInfo *last_info_gi = NULL; - static unsigned long pressed_delay = 0; - static int last_button = 0; - static int last_mx = 0, last_my = 0; - int scrollbar_mouse_pos = 0; - struct GadgetInfo *new_gi, *gi; - boolean press_event; - boolean release_event; - boolean mouse_moving; - boolean gadget_pressed; - boolean gadget_pressed_repeated; - boolean gadget_moving; - boolean gadget_moving_inside; - boolean gadget_moving_off_borders; - boolean gadget_released; - boolean gadget_released_inside; - boolean gadget_released_off_borders; - boolean changed_position = FALSE; - - /* check if there are any gadgets defined */ - if (gadget_list_first_entry == NULL) - return; - - /* check which gadget is under the mouse pointer */ - new_gi = getGadgetInfoFromMousePosition(mx, my); - - /* check if button state has changed since last invocation */ - press_event = (button != 0 && last_button == 0); - release_event = (button == 0 && last_button != 0); - last_button = button; - - /* check if mouse has been moved since last invocation */ - mouse_moving = ((mx != last_mx || my != last_my) && motion_status); - last_mx = mx; - last_my = my; - - /* special treatment for text and number input gadgets */ - if (anyTextGadgetActive() && button != 0 && !motion_status) - { - struct GadgetInfo *gi = last_gi; - - if (new_gi == last_gi) - { - /* if mouse button pressed inside activated text gadget, set cursor */ - gi->text.cursor_position = - (mx - gi->x - gi->border.size) / - getFontWidth(FS_SMALL, gi->text.font_type); - - if (gi->text.cursor_position < 0) - gi->text.cursor_position = 0; - else if (gi->text.cursor_position > strlen(gi->text.value)) - gi->text.cursor_position = strlen(gi->text.value); - - DrawGadget(gi, DG_PRESSED, DG_DIRECT); - } - else - { - /* if mouse button pressed outside text input gadget, deactivate it */ - CheckRangeOfNumericInputGadget(gi); - DrawGadget(gi, DG_UNPRESSED, DG_DIRECT); - - gi->event.type = GD_EVENT_TEXT_LEAVING; - - if (gi->event_mask & GD_EVENT_TEXT_LEAVING) - gi->callback_action(gi); - - last_gi = NULL; - } - } - - gadget_pressed = - (button != 0 && last_gi == NULL && new_gi != NULL && press_event); - gadget_pressed_repeated = - (button != 0 && last_gi != NULL && new_gi == last_gi); - - gadget_released = (release_event && last_gi != NULL); - gadget_released_inside = (gadget_released && new_gi == last_gi); - gadget_released_off_borders = (gadget_released && new_gi != last_gi); - - gadget_moving = (button != 0 && last_gi != NULL && mouse_moving); - gadget_moving_inside = (gadget_moving && new_gi == last_gi); - gadget_moving_off_borders = (gadget_moving && new_gi != last_gi); - - /* if new gadget pressed, store this gadget */ - if (gadget_pressed) - last_gi = new_gi; - - /* 'gi' is actually handled gadget */ - gi = last_gi; - - /* if gadget is scrollbar, choose mouse position value */ - if (gi && gi->type & GD_TYPE_SCROLLBAR) - scrollbar_mouse_pos = - (gi->type == GD_TYPE_SCROLLBAR_HORIZONTAL ? mx - gi->x : my - gi->y); - - /* if mouse button released, no gadget needs to be handled anymore */ - if (button == 0 && last_gi && !(last_gi->type & GD_TYPE_TEXTINPUT)) - last_gi = NULL; - - /* modify event position values even if no gadget is pressed */ - if (button == 0 && !release_event) - gi = new_gi; - - if (gi) - { - int last_x = gi->event.x; - int last_y = gi->event.y; - - gi->event.x = mx - gi->x; - gi->event.y = my - gi->y; - - if (gi->type == GD_TYPE_DRAWING_AREA) - { - gi->event.x /= gi->drawing.item_xsize; - gi->event.y /= gi->drawing.item_ysize; - - if (last_x != gi->event.x || last_y != gi->event.y) - changed_position = TRUE; - } - } - - /* handle gadget popup info text */ - if (last_info_gi != new_gi || - (new_gi && new_gi->type == GD_TYPE_DRAWING_AREA && changed_position)) - { - last_info_gi = new_gi; - - if (new_gi != NULL && (button == 0 || new_gi == last_gi)) - { - new_gi->event.type = 0; - new_gi->callback_info(new_gi); - } - else - default_callback_info(NULL); - } - - if (gadget_pressed) - { - if (gi->type == GD_TYPE_CHECK_BUTTON) - { - gi->checked = !gi->checked; - } - else if (gi->type == GD_TYPE_RADIO_BUTTON) - { - struct GadgetInfo *rgi = gadget_list_first_entry; - - while (rgi) - { - if (rgi->mapped && - rgi->type == GD_TYPE_RADIO_BUTTON && - rgi->radio_nr == gi->radio_nr && - rgi != gi) - { - rgi->checked = FALSE; - DrawGadget(rgi, DG_UNPRESSED, DG_DIRECT); - } - - rgi = rgi->next; - } - - gi->checked = TRUE; - } - else if (gi->type & GD_TYPE_SCROLLBAR) - { - int mpos, gpos; - - if (gi->type == GD_TYPE_SCROLLBAR_HORIZONTAL) - { - mpos = mx; - gpos = gi->x; - } - else - { - mpos = my; - gpos = gi->y; - } - - if (mpos >= gpos + gi->scrollbar.position && - mpos < gpos + gi->scrollbar.position + gi->scrollbar.size) - { - /* drag scrollbar */ - gi->scrollbar.drag_position = - scrollbar_mouse_pos - gi->scrollbar.position; - } - else - { - /* click scrollbar one scrollbar length up/left or down/right */ - - struct GadgetScrollbar *gs = &gi->scrollbar; - int old_item_position = gs->item_position; - - changed_position = FALSE; - - gs->item_position += - gs->items_visible * (mpos < gpos + gi->scrollbar.position ? -1 : +1); - - if (gs->item_position < 0) - gs->item_position = 0; - if (gs->item_position > gs->items_max - gs->items_visible) - gs->item_position = gs->items_max - gs->items_visible; - - if (old_item_position != gs->item_position) - { - gi->event.item_position = gs->item_position; - changed_position = TRUE; - } - - ModifyGadget(gi, GDI_SCROLLBAR_ITEM_POSITION, gs->item_position, - GDI_END); - - gi->state = GD_BUTTON_UNPRESSED; - gi->event.type = GD_EVENT_MOVING; - gi->event.off_borders = FALSE; - - if (gi->event_mask & GD_EVENT_MOVING && changed_position) - gi->callback_action(gi); - - /* don't handle this scrollbar anymore while mouse button pressed */ - last_gi = NULL; - - return; - } - } - - DrawGadget(gi, DG_PRESSED, DG_DIRECT); - - gi->state = GD_BUTTON_PRESSED; - gi->event.type = GD_EVENT_PRESSED; - gi->event.button = button; - gi->event.off_borders = FALSE; - - /* initialize delay counter */ - DelayReached(&pressed_delay, 0); - - if (gi->event_mask & GD_EVENT_PRESSED) - gi->callback_action(gi); - } - - if (gadget_pressed_repeated) - { - gi->event.type = GD_EVENT_PRESSED; - - if (gi->event_mask & GD_EVENT_REPEATED && - DelayReached(&pressed_delay, GADGET_FRAME_DELAY)) - gi->callback_action(gi); - } - - if (gadget_moving) - { - if (gi->type & GD_TYPE_BUTTON) - { - if (gadget_moving_inside && gi->state == GD_BUTTON_UNPRESSED) - DrawGadget(gi, DG_PRESSED, DG_DIRECT); - else if (gadget_moving_off_borders && gi->state == GD_BUTTON_PRESSED) - DrawGadget(gi, DG_UNPRESSED, DG_DIRECT); - } - - if (gi->type & GD_TYPE_SCROLLBAR) - { - struct GadgetScrollbar *gs = &gi->scrollbar; - int old_item_position = gs->item_position; - - gs->position = scrollbar_mouse_pos - gs->drag_position; - - if (gs->position < 0) - gs->position = 0; - if (gs->position > gs->position_max) - gs->position = gs->position_max; - - gs->item_position = - gs->items_max * (gs->position + gs->correction) / gs->size_max; - - if (gs->item_position < 0) - gs->item_position = 0; - if (gs->item_position > gs->items_max - 1) - gs->item_position = gs->items_max - 1; - - if (old_item_position != gs->item_position) - { - gi->event.item_position = gs->item_position; - changed_position = TRUE; - } - - DrawGadget(gi, DG_PRESSED, DG_DIRECT); - } - - gi->state = (gadget_moving_inside || gi->type & GD_TYPE_SCROLLBAR ? - GD_BUTTON_PRESSED : GD_BUTTON_UNPRESSED); - gi->event.type = GD_EVENT_MOVING; - gi->event.off_borders = gadget_moving_off_borders; - - if (gi->event_mask & GD_EVENT_MOVING && changed_position && - (gadget_moving_inside || gi->event_mask & GD_EVENT_OFF_BORDERS)) - gi->callback_action(gi); - } - - if (gadget_released_inside) - { - if (!(gi->type & GD_TYPE_TEXTINPUT)) - DrawGadget(gi, DG_UNPRESSED, DG_DIRECT); - - gi->state = GD_BUTTON_UNPRESSED; - gi->event.type = GD_EVENT_RELEASED; - - if (gi->event_mask & GD_EVENT_RELEASED) - gi->callback_action(gi); - } - - if (gadget_released_off_borders) - { - if (gi->type & GD_TYPE_SCROLLBAR) - DrawGadget(gi, DG_UNPRESSED, DG_DIRECT); - - gi->event.type = GD_EVENT_RELEASED; - - if (gi->event_mask & GD_EVENT_RELEASED && - gi->event_mask & GD_EVENT_OFF_BORDERS) - gi->callback_action(gi); - } -} - -void HandleGadgetsKeyInput(Key key) -{ - struct GadgetInfo *gi = last_gi; - char text[MAX_GADGET_TEXTSIZE]; - int text_length; - int cursor_pos; - char letter; - boolean legal_letter; - - if (gi == NULL || !(gi->type & GD_TYPE_TEXTINPUT) || !gi->mapped) - return; - - text_length = strlen(gi->text.value); - cursor_pos = gi->text.cursor_position; - letter = getCharFromKey(key); - legal_letter = (gi->type == GD_TYPE_TEXTINPUT_NUMERIC ? - letter >= '0' && letter <= '9' : - letter != 0); - - if (legal_letter && text_length < gi->text.size) - { - strcpy(text, gi->text.value); - strcpy(&gi->text.value[cursor_pos + 1], &text[cursor_pos]); - gi->text.value[cursor_pos] = letter; - gi->text.cursor_position++; - DrawGadget(gi, DG_PRESSED, DG_DIRECT); - } - else if (key == KSYM_Left && cursor_pos > 0) - { - gi->text.cursor_position--; - DrawGadget(gi, DG_PRESSED, DG_DIRECT); - } - else if (key == KSYM_Right && cursor_pos < text_length) - { - gi->text.cursor_position++; - DrawGadget(gi, DG_PRESSED, DG_DIRECT); - } - else if (key == KSYM_BackSpace && cursor_pos > 0) - { - strcpy(text, gi->text.value); - strcpy(&gi->text.value[cursor_pos - 1], &text[cursor_pos]); - gi->text.cursor_position--; - DrawGadget(gi, DG_PRESSED, DG_DIRECT); - } - else if (key == KSYM_Delete && cursor_pos < text_length) - { - strcpy(text, gi->text.value); - strcpy(&gi->text.value[cursor_pos], &text[cursor_pos + 1]); - DrawGadget(gi, DG_PRESSED, DG_DIRECT); - } - else if (key == KSYM_Return) - { - CheckRangeOfNumericInputGadget(gi); - DrawGadget(gi, DG_UNPRESSED, DG_DIRECT); - - gi->event.type = GD_EVENT_TEXT_RETURN; - - if (gi->event_mask & GD_EVENT_TEXT_RETURN) - gi->callback_action(gi); - - last_gi = NULL; - } -} diff --git a/src/libgame/buttons.h b/src/libgame/buttons.h deleted file mode 100644 index 38fbe634..00000000 --- a/src/libgame/buttons.h +++ /dev/null @@ -1,265 +0,0 @@ -/*********************************************************** -* Rocks'n'Diamonds -- McDuffin Strikes Back! * -*----------------------------------------------------------* -* (c) 1995-98 Artsoft Entertainment * -* Holger Schemel * -* Oststrasse 11a * -* 33604 Bielefeld * -* phone: ++49 +521 290471 * -* email: aeglos@valinor.owl.de * -*----------------------------------------------------------* -* buttons.h * -***********************************************************/ - -#ifndef BUTTONS_H -#define BUTTONS_H - -#include "libgame.h" - -/* the following definitions are also used by tools.c */ - -/* some positions in the video tape control window */ -#define VIDEO_DISPLAY1_XPOS 5 -#define VIDEO_DISPLAY1_YPOS 5 -#define VIDEO_DISPLAY2_XPOS 5 -#define VIDEO_DISPLAY2_YPOS 41 -#define VIDEO_DISPLAY_XSIZE 90 -#define VIDEO_DISPLAY_YSIZE 31 -#define VIDEO_BUTTON_XSIZE 18 -#define VIDEO_BUTTON_YSIZE 18 -#define VIDEO_CONTROL_XPOS 5 -#define VIDEO_CONTROL_YPOS 77 -#define VIDEO_CONTROL_XSIZE VIDEO_DISPLAY_XSIZE -#define VIDEO_CONTROL_YSIZE VIDEO_BUTTON_YSIZE - -/* values for video tape control */ -#define VIDEO_STATE_PLAY_OFF (1L << 0) -#define VIDEO_STATE_PLAY_ON (1L << 1) -#define VIDEO_STATE_PLAY (VIDEO_STATE_PLAY_OFF | VIDEO_STATE_PLAY_ON) -#define VIDEO_STATE_REC_OFF (1L << 2) -#define VIDEO_STATE_REC_ON (1L << 3) -#define VIDEO_STATE_REC (VIDEO_STATE_REC_OFF | VIDEO_STATE_REC_ON) -#define VIDEO_STATE_PAUSE_OFF (1L << 4) -#define VIDEO_STATE_PAUSE_ON (1L << 5) -#define VIDEO_STATE_PAUSE (VIDEO_STATE_PAUSE_OFF | VIDEO_STATE_PAUSE_ON) -#define VIDEO_STATE_DATE_OFF (1L << 6) -#define VIDEO_STATE_DATE_ON (1L << 7) -#define VIDEO_STATE_DATE (VIDEO_STATE_DATE_OFF | VIDEO_STATE_DATE_ON) -#define VIDEO_STATE_TIME_OFF (1L << 8) -#define VIDEO_STATE_TIME_ON (1L << 9) -#define VIDEO_STATE_TIME (VIDEO_STATE_TIME_OFF | VIDEO_STATE_TIME_ON) -#define VIDEO_PRESS_PLAY_ON (1L << 10) -#define VIDEO_PRESS_PLAY_OFF (1L << 11) -#define VIDEO_PRESS_PLAY (VIDEO_PRESS_PLAY_OFF | VIDEO_PRESS_PLAY_ON) -#define VIDEO_PRESS_REC_ON (1L << 12) -#define VIDEO_PRESS_REC_OFF (1L << 13) -#define VIDEO_PRESS_REC (VIDEO_PRESS_REC_OFF | VIDEO_PRESS_REC_ON) -#define VIDEO_PRESS_PAUSE_ON (1L << 14) -#define VIDEO_PRESS_PAUSE_OFF (1L << 15) -#define VIDEO_PRESS_PAUSE (VIDEO_PRESS_PAUSE_OFF | VIDEO_PRESS_PAUSE_ON) -#define VIDEO_PRESS_STOP_ON (1L << 16) -#define VIDEO_PRESS_STOP_OFF (1L << 17) -#define VIDEO_PRESS_STOP (VIDEO_PRESS_STOP_OFF | VIDEO_PRESS_STOP_ON) -#define VIDEO_PRESS_EJECT_ON (1L << 18) -#define VIDEO_PRESS_EJECT_OFF (1L << 19) -#define VIDEO_PRESS_EJECT (VIDEO_PRESS_EJECT_OFF | VIDEO_PRESS_EJECT_ON) - -/* special */ -#define VIDEO_STATE_FFWD_OFF ((1L << 20) | VIDEO_STATE_PAUSE_OFF) -#define VIDEO_STATE_FFWD_ON (1L << 21) -#define VIDEO_STATE_FFWD (VIDEO_STATE_FFWD_OFF | VIDEO_STATE_FFWD_ON) -#define VIDEO_STATE_PBEND_OFF (1L << 22) -#define VIDEO_STATE_PBEND_ON (1L << 23) -#define VIDEO_STATE_PBEND (VIDEO_STATE_PBEND_OFF | VIDEO_STATE_PBEND_ON) - -/* tags to draw video display labels or symbols only */ -#define VIDEO_DISPLAY_DEFAULT 0 -#define VIDEO_DISPLAY_LABEL_ONLY 1 -#define VIDEO_DISPLAY_SYMBOL_ONLY 2 - -void DrawVideoDisplay(unsigned long, unsigned long); -void DrawCompleteVideoDisplay(void); - - -/* NEW GADGET STUFF -------------------------------------------------------- */ - -/* gadget types */ -#define GD_TYPE_NORMAL_BUTTON (1 << 0) -#define GD_TYPE_CHECK_BUTTON (1 << 1) -#define GD_TYPE_RADIO_BUTTON (1 << 2) -#define GD_TYPE_DRAWING_AREA (1 << 3) -#define GD_TYPE_TEXTINPUT_ALPHANUMERIC (1 << 4) -#define GD_TYPE_TEXTINPUT_NUMERIC (1 << 5) -#define GD_TYPE_SCROLLBAR_VERTICAL (1 << 6) -#define GD_TYPE_SCROLLBAR_HORIZONTAL (1 << 7) - -#define GD_TYPE_BUTTON (GD_TYPE_NORMAL_BUTTON | \ - GD_TYPE_CHECK_BUTTON | \ - GD_TYPE_RADIO_BUTTON) -#define GD_TYPE_SCROLLBAR (GD_TYPE_SCROLLBAR_VERTICAL | \ - GD_TYPE_SCROLLBAR_HORIZONTAL) -#define GD_TYPE_TEXTINPUT (GD_TYPE_TEXTINPUT_ALPHANUMERIC | \ - GD_TYPE_TEXTINPUT_NUMERIC) - -/* gadget events */ -#define GD_EVENT_PRESSED (1 << 0) -#define GD_EVENT_RELEASED (1 << 1) -#define GD_EVENT_MOVING (1 << 2) -#define GD_EVENT_REPEATED (1 << 3) -#define GD_EVENT_OFF_BORDERS (1 << 4) -#define GD_EVENT_TEXT_RETURN (1 << 5) -#define GD_EVENT_TEXT_LEAVING (1 << 6) - -/* gadget button states */ -#define GD_BUTTON_UNPRESSED 0 -#define GD_BUTTON_PRESSED 1 - -/* gadget structure constants */ -#define MAX_GADGET_TEXTSIZE 1024 -#define MAX_INFO_TEXTSIZE 1024 - -/* gadget creation tags */ -#define GDI_END 0 -#define GDI_CUSTOM_ID 1 -#define GDI_CUSTOM_TYPE_ID 2 -#define GDI_X 3 -#define GDI_Y 4 -#define GDI_WIDTH 5 -#define GDI_HEIGHT 6 -#define GDI_TYPE 7 -#define GDI_STATE 8 -#define GDI_CHECKED 9 -#define GDI_RADIO_NR 10 -#define GDI_NUMBER_VALUE 11 -#define GDI_NUMBER_MIN 12 -#define GDI_NUMBER_MAX 13 -#define GDI_TEXT_VALUE 14 -#define GDI_TEXT_SIZE 15 -#define GDI_TEXT_FONT 16 -#define GDI_DESIGN_UNPRESSED 17 -#define GDI_DESIGN_PRESSED 18 -#define GDI_ALT_DESIGN_UNPRESSED 19 -#define GDI_ALT_DESIGN_PRESSED 20 -#define GDI_BORDER_SIZE 21 -#define GDI_TEXTINPUT_DESIGN_WIDTH 22 -#define GDI_DECORATION_DESIGN 23 -#define GDI_DECORATION_POSITION 24 -#define GDI_DECORATION_SIZE 25 -#define GDI_DECORATION_SHIFTING 26 -#define GDI_EVENT_MASK 27 -#define GDI_EVENT 28 -#define GDI_CALLBACK_INFO 29 -#define GDI_CALLBACK_ACTION 30 -#define GDI_AREA_SIZE 31 -#define GDI_ITEM_SIZE 32 -#define GDI_SCROLLBAR_ITEMS_MAX 33 -#define GDI_SCROLLBAR_ITEMS_VISIBLE 34 -#define GDI_SCROLLBAR_ITEM_POSITION 35 -#define GDI_INFO_TEXT 36 - -typedef void (*gadget_function)(void *); - -struct GadgetBorder -{ - int size; /* size of gadget border */ - int width; /* for text input gadgets */ -}; - -struct GadgetDesign -{ - Bitmap bitmap; /* Bitmap with gadget surface */ - int x, y; /* position of rectangle in Bitmap */ -}; - -struct GadgetDecoration -{ - struct GadgetDesign design; /* decoration design structure */ - int x, y; /* position of deco on the gadget */ - int width, height; /* width and height of decoration */ - int xshift, yshift; /* deco shifting when gadget pressed */ -}; - -struct GadgetEvent -{ - unsigned long type; /* event type */ - int button; /* button number for button events */ - int x, y; /* gadget position at event time */ - boolean off_borders; /* mouse pointer outside gadget? */ - int item_x, item_y, item_position; /* new item position */ -}; - -struct GadgetDrawingArea -{ - int area_xsize, area_ysize; /* size of drawing area (in items) */ - int item_xsize, item_ysize; /* size of each item in drawing area */ -}; - -struct GadgetTextInput -{ - char value[MAX_GADGET_TEXTSIZE]; /* text string in input field */ - int number_value; /* integer value, if numeric */ - int number_min; /* minimal allowed numeric value */ - int number_max; /* maximal allowed numeric value */ - int size; /* maximal size of input text */ - int cursor_position; /* actual cursor position */ - int font_type; /* font to use for text input */ -}; - -struct GadgetScrollbar -{ - int items_max; /* number of items to access */ - int items_visible; /* number of visible items */ - int item_position; /* actual item position */ - int size_max; /* this is either width or height */ - int size; /* scrollbar size on screen */ - int position; /* scrollbar position on screen */ - int position_max; /* bottom/right scrollbar position */ - int drag_position; /* drag position on scrollbar */ - int correction; /* scrollbar position correction */ -}; - -struct GadgetInfo -{ - int id; /* internal gadget identifier */ - int custom_id; /* custom gadget identifier */ - int custom_type_id; /* custom gadget type identifier */ - char info_text[MAX_INFO_TEXTSIZE]; /* short popup info text */ - int x, y; /* gadget position */ - int width, height; /* gadget size */ - unsigned long type; /* type (button, text input, ...) */ - unsigned long state; /* state (pressed, released, ...) */ - boolean checked; /* check/radio button state */ - int radio_nr; /* number of radio button series */ - boolean mapped; /* gadget is active */ - struct GadgetBorder border; /* gadget border design */ - struct GadgetDesign design[2]; /* 0: normal; 1: pressed */ - struct GadgetDesign alt_design[2]; /* alternative design */ - struct GadgetDecoration deco; /* decoration on top of gadget */ - unsigned long event_mask; /* possible events for this gadget */ - struct GadgetEvent event; /* actual gadget event */ - gadget_function callback_info; /* function for pop-up info text */ - gadget_function callback_action; /* function for gadget action */ - struct GadgetDrawingArea drawing; /* fields for drawing area gadget */ - struct GadgetTextInput text; /* fields for text input gadget */ - struct GadgetScrollbar scrollbar; /* fields for scrollbar gadget */ - struct GadgetInfo *next; /* next list entry */ -}; - -struct GadgetInfo *CreateGadget(int, ...); -void FreeGadget(struct GadgetInfo *); - -void ModifyGadget(struct GadgetInfo *, int, ...); -void RedrawGadget(struct GadgetInfo *); - -void MapGadget(struct GadgetInfo *); -void UnmapGadget(struct GadgetInfo *); -void UnmapAllGadgets(); -void RemapAllGadgets(); - -boolean anyTextGadgetActive(); -void ClickOnGadget(struct GadgetInfo *, int); - -void HandleGadgets(int, int, int); -void HandleGadgetsKeyInput(Key); - -#endif diff --git a/src/libgame/gadgets.c b/src/libgame/gadgets.c new file mode 100644 index 00000000..9827fc80 --- /dev/null +++ b/src/libgame/gadgets.c @@ -0,0 +1,1349 @@ +/*********************************************************** +* Rocks'n'Diamonds -- McDuffin Strikes Back! * +*----------------------------------------------------------* +* (c) 1995-98 Artsoft Entertainment * +* Holger Schemel * +* Oststrasse 11a * +* 33604 Bielefeld * +* phone: ++49 +521 290471 * +* email: aeglos@valinor.owl.de * +*----------------------------------------------------------* +* gadgets.c * +***********************************************************/ + +#include + +#include "libgame.h" + +#include "main_TMP.h" + +#include "gadgets.h" + +/* some positions in the video tape control window */ +#define VIDEO_DATE_LABEL_XPOS (VIDEO_DISPLAY1_XPOS) +#define VIDEO_DATE_LABEL_YPOS (VIDEO_DISPLAY1_YPOS) +#define VIDEO_DATE_LABEL_XSIZE (VIDEO_DISPLAY_XSIZE) +#define VIDEO_DATE_LABEL_YSIZE (VIDEO_DISPLAY_YSIZE) +#define VIDEO_DATE_XPOS (VIDEO_DISPLAY1_XPOS + 1) +#define VIDEO_DATE_YPOS (VIDEO_DISPLAY1_YPOS + 14) +#define VIDEO_DATE_XSIZE (VIDEO_DISPLAY_XSIZE) +#define VIDEO_DATE_YSIZE 16 +#define VIDEO_REC_LABEL_XPOS (VIDEO_DISPLAY2_XPOS) +#define VIDEO_REC_LABEL_YPOS (VIDEO_DISPLAY2_YPOS) +#define VIDEO_REC_LABEL_XSIZE 20 +#define VIDEO_REC_LABEL_YSIZE 12 +#define VIDEO_REC_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS + 20) +#define VIDEO_REC_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS) +#define VIDEO_REC_SYMBOL_XSIZE 16 +#define VIDEO_REC_SYMBOL_YSIZE 16 +#define VIDEO_PLAY_LABEL_XPOS (VIDEO_DISPLAY2_XPOS + 65) +#define VIDEO_PLAY_LABEL_YPOS (VIDEO_DISPLAY2_YPOS) +#define VIDEO_PLAY_LABEL_XSIZE 22 +#define VIDEO_PLAY_LABEL_YSIZE 12 +#define VIDEO_PLAY_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS + 52) +#define VIDEO_PLAY_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS) +#define VIDEO_PLAY_SYMBOL_XSIZE 11 +#define VIDEO_PLAY_SYMBOL_YSIZE 13 +#define VIDEO_PAUSE_LABEL_XPOS (VIDEO_DISPLAY2_XPOS) +#define VIDEO_PAUSE_LABEL_YPOS (VIDEO_DISPLAY2_YPOS + 20) +#define VIDEO_PAUSE_LABEL_XSIZE 35 +#define VIDEO_PAUSE_LABEL_YSIZE 8 +#define VIDEO_PAUSE_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS + 35) +#define VIDEO_PAUSE_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS) +#define VIDEO_PAUSE_SYMBOL_XSIZE 17 +#define VIDEO_PAUSE_SYMBOL_YSIZE 13 +#define VIDEO_TIME_XPOS (VIDEO_DISPLAY2_XPOS + 38) +#define VIDEO_TIME_YPOS (VIDEO_DISPLAY2_YPOS + 14) +#define VIDEO_TIME_XSIZE 50 +#define VIDEO_TIME_YSIZE 16 + +/* special */ +#define VIDEO_PBEND_LABEL_XPOS 6 +#define VIDEO_PBEND_LABEL_YPOS 220 +#define VIDEO_PBEND_LABEL_XSIZE 35 +#define VIDEO_PBEND_LABEL_YSIZE 30 + +#define VIDEO_STATE_OFF (VIDEO_STATE_PLAY_OFF | \ + VIDEO_STATE_REC_OFF | \ + VIDEO_STATE_PAUSE_OFF | \ + VIDEO_STATE_FFWD_OFF | \ + VIDEO_STATE_PBEND_OFF | \ + VIDEO_STATE_DATE_OFF | \ + VIDEO_STATE_TIME_OFF) +#define VIDEO_PRESS_OFF (VIDEO_PRESS_PLAY_OFF | \ + VIDEO_PRESS_REC_OFF | \ + VIDEO_PRESS_PAUSE_OFF | \ + VIDEO_PRESS_STOP_OFF | \ + VIDEO_PRESS_EJECT_OFF) +#define VIDEO_ALL_OFF (VIDEO_STATE_OFF | VIDEO_PRESS_OFF) + +#define VIDEO_STATE_ON (VIDEO_STATE_PLAY_ON | \ + VIDEO_STATE_REC_ON | \ + VIDEO_STATE_PAUSE_ON | \ + VIDEO_STATE_FFWD_ON | \ + VIDEO_STATE_PBEND_ON | \ + VIDEO_STATE_DATE_ON | \ + VIDEO_STATE_TIME_ON) +#define VIDEO_PRESS_ON (VIDEO_PRESS_PLAY_ON | \ + VIDEO_PRESS_REC_ON | \ + VIDEO_PRESS_PAUSE_ON | \ + VIDEO_PRESS_STOP_ON | \ + VIDEO_PRESS_EJECT_ON) +#define VIDEO_ALL_ON (VIDEO_STATE_ON | VIDEO_PRESS_ON) + +#define VIDEO_STATE (VIDEO_STATE_ON | VIDEO_STATE_OFF) +#define VIDEO_PRESS (VIDEO_PRESS_ON | VIDEO_PRESS_OFF) +#define VIDEO_ALL (VIDEO_ALL_ON | VIDEO_ALL_OFF) + + +void DrawVideoDisplay(unsigned long state, unsigned long value) +{ + int i; + int part_label = 0, part_symbol = 1; + int xpos = 0, ypos = 1, xsize = 2, ysize = 3; + static char *monatsname[12] = + { + "JAN", "FEB", "MAR", "APR", "MAY", "JUN", + "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" + }; + static int video_pos[5][2][4] = + { + {{ VIDEO_PLAY_LABEL_XPOS, VIDEO_PLAY_LABEL_YPOS, + VIDEO_PLAY_LABEL_XSIZE,VIDEO_PLAY_LABEL_YSIZE }, + { VIDEO_PLAY_SYMBOL_XPOS, VIDEO_PLAY_SYMBOL_YPOS, + VIDEO_PLAY_SYMBOL_XSIZE,VIDEO_PLAY_SYMBOL_YSIZE }}, + + {{ VIDEO_REC_LABEL_XPOS, VIDEO_REC_LABEL_YPOS, + VIDEO_REC_LABEL_XSIZE,VIDEO_REC_LABEL_YSIZE }, + { VIDEO_REC_SYMBOL_XPOS, VIDEO_REC_SYMBOL_YPOS, + VIDEO_REC_SYMBOL_XSIZE,VIDEO_REC_SYMBOL_YSIZE }}, + + {{ VIDEO_PAUSE_LABEL_XPOS, VIDEO_PAUSE_LABEL_YPOS, + VIDEO_PAUSE_LABEL_XSIZE,VIDEO_PAUSE_LABEL_YSIZE }, + { VIDEO_PAUSE_SYMBOL_XPOS, VIDEO_PAUSE_SYMBOL_YPOS, + VIDEO_PAUSE_SYMBOL_XSIZE,VIDEO_PAUSE_SYMBOL_YSIZE }}, + + {{ VIDEO_DATE_LABEL_XPOS, VIDEO_DATE_LABEL_YPOS, + VIDEO_DATE_LABEL_XSIZE,VIDEO_DATE_LABEL_YSIZE }, + { VIDEO_DATE_XPOS, VIDEO_DATE_YPOS, + VIDEO_DATE_XSIZE,VIDEO_DATE_YSIZE }}, + + {{ 0,0, + 0,0 }, + { VIDEO_TIME_XPOS, VIDEO_TIME_YPOS, + VIDEO_TIME_XSIZE,VIDEO_TIME_YSIZE }} + }; + + if (state & VIDEO_STATE_PBEND_OFF) + { + int cx = DOOR_GFX_PAGEX3, cy = DOOR_GFX_PAGEY2; + + BlitBitmap(pix[PIX_DOOR], drawto, + cx + VIDEO_REC_LABEL_XPOS, + cy + VIDEO_REC_LABEL_YPOS, + VIDEO_PBEND_LABEL_XSIZE, + VIDEO_PBEND_LABEL_YSIZE, + VX + VIDEO_REC_LABEL_XPOS, + VY + VIDEO_REC_LABEL_YPOS); + } + + for(i=0;i<10;i++) + { + if (state & (1< STATE_ON / PRESS_OFF */ + cx = DOOR_GFX_PAGEX4; + else + cx = DOOR_GFX_PAGEX3; /* i gerade => STATE_OFF / PRESS_ON */ + + if (video_pos[pos][part_label][0] && value != VIDEO_DISPLAY_SYMBOL_ONLY) + BlitBitmap(pix[PIX_DOOR], drawto, + cx + video_pos[pos][part_label][xpos], + cy + video_pos[pos][part_label][ypos], + video_pos[pos][part_label][xsize], + video_pos[pos][part_label][ysize], + VX + video_pos[pos][part_label][xpos], + VY + video_pos[pos][part_label][ypos]); + if (video_pos[pos][part_symbol][0] && value != VIDEO_DISPLAY_LABEL_ONLY) + BlitBitmap(pix[PIX_DOOR], drawto, + cx + video_pos[pos][part_symbol][xpos], + cy + video_pos[pos][part_symbol][ypos], + video_pos[pos][part_symbol][xsize], + video_pos[pos][part_symbol][ysize], + VX + video_pos[pos][part_symbol][xpos], + VY + video_pos[pos][part_symbol][ypos]); + } + } + + if (state & VIDEO_STATE_FFWD_ON) + { + int cx = DOOR_GFX_PAGEX4, cy = DOOR_GFX_PAGEY2; + + BlitBitmap(pix[PIX_DOOR], drawto, + cx + VIDEO_PLAY_SYMBOL_XPOS, + cy + VIDEO_PLAY_SYMBOL_YPOS, + VIDEO_PLAY_SYMBOL_XSIZE - 2, + VIDEO_PLAY_SYMBOL_YSIZE, + VX + VIDEO_PLAY_SYMBOL_XPOS - 9, + VY + VIDEO_PLAY_SYMBOL_YPOS); + } + + if (state & VIDEO_STATE_PBEND_ON) + { + int cx = DOOR_GFX_PAGEX6, cy = DOOR_GFX_PAGEY1; + + BlitBitmap(pix[PIX_DOOR], drawto, + cx + VIDEO_PBEND_LABEL_XPOS, + cy + VIDEO_PBEND_LABEL_YPOS, + VIDEO_PBEND_LABEL_XSIZE, + VIDEO_PBEND_LABEL_YSIZE, + VX + VIDEO_REC_LABEL_XPOS, + VY + VIDEO_REC_LABEL_YPOS); + } + + if (state & VIDEO_STATE_DATE_ON) + { + int tag = value % 100; + int monat = (value/100) % 100; + int jahr = (value/10000); + + DrawText(VX+VIDEO_DATE_XPOS,VY+VIDEO_DATE_YPOS, + int2str(tag,2),FS_SMALL,FC_SPECIAL1); + DrawText(VX+VIDEO_DATE_XPOS+27,VY+VIDEO_DATE_YPOS, + monatsname[monat],FS_SMALL,FC_SPECIAL1); + DrawText(VX+VIDEO_DATE_XPOS+64,VY+VIDEO_DATE_YPOS, + int2str(jahr,2),FS_SMALL,FC_SPECIAL1); + } + + if (state & VIDEO_STATE_TIME_ON) + { + int min = value / 60; + int sec = value % 60; + + DrawText(VX+VIDEO_TIME_XPOS,VY+VIDEO_TIME_YPOS, + int2str(min,2),FS_SMALL,FC_SPECIAL1); + DrawText(VX+VIDEO_TIME_XPOS+27,VY+VIDEO_TIME_YPOS, + int2str(sec,2),FS_SMALL,FC_SPECIAL1); + } + + if (state & VIDEO_STATE_DATE) + redraw_mask |= REDRAW_VIDEO_1; + if ((state & ~VIDEO_STATE_DATE) & VIDEO_STATE) + redraw_mask |= REDRAW_VIDEO_2; + if (state & VIDEO_PRESS) + redraw_mask |= REDRAW_VIDEO_3; +} + +void DrawCompleteVideoDisplay() +{ + BlitBitmap(pix[PIX_DOOR], drawto, + DOOR_GFX_PAGEX3,DOOR_GFX_PAGEY2, VXSIZE,VYSIZE, VX,VY); + BlitBitmap(pix[PIX_DOOR], drawto, + DOOR_GFX_PAGEX4+VIDEO_CONTROL_XPOS, + DOOR_GFX_PAGEY2+VIDEO_CONTROL_YPOS, + VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE, + VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS); + + DrawVideoDisplay(VIDEO_ALL_OFF,0); + if (tape.date && tape.length) + { + DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date); + DrawVideoDisplay(VIDEO_STATE_TIME_ON,tape.length_seconds); + } + + BlitBitmap(drawto, pix[PIX_DB_DOOR], + VX,VY, VXSIZE,VYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2); +} + + +/* NEW GADGET STUFF -------------------------------------------------------- */ + + +/* values for DrawGadget() */ +#define DG_UNPRESSED 0 +#define DG_PRESSED 1 +#define DG_BUFFERED 0 +#define DG_DIRECT 1 + +static struct GadgetInfo *gadget_list_first_entry = NULL; +static struct GadgetInfo *gadget_list_last_entry = NULL; +static int next_free_gadget_id = 1; +static boolean gadget_id_wrapped = FALSE; + +static struct GadgetInfo *getGadgetInfoFromGadgetID(int id) +{ + struct GadgetInfo *gi = gadget_list_first_entry; + + while (gi && gi->id != id) + gi = gi->next; + + return gi; +} + +static int getNewGadgetID() +{ + int id = next_free_gadget_id++; + + if (next_free_gadget_id <= 0) /* counter overrun */ + { + gadget_id_wrapped = TRUE; /* now we must check each ID */ + next_free_gadget_id = 0; + } + + if (gadget_id_wrapped) + { + next_free_gadget_id++; + while (getGadgetInfoFromGadgetID(next_free_gadget_id) != NULL) + next_free_gadget_id++; + } + + if (next_free_gadget_id <= 0) /* cannot get new gadget id */ + Error(ERR_EXIT, "too much gadgets -- this should not happen"); + + return id; +} + +static struct GadgetInfo *getGadgetInfoFromMousePosition(int mx, int my) +{ + struct GadgetInfo *gi = gadget_list_first_entry; + + while (gi) + { + if (gi->mapped && + mx >= gi->x && mx < gi->x + gi->width && + my >= gi->y && my < gi->y + gi->height) + break; + + gi = gi->next; + } + + return gi; +} + +static void default_callback_info(void *ptr) +{ +#if 0 + if (game_status == LEVELED) + HandleEditorGadgetInfoText(ptr); +#endif + + return; +} + +static void default_callback_action(void *ptr) +{ + return; +} + +static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct) +{ + int state = (pressed ? 1 : 0); + struct GadgetDesign *gd = (gi->checked ? + &gi->alt_design[state] : + &gi->design[state]); + + switch (gi->type) + { + case GD_TYPE_NORMAL_BUTTON: + case GD_TYPE_CHECK_BUTTON: + case GD_TYPE_RADIO_BUTTON: + BlitBitmap(gd->bitmap, drawto, + gd->x, gd->y, gi->width, gi->height, gi->x, gi->y); + if (gi->deco.design.bitmap) + BlitBitmap(gi->deco.design.bitmap, drawto, + gi->deco.design.x, gi->deco.design.y, + gi->deco.width, gi->deco.height, + gi->x + gi->deco.x + (pressed ? gi->deco.xshift : 0), + gi->y + gi->deco.y + (pressed ? gi->deco.yshift : 0)); + break; + + case GD_TYPE_TEXTINPUT_ALPHANUMERIC: + case GD_TYPE_TEXTINPUT_NUMERIC: + { + int i; + char cursor_letter; + char cursor_string[3]; + char text[MAX_GADGET_TEXTSIZE + 1]; + int font_type = gi->text.font_type; + int font_width = getFontWidth(FS_SMALL, font_type); + int border = gi->border.size; + strcpy(text, gi->text.value); + strcat(text, " "); + + /* left part of gadget */ + BlitBitmap(gd->bitmap, drawto, + gd->x, gd->y, border, gi->height, gi->x, gi->y); + + /* middle part of gadget */ + for (i=0; i<=gi->text.size; i++) + BlitBitmap(gd->bitmap, drawto, + gd->x + border, gd->y, font_width, gi->height, + gi->x + border + i * font_width, gi->y); + + /* right part of gadget */ + BlitBitmap(gd->bitmap, drawto, + gd->x + gi->border.width - border, gd->y, + border, gi->height, gi->x + gi->width - border, gi->y); + + /* gadget text value */ + DrawText(gi->x + border, gi->y + border, text, FS_SMALL, font_type); + + cursor_letter = gi->text.value[gi->text.cursor_position]; + cursor_string[0] = '~'; + cursor_string[1] = (cursor_letter != '\0' ? cursor_letter : ' '); + cursor_string[2] = '\0'; + + /* draw cursor, if active */ + if (pressed) + DrawText(gi->x + border + gi->text.cursor_position * font_width, + gi->y + border, cursor_string, FS_SMALL, font_type); + } + break; + + case GD_TYPE_SCROLLBAR_VERTICAL: + { + int i; + int xpos = gi->x; + int ypos = gi->y + gi->scrollbar.position; + int design_full = gi->width; + int design_body = design_full - 2 * gi->border.size; + int size_full = gi->scrollbar.size; + int size_body = size_full - 2 * gi->border.size; + int num_steps = size_body / design_body; + int step_size_remain = size_body - num_steps * design_body; + + /* clear scrollbar area */ + ClearRectangle(backbuffer, gi->x, gi->y, gi->width, gi->height); + + /* upper part of gadget */ + BlitBitmap(gd->bitmap, drawto, + gd->x, gd->y, + gi->width, gi->border.size, + xpos, ypos); + + /* middle part of gadget */ + for (i=0; ibitmap, drawto, + gd->x, gd->y + gi->border.size, + gi->width, design_body, + xpos, ypos + gi->border.size + i * design_body); + + /* remaining middle part of gadget */ + if (step_size_remain > 0) + BlitBitmap(gd->bitmap, drawto, + gd->x, gd->y + gi->border.size, + gi->width, step_size_remain, + xpos, ypos + gi->border.size + num_steps * design_body); + + /* lower part of gadget */ + BlitBitmap(gd->bitmap, drawto, + gd->x, gd->y + design_full - gi->border.size, + gi->width, gi->border.size, + xpos, ypos + size_full - gi->border.size); + } + break; + + case GD_TYPE_SCROLLBAR_HORIZONTAL: + { + int i; + int xpos = gi->x + gi->scrollbar.position; + int ypos = gi->y; + int design_full = gi->height; + int design_body = design_full - 2 * gi->border.size; + int size_full = gi->scrollbar.size; + int size_body = size_full - 2 * gi->border.size; + int num_steps = size_body / design_body; + int step_size_remain = size_body - num_steps * design_body; + + /* clear scrollbar area */ + ClearRectangle(backbuffer, gi->x, gi->y, gi->width, gi->height); + + /* left part of gadget */ + BlitBitmap(gd->bitmap, drawto, + gd->x, gd->y, + gi->border.size, gi->height, + xpos, ypos); + + /* middle part of gadget */ + for (i=0; ibitmap, drawto, + gd->x + gi->border.size, gd->y, + design_body, gi->height, + xpos + gi->border.size + i * design_body, ypos); + + /* remaining middle part of gadget */ + if (step_size_remain > 0) + BlitBitmap(gd->bitmap, drawto, + gd->x + gi->border.size, gd->y, + step_size_remain, gi->height, + xpos + gi->border.size + num_steps * design_body, ypos); + + /* right part of gadget */ + BlitBitmap(gd->bitmap, drawto, + gd->x + design_full - gi->border.size, gd->y, + gi->border.size, gi->height, + xpos + size_full - gi->border.size, ypos); + } + break; + + default: + return; + } + + if (direct) + BlitBitmap(drawto, window, + gi->x, gi->y, gi->width, gi->height, gi->x, gi->y); + else + redraw_mask |= (gi->x < SX + SXSIZE ? REDRAW_FIELD : + gi->y < DY + DYSIZE ? REDRAW_DOOR_1 : + gi->y > VY ? REDRAW_DOOR_2 : REDRAW_DOOR_3); +} + +static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap) +{ + int tag = first_tag; + + while (tag != GDI_END) + { + switch(tag) + { + case GDI_CUSTOM_ID: + gi->custom_id = va_arg(ap, int); + break; + + case GDI_CUSTOM_TYPE_ID: + gi->custom_type_id = va_arg(ap, int); + break; + + case GDI_INFO_TEXT: + { + int max_textsize = MAX_INFO_TEXTSIZE - 1; + + strncpy(gi->info_text, va_arg(ap, char *), max_textsize); + gi->info_text[max_textsize] = '\0'; + } + break; + + case GDI_X: + gi->x = va_arg(ap, int); + break; + + case GDI_Y: + gi->y = va_arg(ap, int); + break; + + case GDI_WIDTH: + gi->width = va_arg(ap, int); + break; + + case GDI_HEIGHT: + gi->height = va_arg(ap, int); + break; + + case GDI_TYPE: + gi->type = va_arg(ap, unsigned long); + break; + + case GDI_STATE: + gi->state = va_arg(ap, unsigned long); + break; + + case GDI_CHECKED: + gi->checked = va_arg(ap, boolean); + break; + + case GDI_RADIO_NR: + gi->radio_nr = va_arg(ap, unsigned long); + break; + + case GDI_NUMBER_VALUE: + gi->text.number_value = va_arg(ap, long); + sprintf(gi->text.value, "%d", gi->text.number_value); + gi->text.cursor_position = strlen(gi->text.value); + break; + + case GDI_NUMBER_MIN: + gi->text.number_min = va_arg(ap, long); + if (gi->text.number_value < gi->text.number_min) + { + gi->text.number_value = gi->text.number_min; + sprintf(gi->text.value, "%d", gi->text.number_value); + } + break; + + case GDI_NUMBER_MAX: + gi->text.number_max = va_arg(ap, long); + if (gi->text.number_value > gi->text.number_max) + { + gi->text.number_value = gi->text.number_max; + sprintf(gi->text.value, "%d", gi->text.number_value); + } + break; + + case GDI_TEXT_VALUE: + { + int max_textsize = MAX_GADGET_TEXTSIZE; + + if (gi->text.size) + max_textsize = MIN(gi->text.size, MAX_GADGET_TEXTSIZE - 1); + + strncpy(gi->text.value, va_arg(ap, char *), max_textsize); + gi->text.value[max_textsize] = '\0'; + gi->text.cursor_position = strlen(gi->text.value); + } + break; + + case GDI_TEXT_SIZE: + { + int tag_value = va_arg(ap, int); + int max_textsize = MIN(tag_value, MAX_GADGET_TEXTSIZE - 1); + + gi->text.size = max_textsize; + gi->text.value[max_textsize] = '\0'; + } + break; + + case GDI_TEXT_FONT: + gi->text.font_type = va_arg(ap, int); + break; + + case GDI_DESIGN_UNPRESSED: + gi->design[GD_BUTTON_UNPRESSED].bitmap = va_arg(ap, Bitmap); + gi->design[GD_BUTTON_UNPRESSED].x = va_arg(ap, int); + gi->design[GD_BUTTON_UNPRESSED].y = va_arg(ap, int); + break; + + case GDI_DESIGN_PRESSED: + gi->design[GD_BUTTON_PRESSED].bitmap = va_arg(ap, Bitmap); + gi->design[GD_BUTTON_PRESSED].x = va_arg(ap, int); + gi->design[GD_BUTTON_PRESSED].y = va_arg(ap, int); + break; + + case GDI_ALT_DESIGN_UNPRESSED: + gi->alt_design[GD_BUTTON_UNPRESSED].bitmap= va_arg(ap, Bitmap); + gi->alt_design[GD_BUTTON_UNPRESSED].x = va_arg(ap, int); + gi->alt_design[GD_BUTTON_UNPRESSED].y = va_arg(ap, int); + break; + + case GDI_ALT_DESIGN_PRESSED: + gi->alt_design[GD_BUTTON_PRESSED].bitmap = va_arg(ap, Bitmap); + gi->alt_design[GD_BUTTON_PRESSED].x = va_arg(ap, int); + gi->alt_design[GD_BUTTON_PRESSED].y = va_arg(ap, int); + break; + + case GDI_BORDER_SIZE: + gi->border.size = va_arg(ap, int); + break; + + case GDI_TEXTINPUT_DESIGN_WIDTH: + gi->border.width = va_arg(ap, int); + break; + + case GDI_DECORATION_DESIGN: + gi->deco.design.bitmap = va_arg(ap, Bitmap); + gi->deco.design.x = va_arg(ap, int); + gi->deco.design.y = va_arg(ap, int); + break; + + case GDI_DECORATION_POSITION: + gi->deco.x = va_arg(ap, int); + gi->deco.y = va_arg(ap, int); + break; + + case GDI_DECORATION_SIZE: + gi->deco.width = va_arg(ap, int); + gi->deco.height = va_arg(ap, int); + break; + + case GDI_DECORATION_SHIFTING: + gi->deco.xshift = va_arg(ap, int); + gi->deco.yshift = va_arg(ap, int); + break; + + case GDI_EVENT_MASK: + gi->event_mask = va_arg(ap, unsigned long); + break; + + case GDI_AREA_SIZE: + gi->drawing.area_xsize = va_arg(ap, int); + gi->drawing.area_ysize = va_arg(ap, int); + + /* determine dependent values for drawing area gadget, if needed */ + if (gi->width == 0 && gi->height == 0 && + gi->drawing.item_xsize !=0 && gi->drawing.item_ysize !=0) + { + gi->width = gi->drawing.area_xsize * gi->drawing.item_xsize; + gi->height = gi->drawing.area_ysize * gi->drawing.item_ysize; + } + else if (gi->drawing.item_xsize == 0 && gi->drawing.item_ysize == 0 && + gi->width != 0 && gi->height != 0) + { + gi->drawing.item_xsize = gi->width / gi->drawing.area_xsize; + gi->drawing.item_ysize = gi->height / gi->drawing.area_ysize; + } + break; + + case GDI_ITEM_SIZE: + gi->drawing.item_xsize = va_arg(ap, int); + gi->drawing.item_ysize = va_arg(ap, int); + + /* determine dependent values for drawing area gadget, if needed */ + if (gi->width == 0 && gi->height == 0 && + gi->drawing.area_xsize !=0 && gi->drawing.area_ysize !=0) + { + gi->width = gi->drawing.area_xsize * gi->drawing.item_xsize; + gi->height = gi->drawing.area_ysize * gi->drawing.item_ysize; + } + else if (gi->drawing.area_xsize == 0 && gi->drawing.area_ysize == 0 && + gi->width != 0 && gi->height != 0) + { + gi->drawing.area_xsize = gi->width / gi->drawing.item_xsize; + gi->drawing.area_ysize = gi->height / gi->drawing.item_ysize; + } + break; + + case GDI_SCROLLBAR_ITEMS_MAX: + gi->scrollbar.items_max = va_arg(ap, int); + break; + + case GDI_SCROLLBAR_ITEMS_VISIBLE: + gi->scrollbar.items_visible = va_arg(ap, int); + break; + + case GDI_SCROLLBAR_ITEM_POSITION: + gi->scrollbar.item_position = va_arg(ap, int); + break; + + case GDI_CALLBACK_INFO: + gi->callback_info = va_arg(ap, gadget_function); + break; + + case GDI_CALLBACK_ACTION: + gi->callback_action = va_arg(ap, gadget_function); + break; + + default: + Error(ERR_EXIT, "HandleGadgetTags(): unknown tag %d", tag); + } + + tag = va_arg(ap, int); /* read next tag */ + } + + /* check if gadget complete */ + if (gi->type != GD_TYPE_DRAWING_AREA && + (!gi->design[GD_BUTTON_UNPRESSED].bitmap || + !gi->design[GD_BUTTON_PRESSED].bitmap)) + Error(ERR_EXIT, "gadget incomplete (missing Bitmap)"); + + /* adjust gadget values in relation to other gadget values */ + + if (gi->type & GD_TYPE_TEXTINPUT) + { + int font_width = getFontWidth(FS_SMALL, gi->text.font_type); + int font_height = getFontHeight(FS_SMALL, gi->text.font_type); + + gi->width = 2 * gi->border.size + (gi->text.size + 1) * font_width; + gi->height = 2 * gi->border.size + font_height; + } + + if (gi->type & GD_TYPE_TEXTINPUT_NUMERIC) + { + struct GadgetTextInput *text = &gi->text; + int value = text->number_value; + + text->number_value = (value < text->number_min ? text->number_min : + value > text->number_max ? text->number_max : + value); + + sprintf(text->value, "%d", text->number_value); + } + + if (gi->type & GD_TYPE_SCROLLBAR) + { + struct GadgetScrollbar *gs = &gi->scrollbar; + + if (gi->width == 0 || gi->height == 0 || + gs->items_max == 0 || gs->items_visible == 0) + Error(ERR_EXIT, "scrollbar gadget incomplete (missing tags)"); + + /* calculate internal scrollbar values */ + gs->size_max = (gi->type == GD_TYPE_SCROLLBAR_VERTICAL ? + gi->height : gi->width); + gs->size = gs->size_max * gs->items_visible / gs->items_max; + gs->position = gs->size_max * gs->item_position / gs->items_max; + gs->position_max = gs->size_max - gs->size; + gs->correction = gs->size_max / gs->items_max / 2; + + /* finetuning for maximal right/bottom position */ + if (gs->item_position == gs->items_max - gs->items_visible) + gs->position = gs->position_max; + } +} + +void ModifyGadget(struct GadgetInfo *gi, int first_tag, ...) +{ + va_list ap; + + va_start(ap, first_tag); + HandleGadgetTags(gi, first_tag, ap); + va_end(ap); + + RedrawGadget(gi); +} + +void RedrawGadget(struct GadgetInfo *gi) +{ + if (gi->mapped) + DrawGadget(gi, gi->state, DG_DIRECT); +} + +struct GadgetInfo *CreateGadget(int first_tag, ...) +{ + struct GadgetInfo *new_gadget = checked_malloc(sizeof(struct GadgetInfo)); + va_list ap; + + /* always start with reliable default values */ + memset(new_gadget, 0, sizeof(struct GadgetInfo)); /* zero all fields */ + new_gadget->id = getNewGadgetID(); + new_gadget->callback_info = default_callback_info; + new_gadget->callback_action = default_callback_action; + + va_start(ap, first_tag); + HandleGadgetTags(new_gadget, first_tag, ap); + va_end(ap); + + /* insert new gadget into global gadget list */ + if (gadget_list_last_entry) + { + gadget_list_last_entry->next = new_gadget; + gadget_list_last_entry = gadget_list_last_entry->next; + } + else + gadget_list_first_entry = gadget_list_last_entry = new_gadget; + + return new_gadget; +} + +void FreeGadget(struct GadgetInfo *gi) +{ + struct GadgetInfo *gi_previous = gadget_list_first_entry; + + while (gi_previous && gi_previous->next != gi) + gi_previous = gi_previous->next; + + if (gi == gadget_list_first_entry) + gadget_list_first_entry = gi->next; + + if (gi == gadget_list_last_entry) + gadget_list_last_entry = gi_previous; + + gi_previous->next = gi->next; + free(gi); +} + +static void CheckRangeOfNumericInputGadget(struct GadgetInfo *gi) +{ + if (gi->type != GD_TYPE_TEXTINPUT_NUMERIC) + return; + + gi->text.number_value = atoi(gi->text.value); + + if (gi->text.number_value < gi->text.number_min) + gi->text.number_value = gi->text.number_min; + if (gi->text.number_value > gi->text.number_max) + gi->text.number_value = gi->text.number_max; + + sprintf(gi->text.value, "%d", gi->text.number_value); + + if (gi->text.cursor_position < 0) + gi->text.cursor_position = 0; + else if (gi->text.cursor_position > strlen(gi->text.value)) + gi->text.cursor_position = strlen(gi->text.value); +} + +/* global pointer to gadget actually in use (when mouse button pressed) */ +static struct GadgetInfo *last_gi = NULL; + +static void MapGadgetExt(struct GadgetInfo *gi, boolean redraw) +{ + if (gi == NULL || gi->mapped) + return; + + gi->mapped = TRUE; + + if (redraw) + DrawGadget(gi, DG_UNPRESSED, DG_BUFFERED); +} + +void MapGadget(struct GadgetInfo *gi) +{ + MapGadgetExt(gi, TRUE); +} + +void UnmapGadget(struct GadgetInfo *gi) +{ + if (gi == NULL || !gi->mapped) + return; + + gi->mapped = FALSE; + + if (gi == last_gi) + last_gi = NULL; +} + +#define MAX_NUM_GADGETS 1024 +#define MULTIMAP_UNMAP (1 << 0) +#define MULTIMAP_REMAP (1 << 1) +#define MULTIMAP_REDRAW (1 << 2) +#define MULTIMAP_PLAYFIELD (1 << 3) +#define MULTIMAP_DOOR_1 (1 << 4) +#define MULTIMAP_DOOR_2 (1 << 5) +#define MULTIMAP_ALL (MULTIMAP_PLAYFIELD | \ + MULTIMAP_DOOR_1 | \ + MULTIMAP_DOOR_2) + +static void MultiMapGadgets(int mode) +{ + struct GadgetInfo *gi = gadget_list_first_entry; + static boolean map_state[MAX_NUM_GADGETS]; + int map_count = 0; + + while (gi) + { + if ((mode & MULTIMAP_PLAYFIELD && gi->x < SX + SXSIZE) || + (mode & MULTIMAP_DOOR_1 && gi->x >= DX && gi->y < DY + DYSIZE) || + (mode & MULTIMAP_DOOR_2 && gi->x >= DX && gi->y > DY + DYSIZE) || + (mode & MULTIMAP_ALL) == MULTIMAP_ALL) + { + if (mode & MULTIMAP_UNMAP) + { + map_state[map_count++ % MAX_NUM_GADGETS] = gi->mapped; + UnmapGadget(gi); + } + else + { + if (map_state[map_count++ % MAX_NUM_GADGETS]) + MapGadgetExt(gi, (mode & MULTIMAP_REDRAW)); + } + } + + gi = gi->next; + } +} + +void UnmapAllGadgets() +{ + MultiMapGadgets(MULTIMAP_ALL | MULTIMAP_UNMAP); +} + +void RemapAllGadgets() +{ + MultiMapGadgets(MULTIMAP_ALL | MULTIMAP_REMAP); +} + +boolean anyTextGadgetActive() +{ + return (last_gi && last_gi->type & GD_TYPE_TEXTINPUT && last_gi->mapped); +} + +void ClickOnGadget(struct GadgetInfo *gi, int button) +{ + /* simulate releasing mouse button over last gadget, if still pressed */ + if (button_status) + HandleGadgets(-1, -1, 0); + + /* simulate pressing mouse button over specified gadget */ + HandleGadgets(gi->x, gi->y, button); + + /* simulate releasing mouse button over specified gadget */ + HandleGadgets(gi->x, gi->y, 0); +} + +void HandleGadgets(int mx, int my, int button) +{ + static struct GadgetInfo *last_info_gi = NULL; + static unsigned long pressed_delay = 0; + static int last_button = 0; + static int last_mx = 0, last_my = 0; + int scrollbar_mouse_pos = 0; + struct GadgetInfo *new_gi, *gi; + boolean press_event; + boolean release_event; + boolean mouse_moving; + boolean gadget_pressed; + boolean gadget_pressed_repeated; + boolean gadget_moving; + boolean gadget_moving_inside; + boolean gadget_moving_off_borders; + boolean gadget_released; + boolean gadget_released_inside; + boolean gadget_released_off_borders; + boolean changed_position = FALSE; + + /* check if there are any gadgets defined */ + if (gadget_list_first_entry == NULL) + return; + + /* check which gadget is under the mouse pointer */ + new_gi = getGadgetInfoFromMousePosition(mx, my); + + /* check if button state has changed since last invocation */ + press_event = (button != 0 && last_button == 0); + release_event = (button == 0 && last_button != 0); + last_button = button; + + /* check if mouse has been moved since last invocation */ + mouse_moving = ((mx != last_mx || my != last_my) && motion_status); + last_mx = mx; + last_my = my; + + /* special treatment for text and number input gadgets */ + if (anyTextGadgetActive() && button != 0 && !motion_status) + { + struct GadgetInfo *gi = last_gi; + + if (new_gi == last_gi) + { + /* if mouse button pressed inside activated text gadget, set cursor */ + gi->text.cursor_position = + (mx - gi->x - gi->border.size) / + getFontWidth(FS_SMALL, gi->text.font_type); + + if (gi->text.cursor_position < 0) + gi->text.cursor_position = 0; + else if (gi->text.cursor_position > strlen(gi->text.value)) + gi->text.cursor_position = strlen(gi->text.value); + + DrawGadget(gi, DG_PRESSED, DG_DIRECT); + } + else + { + /* if mouse button pressed outside text input gadget, deactivate it */ + CheckRangeOfNumericInputGadget(gi); + DrawGadget(gi, DG_UNPRESSED, DG_DIRECT); + + gi->event.type = GD_EVENT_TEXT_LEAVING; + + if (gi->event_mask & GD_EVENT_TEXT_LEAVING) + gi->callback_action(gi); + + last_gi = NULL; + } + } + + gadget_pressed = + (button != 0 && last_gi == NULL && new_gi != NULL && press_event); + gadget_pressed_repeated = + (button != 0 && last_gi != NULL && new_gi == last_gi); + + gadget_released = (release_event && last_gi != NULL); + gadget_released_inside = (gadget_released && new_gi == last_gi); + gadget_released_off_borders = (gadget_released && new_gi != last_gi); + + gadget_moving = (button != 0 && last_gi != NULL && mouse_moving); + gadget_moving_inside = (gadget_moving && new_gi == last_gi); + gadget_moving_off_borders = (gadget_moving && new_gi != last_gi); + + /* if new gadget pressed, store this gadget */ + if (gadget_pressed) + last_gi = new_gi; + + /* 'gi' is actually handled gadget */ + gi = last_gi; + + /* if gadget is scrollbar, choose mouse position value */ + if (gi && gi->type & GD_TYPE_SCROLLBAR) + scrollbar_mouse_pos = + (gi->type == GD_TYPE_SCROLLBAR_HORIZONTAL ? mx - gi->x : my - gi->y); + + /* if mouse button released, no gadget needs to be handled anymore */ + if (button == 0 && last_gi && !(last_gi->type & GD_TYPE_TEXTINPUT)) + last_gi = NULL; + + /* modify event position values even if no gadget is pressed */ + if (button == 0 && !release_event) + gi = new_gi; + + if (gi) + { + int last_x = gi->event.x; + int last_y = gi->event.y; + + gi->event.x = mx - gi->x; + gi->event.y = my - gi->y; + + if (gi->type == GD_TYPE_DRAWING_AREA) + { + gi->event.x /= gi->drawing.item_xsize; + gi->event.y /= gi->drawing.item_ysize; + + if (last_x != gi->event.x || last_y != gi->event.y) + changed_position = TRUE; + } + } + + /* handle gadget popup info text */ + if (last_info_gi != new_gi || + (new_gi && new_gi->type == GD_TYPE_DRAWING_AREA && changed_position)) + { + last_info_gi = new_gi; + + if (new_gi != NULL && (button == 0 || new_gi == last_gi)) + { + new_gi->event.type = 0; + new_gi->callback_info(new_gi); + } + else + default_callback_info(NULL); + } + + if (gadget_pressed) + { + if (gi->type == GD_TYPE_CHECK_BUTTON) + { + gi->checked = !gi->checked; + } + else if (gi->type == GD_TYPE_RADIO_BUTTON) + { + struct GadgetInfo *rgi = gadget_list_first_entry; + + while (rgi) + { + if (rgi->mapped && + rgi->type == GD_TYPE_RADIO_BUTTON && + rgi->radio_nr == gi->radio_nr && + rgi != gi) + { + rgi->checked = FALSE; + DrawGadget(rgi, DG_UNPRESSED, DG_DIRECT); + } + + rgi = rgi->next; + } + + gi->checked = TRUE; + } + else if (gi->type & GD_TYPE_SCROLLBAR) + { + int mpos, gpos; + + if (gi->type == GD_TYPE_SCROLLBAR_HORIZONTAL) + { + mpos = mx; + gpos = gi->x; + } + else + { + mpos = my; + gpos = gi->y; + } + + if (mpos >= gpos + gi->scrollbar.position && + mpos < gpos + gi->scrollbar.position + gi->scrollbar.size) + { + /* drag scrollbar */ + gi->scrollbar.drag_position = + scrollbar_mouse_pos - gi->scrollbar.position; + } + else + { + /* click scrollbar one scrollbar length up/left or down/right */ + + struct GadgetScrollbar *gs = &gi->scrollbar; + int old_item_position = gs->item_position; + + changed_position = FALSE; + + gs->item_position += + gs->items_visible * (mpos < gpos + gi->scrollbar.position ? -1 : +1); + + if (gs->item_position < 0) + gs->item_position = 0; + if (gs->item_position > gs->items_max - gs->items_visible) + gs->item_position = gs->items_max - gs->items_visible; + + if (old_item_position != gs->item_position) + { + gi->event.item_position = gs->item_position; + changed_position = TRUE; + } + + ModifyGadget(gi, GDI_SCROLLBAR_ITEM_POSITION, gs->item_position, + GDI_END); + + gi->state = GD_BUTTON_UNPRESSED; + gi->event.type = GD_EVENT_MOVING; + gi->event.off_borders = FALSE; + + if (gi->event_mask & GD_EVENT_MOVING && changed_position) + gi->callback_action(gi); + + /* don't handle this scrollbar anymore while mouse button pressed */ + last_gi = NULL; + + return; + } + } + + DrawGadget(gi, DG_PRESSED, DG_DIRECT); + + gi->state = GD_BUTTON_PRESSED; + gi->event.type = GD_EVENT_PRESSED; + gi->event.button = button; + gi->event.off_borders = FALSE; + + /* initialize delay counter */ + DelayReached(&pressed_delay, 0); + + if (gi->event_mask & GD_EVENT_PRESSED) + gi->callback_action(gi); + } + + if (gadget_pressed_repeated) + { + gi->event.type = GD_EVENT_PRESSED; + + if (gi->event_mask & GD_EVENT_REPEATED && + DelayReached(&pressed_delay, GADGET_FRAME_DELAY)) + gi->callback_action(gi); + } + + if (gadget_moving) + { + if (gi->type & GD_TYPE_BUTTON) + { + if (gadget_moving_inside && gi->state == GD_BUTTON_UNPRESSED) + DrawGadget(gi, DG_PRESSED, DG_DIRECT); + else if (gadget_moving_off_borders && gi->state == GD_BUTTON_PRESSED) + DrawGadget(gi, DG_UNPRESSED, DG_DIRECT); + } + + if (gi->type & GD_TYPE_SCROLLBAR) + { + struct GadgetScrollbar *gs = &gi->scrollbar; + int old_item_position = gs->item_position; + + gs->position = scrollbar_mouse_pos - gs->drag_position; + + if (gs->position < 0) + gs->position = 0; + if (gs->position > gs->position_max) + gs->position = gs->position_max; + + gs->item_position = + gs->items_max * (gs->position + gs->correction) / gs->size_max; + + if (gs->item_position < 0) + gs->item_position = 0; + if (gs->item_position > gs->items_max - 1) + gs->item_position = gs->items_max - 1; + + if (old_item_position != gs->item_position) + { + gi->event.item_position = gs->item_position; + changed_position = TRUE; + } + + DrawGadget(gi, DG_PRESSED, DG_DIRECT); + } + + gi->state = (gadget_moving_inside || gi->type & GD_TYPE_SCROLLBAR ? + GD_BUTTON_PRESSED : GD_BUTTON_UNPRESSED); + gi->event.type = GD_EVENT_MOVING; + gi->event.off_borders = gadget_moving_off_borders; + + if (gi->event_mask & GD_EVENT_MOVING && changed_position && + (gadget_moving_inside || gi->event_mask & GD_EVENT_OFF_BORDERS)) + gi->callback_action(gi); + } + + if (gadget_released_inside) + { + if (!(gi->type & GD_TYPE_TEXTINPUT)) + DrawGadget(gi, DG_UNPRESSED, DG_DIRECT); + + gi->state = GD_BUTTON_UNPRESSED; + gi->event.type = GD_EVENT_RELEASED; + + if (gi->event_mask & GD_EVENT_RELEASED) + gi->callback_action(gi); + } + + if (gadget_released_off_borders) + { + if (gi->type & GD_TYPE_SCROLLBAR) + DrawGadget(gi, DG_UNPRESSED, DG_DIRECT); + + gi->event.type = GD_EVENT_RELEASED; + + if (gi->event_mask & GD_EVENT_RELEASED && + gi->event_mask & GD_EVENT_OFF_BORDERS) + gi->callback_action(gi); + } +} + +void HandleGadgetsKeyInput(Key key) +{ + struct GadgetInfo *gi = last_gi; + char text[MAX_GADGET_TEXTSIZE]; + int text_length; + int cursor_pos; + char letter; + boolean legal_letter; + + if (gi == NULL || !(gi->type & GD_TYPE_TEXTINPUT) || !gi->mapped) + return; + + text_length = strlen(gi->text.value); + cursor_pos = gi->text.cursor_position; + letter = getCharFromKey(key); + legal_letter = (gi->type == GD_TYPE_TEXTINPUT_NUMERIC ? + letter >= '0' && letter <= '9' : + letter != 0); + + if (legal_letter && text_length < gi->text.size) + { + strcpy(text, gi->text.value); + strcpy(&gi->text.value[cursor_pos + 1], &text[cursor_pos]); + gi->text.value[cursor_pos] = letter; + gi->text.cursor_position++; + DrawGadget(gi, DG_PRESSED, DG_DIRECT); + } + else if (key == KSYM_Left && cursor_pos > 0) + { + gi->text.cursor_position--; + DrawGadget(gi, DG_PRESSED, DG_DIRECT); + } + else if (key == KSYM_Right && cursor_pos < text_length) + { + gi->text.cursor_position++; + DrawGadget(gi, DG_PRESSED, DG_DIRECT); + } + else if (key == KSYM_BackSpace && cursor_pos > 0) + { + strcpy(text, gi->text.value); + strcpy(&gi->text.value[cursor_pos - 1], &text[cursor_pos]); + gi->text.cursor_position--; + DrawGadget(gi, DG_PRESSED, DG_DIRECT); + } + else if (key == KSYM_Delete && cursor_pos < text_length) + { + strcpy(text, gi->text.value); + strcpy(&gi->text.value[cursor_pos], &text[cursor_pos + 1]); + DrawGadget(gi, DG_PRESSED, DG_DIRECT); + } + else if (key == KSYM_Return) + { + CheckRangeOfNumericInputGadget(gi); + DrawGadget(gi, DG_UNPRESSED, DG_DIRECT); + + gi->event.type = GD_EVENT_TEXT_RETURN; + + if (gi->event_mask & GD_EVENT_TEXT_RETURN) + gi->callback_action(gi); + + last_gi = NULL; + } +} diff --git a/src/libgame/gadgets.h b/src/libgame/gadgets.h new file mode 100644 index 00000000..44a64f5f --- /dev/null +++ b/src/libgame/gadgets.h @@ -0,0 +1,265 @@ +/*********************************************************** +* Rocks'n'Diamonds -- McDuffin Strikes Back! * +*----------------------------------------------------------* +* (c) 1995-98 Artsoft Entertainment * +* Holger Schemel * +* Oststrasse 11a * +* 33604 Bielefeld * +* phone: ++49 +521 290471 * +* email: aeglos@valinor.owl.de * +*----------------------------------------------------------* +* gadgets.h * +***********************************************************/ + +#ifndef GADGETS_H +#define GADGETS_H + +#include "libgame.h" + +/* the following definitions are also used by tools.c */ + +/* some positions in the video tape control window */ +#define VIDEO_DISPLAY1_XPOS 5 +#define VIDEO_DISPLAY1_YPOS 5 +#define VIDEO_DISPLAY2_XPOS 5 +#define VIDEO_DISPLAY2_YPOS 41 +#define VIDEO_DISPLAY_XSIZE 90 +#define VIDEO_DISPLAY_YSIZE 31 +#define VIDEO_BUTTON_XSIZE 18 +#define VIDEO_BUTTON_YSIZE 18 +#define VIDEO_CONTROL_XPOS 5 +#define VIDEO_CONTROL_YPOS 77 +#define VIDEO_CONTROL_XSIZE VIDEO_DISPLAY_XSIZE +#define VIDEO_CONTROL_YSIZE VIDEO_BUTTON_YSIZE + +/* values for video tape control */ +#define VIDEO_STATE_PLAY_OFF (1L << 0) +#define VIDEO_STATE_PLAY_ON (1L << 1) +#define VIDEO_STATE_PLAY (VIDEO_STATE_PLAY_OFF | VIDEO_STATE_PLAY_ON) +#define VIDEO_STATE_REC_OFF (1L << 2) +#define VIDEO_STATE_REC_ON (1L << 3) +#define VIDEO_STATE_REC (VIDEO_STATE_REC_OFF | VIDEO_STATE_REC_ON) +#define VIDEO_STATE_PAUSE_OFF (1L << 4) +#define VIDEO_STATE_PAUSE_ON (1L << 5) +#define VIDEO_STATE_PAUSE (VIDEO_STATE_PAUSE_OFF | VIDEO_STATE_PAUSE_ON) +#define VIDEO_STATE_DATE_OFF (1L << 6) +#define VIDEO_STATE_DATE_ON (1L << 7) +#define VIDEO_STATE_DATE (VIDEO_STATE_DATE_OFF | VIDEO_STATE_DATE_ON) +#define VIDEO_STATE_TIME_OFF (1L << 8) +#define VIDEO_STATE_TIME_ON (1L << 9) +#define VIDEO_STATE_TIME (VIDEO_STATE_TIME_OFF | VIDEO_STATE_TIME_ON) +#define VIDEO_PRESS_PLAY_ON (1L << 10) +#define VIDEO_PRESS_PLAY_OFF (1L << 11) +#define VIDEO_PRESS_PLAY (VIDEO_PRESS_PLAY_OFF | VIDEO_PRESS_PLAY_ON) +#define VIDEO_PRESS_REC_ON (1L << 12) +#define VIDEO_PRESS_REC_OFF (1L << 13) +#define VIDEO_PRESS_REC (VIDEO_PRESS_REC_OFF | VIDEO_PRESS_REC_ON) +#define VIDEO_PRESS_PAUSE_ON (1L << 14) +#define VIDEO_PRESS_PAUSE_OFF (1L << 15) +#define VIDEO_PRESS_PAUSE (VIDEO_PRESS_PAUSE_OFF | VIDEO_PRESS_PAUSE_ON) +#define VIDEO_PRESS_STOP_ON (1L << 16) +#define VIDEO_PRESS_STOP_OFF (1L << 17) +#define VIDEO_PRESS_STOP (VIDEO_PRESS_STOP_OFF | VIDEO_PRESS_STOP_ON) +#define VIDEO_PRESS_EJECT_ON (1L << 18) +#define VIDEO_PRESS_EJECT_OFF (1L << 19) +#define VIDEO_PRESS_EJECT (VIDEO_PRESS_EJECT_OFF | VIDEO_PRESS_EJECT_ON) + +/* special */ +#define VIDEO_STATE_FFWD_OFF ((1L << 20) | VIDEO_STATE_PAUSE_OFF) +#define VIDEO_STATE_FFWD_ON (1L << 21) +#define VIDEO_STATE_FFWD (VIDEO_STATE_FFWD_OFF | VIDEO_STATE_FFWD_ON) +#define VIDEO_STATE_PBEND_OFF (1L << 22) +#define VIDEO_STATE_PBEND_ON (1L << 23) +#define VIDEO_STATE_PBEND (VIDEO_STATE_PBEND_OFF | VIDEO_STATE_PBEND_ON) + +/* tags to draw video display labels or symbols only */ +#define VIDEO_DISPLAY_DEFAULT 0 +#define VIDEO_DISPLAY_LABEL_ONLY 1 +#define VIDEO_DISPLAY_SYMBOL_ONLY 2 + +void DrawVideoDisplay(unsigned long, unsigned long); +void DrawCompleteVideoDisplay(void); + + +/* NEW GADGET STUFF -------------------------------------------------------- */ + +/* gadget types */ +#define GD_TYPE_NORMAL_BUTTON (1 << 0) +#define GD_TYPE_CHECK_BUTTON (1 << 1) +#define GD_TYPE_RADIO_BUTTON (1 << 2) +#define GD_TYPE_DRAWING_AREA (1 << 3) +#define GD_TYPE_TEXTINPUT_ALPHANUMERIC (1 << 4) +#define GD_TYPE_TEXTINPUT_NUMERIC (1 << 5) +#define GD_TYPE_SCROLLBAR_VERTICAL (1 << 6) +#define GD_TYPE_SCROLLBAR_HORIZONTAL (1 << 7) + +#define GD_TYPE_BUTTON (GD_TYPE_NORMAL_BUTTON | \ + GD_TYPE_CHECK_BUTTON | \ + GD_TYPE_RADIO_BUTTON) +#define GD_TYPE_SCROLLBAR (GD_TYPE_SCROLLBAR_VERTICAL | \ + GD_TYPE_SCROLLBAR_HORIZONTAL) +#define GD_TYPE_TEXTINPUT (GD_TYPE_TEXTINPUT_ALPHANUMERIC | \ + GD_TYPE_TEXTINPUT_NUMERIC) + +/* gadget events */ +#define GD_EVENT_PRESSED (1 << 0) +#define GD_EVENT_RELEASED (1 << 1) +#define GD_EVENT_MOVING (1 << 2) +#define GD_EVENT_REPEATED (1 << 3) +#define GD_EVENT_OFF_BORDERS (1 << 4) +#define GD_EVENT_TEXT_RETURN (1 << 5) +#define GD_EVENT_TEXT_LEAVING (1 << 6) + +/* gadget button states */ +#define GD_BUTTON_UNPRESSED 0 +#define GD_BUTTON_PRESSED 1 + +/* gadget structure constants */ +#define MAX_GADGET_TEXTSIZE 1024 +#define MAX_INFO_TEXTSIZE 1024 + +/* gadget creation tags */ +#define GDI_END 0 +#define GDI_CUSTOM_ID 1 +#define GDI_CUSTOM_TYPE_ID 2 +#define GDI_X 3 +#define GDI_Y 4 +#define GDI_WIDTH 5 +#define GDI_HEIGHT 6 +#define GDI_TYPE 7 +#define GDI_STATE 8 +#define GDI_CHECKED 9 +#define GDI_RADIO_NR 10 +#define GDI_NUMBER_VALUE 11 +#define GDI_NUMBER_MIN 12 +#define GDI_NUMBER_MAX 13 +#define GDI_TEXT_VALUE 14 +#define GDI_TEXT_SIZE 15 +#define GDI_TEXT_FONT 16 +#define GDI_DESIGN_UNPRESSED 17 +#define GDI_DESIGN_PRESSED 18 +#define GDI_ALT_DESIGN_UNPRESSED 19 +#define GDI_ALT_DESIGN_PRESSED 20 +#define GDI_BORDER_SIZE 21 +#define GDI_TEXTINPUT_DESIGN_WIDTH 22 +#define GDI_DECORATION_DESIGN 23 +#define GDI_DECORATION_POSITION 24 +#define GDI_DECORATION_SIZE 25 +#define GDI_DECORATION_SHIFTING 26 +#define GDI_EVENT_MASK 27 +#define GDI_EVENT 28 +#define GDI_CALLBACK_INFO 29 +#define GDI_CALLBACK_ACTION 30 +#define GDI_AREA_SIZE 31 +#define GDI_ITEM_SIZE 32 +#define GDI_SCROLLBAR_ITEMS_MAX 33 +#define GDI_SCROLLBAR_ITEMS_VISIBLE 34 +#define GDI_SCROLLBAR_ITEM_POSITION 35 +#define GDI_INFO_TEXT 36 + +typedef void (*gadget_function)(void *); + +struct GadgetBorder +{ + int size; /* size of gadget border */ + int width; /* for text input gadgets */ +}; + +struct GadgetDesign +{ + Bitmap bitmap; /* Bitmap with gadget surface */ + int x, y; /* position of rectangle in Bitmap */ +}; + +struct GadgetDecoration +{ + struct GadgetDesign design; /* decoration design structure */ + int x, y; /* position of deco on the gadget */ + int width, height; /* width and height of decoration */ + int xshift, yshift; /* deco shifting when gadget pressed */ +}; + +struct GadgetEvent +{ + unsigned long type; /* event type */ + int button; /* button number for button events */ + int x, y; /* gadget position at event time */ + boolean off_borders; /* mouse pointer outside gadget? */ + int item_x, item_y, item_position; /* new item position */ +}; + +struct GadgetDrawingArea +{ + int area_xsize, area_ysize; /* size of drawing area (in items) */ + int item_xsize, item_ysize; /* size of each item in drawing area */ +}; + +struct GadgetTextInput +{ + char value[MAX_GADGET_TEXTSIZE]; /* text string in input field */ + int number_value; /* integer value, if numeric */ + int number_min; /* minimal allowed numeric value */ + int number_max; /* maximal allowed numeric value */ + int size; /* maximal size of input text */ + int cursor_position; /* actual cursor position */ + int font_type; /* font to use for text input */ +}; + +struct GadgetScrollbar +{ + int items_max; /* number of items to access */ + int items_visible; /* number of visible items */ + int item_position; /* actual item position */ + int size_max; /* this is either width or height */ + int size; /* scrollbar size on screen */ + int position; /* scrollbar position on screen */ + int position_max; /* bottom/right scrollbar position */ + int drag_position; /* drag position on scrollbar */ + int correction; /* scrollbar position correction */ +}; + +struct GadgetInfo +{ + int id; /* internal gadget identifier */ + int custom_id; /* custom gadget identifier */ + int custom_type_id; /* custom gadget type identifier */ + char info_text[MAX_INFO_TEXTSIZE]; /* short popup info text */ + int x, y; /* gadget position */ + int width, height; /* gadget size */ + unsigned long type; /* type (button, text input, ...) */ + unsigned long state; /* state (pressed, released, ...) */ + boolean checked; /* check/radio button state */ + int radio_nr; /* number of radio button series */ + boolean mapped; /* gadget is active */ + struct GadgetBorder border; /* gadget border design */ + struct GadgetDesign design[2]; /* 0: normal; 1: pressed */ + struct GadgetDesign alt_design[2]; /* alternative design */ + struct GadgetDecoration deco; /* decoration on top of gadget */ + unsigned long event_mask; /* possible events for this gadget */ + struct GadgetEvent event; /* actual gadget event */ + gadget_function callback_info; /* function for pop-up info text */ + gadget_function callback_action; /* function for gadget action */ + struct GadgetDrawingArea drawing; /* fields for drawing area gadget */ + struct GadgetTextInput text; /* fields for text input gadget */ + struct GadgetScrollbar scrollbar; /* fields for scrollbar gadget */ + struct GadgetInfo *next; /* next list entry */ +}; + +struct GadgetInfo *CreateGadget(int, ...); +void FreeGadget(struct GadgetInfo *); + +void ModifyGadget(struct GadgetInfo *, int, ...); +void RedrawGadget(struct GadgetInfo *); + +void MapGadget(struct GadgetInfo *); +void UnmapGadget(struct GadgetInfo *); +void UnmapAllGadgets(); +void RemapAllGadgets(); + +boolean anyTextGadgetActive(); +void ClickOnGadget(struct GadgetInfo *, int); + +void HandleGadgets(int, int, int); +void HandleGadgetsKeyInput(Key); + +#endif /* GADGETS_H */ diff --git a/src/libgame/image.c b/src/libgame/image.c index 9dd4c249..b83de19f 100644 --- a/src/libgame/image.c +++ b/src/libgame/image.c @@ -11,6 +11,8 @@ * image.c * ***********************************************************/ +#include "platform.h" + #if defined(TARGET_X11) #include "image.h" diff --git a/src/libgame/image.h b/src/libgame/image.h index 4f55fe3a..1257dda1 100644 --- a/src/libgame/image.h +++ b/src/libgame/image.h @@ -18,8 +18,13 @@ #ifndef TARGET_SDL +#include "types.h" +#include "system.h" + +/* #include "types.h" #include "x11.h" +*/ #define MAX_COLORS 256 /* maximal number of colors for each image */ diff --git a/src/libgame/libgame.h b/src/libgame/libgame.h index b2af1408..95dba9b3 100644 --- a/src/libgame/libgame.h +++ b/src/libgame/libgame.h @@ -19,7 +19,7 @@ #include "private.h" #include "system.h" #include "random.h" -#include "buttons.h" +#include "gadgets.h" #include "text.h" #include "sound.h" #include "image.h" diff --git a/src/libgame/misc.c b/src/libgame/misc.c index 29e23929..572ff360 100644 --- a/src/libgame/misc.c +++ b/src/libgame/misc.c @@ -17,6 +17,8 @@ #include #include +#include "libgame.h" + #if !defined(PLATFORM_WIN32) #include #include diff --git a/src/libgame/msdos.c b/src/libgame/msdos.c index cc8aedd7..782369c1 100644 --- a/src/libgame/msdos.c +++ b/src/libgame/msdos.c @@ -16,6 +16,8 @@ #if defined(PLATFORM_MSDOS) +#define AllegroDefaultScreen() (display->screens[display->default_screen]) + /* allegro driver declarations */ DECLARE_GFX_DRIVER_LIST(GFX_DRIVER_VBEAF GFX_DRIVER_VESA2L GFX_DRIVER_VESA1) DECLARE_COLOR_DEPTH_LIST(COLOR_DEPTH_8) @@ -238,10 +240,10 @@ void XMapWindow(Display *display, Window window) unsigned int width, height; boolean mouse_off; - x = display->screens[display->default_screen].x; - y = display->screens[display->default_screen].y; - width = display->screens[display->default_screen].width; - height = display->screens[display->default_screen].height; + x = AllegroDefaultScreen().x; + y = AllegroDefaultScreen().y; + width = AllegroDefaultScreen().width; + height = AllegroDefaultScreen().height; mouse_off = hide_mouse(display, x, y, width, height); blit((BITMAP *)window, video_bitmap, 0, 0, x, y, width, height); @@ -291,14 +293,8 @@ Display *XOpenDisplay(char *display_name) Screen *screen; Display *display; BITMAP *mouse_bitmap = NULL; - char *filename; - - filename = getPath3(options.ro_base_directory, GRAPHICS_DIRECTORY, - MOUSE_FILENAME); - - mouse_bitmap = Read_PCX_to_AllegroBitmap(filename); - free(filename); + mouse_bitmap = Read_PCX_to_AllegroBitmap(program.msdos_pointer_filename); if (mouse_bitmap == NULL) return NULL; @@ -340,11 +336,11 @@ Window XCreateSimpleWindow(Display *display, Window parent, int x, int y, video_bitmap = create_video_bitmap(XRES, YRES); clear_to_color(video_bitmap, background); - display->screens[display->default_screen].video_bitmap = video_bitmap; - display->screens[display->default_screen].x = x; - display->screens[display->default_screen].y = y; - display->screens[display->default_screen].width = XRES; - display->screens[display->default_screen].height = YRES; + AllegroDefaultScreen().video_bitmap = video_bitmap; + AllegroDefaultScreen().x = x; + AllegroDefaultScreen().y = y; + AllegroDefaultScreen().width = XRES; + AllegroDefaultScreen().height = YRES; set_mouse_sprite(display->mouse_ptr); @@ -353,10 +349,10 @@ Window XCreateSimpleWindow(Display *display, Window parent, int x, int y, #endif set_mouse_speed(1, 1); - set_mouse_range(display->screens[display->default_screen].x + 1, - display->screens[display->default_screen].y + 1, - display->screens[display->default_screen].x + WIN_XSIZE + 1, - display->screens[display->default_screen].y + WIN_YSIZE + 1); + set_mouse_range(AllegroDefaultScreen().x + 1, + AllegroDefaultScreen().y + 1, + AllegroDefaultScreen().x + video.width + 1, + AllegroDefaultScreen().y + video.height + 1); show_video_bitmap(video_bitmap); @@ -425,8 +421,8 @@ void XFillRectangle(Display *display, Drawable d, GC gc, int x, int y, if ((BITMAP *)d == video_bitmap) { - x += display->screens[display->default_screen].x; - y += display->screens[display->default_screen].y; + x += AllegroDefaultScreen().x; + y += AllegroDefaultScreen().y; freeze_mouse_flag = TRUE; mouse_off = hide_mouse(display, x, y, width, height); } @@ -446,7 +442,7 @@ Pixmap XCreatePixmap(Display *display, Drawable d, unsigned int width, BITMAP *bitmap = NULL; if (gfx_capabilities & GFX_HW_VRAM_BLIT && - width == FXSIZE && height == FYSIZE) + width == video.scrollbuffer_width && height == video.scrollbuffer_height) bitmap = create_video_bitmap(width, height); if (bitmap == NULL) @@ -469,14 +465,14 @@ inline void XCopyArea(Display *display, Drawable src, Drawable dest, GC gc, if ((BITMAP *)src == video_bitmap) { - src_x += display->screens[display->default_screen].x; - src_y += display->screens[display->default_screen].y; + src_x += AllegroDefaultScreen().x; + src_y += AllegroDefaultScreen().y; } if ((BITMAP *)dest == video_bitmap) { - dest_x += display->screens[display->default_screen].x; - dest_y += display->screens[display->default_screen].y; + dest_x += AllegroDefaultScreen().x; + dest_y += AllegroDefaultScreen().y; freeze_mouse_flag = TRUE; mouse_off = hide_mouse(display, dest_x, dest_y, width, height); } @@ -812,8 +808,8 @@ int XPending(Display *display) pending_events++; xmotion = (XMotionEvent *)&event_buffer[pending_events]; xmotion->type = MotionNotify; - xmotion->x = mouse_x - display->screens[display->default_screen].x; - xmotion->y = mouse_y - display->screens[display->default_screen].y; + xmotion->x = mouse_x - AllegroDefaultScreen().x; + xmotion->y = mouse_y - AllegroDefaultScreen().y; } /* mouse button event */ @@ -831,8 +827,8 @@ int XPending(Display *display) xbutton = (XButtonEvent *)&event_buffer[pending_events]; xbutton->type = (mouse_b & bitmask ? ButtonPress : ButtonRelease); xbutton->button = mapping[i]; - xbutton->x = mouse_x - display->screens[display->default_screen].x; - xbutton->y = mouse_y - display->screens[display->default_screen].y; + xbutton->x = mouse_x - AllegroDefaultScreen().x; + xbutton->y = mouse_y - AllegroDefaultScreen().y; } } last_mouse_b = mouse_b; @@ -868,10 +864,10 @@ void XDrawLine(Display *display, Drawable d, GC gc, if ((BITMAP *)d == video_bitmap) { - x1 += display->screens[display->default_screen].x; - y1 += display->screens[display->default_screen].y; - x2 += display->screens[display->default_screen].x; - y2 += display->screens[display->default_screen].y; + x1 += AllegroDefaultScreen().x; + y1 += AllegroDefaultScreen().y; + x2 += AllegroDefaultScreen().x; + y2 += AllegroDefaultScreen().y; freeze_mouse_flag = TRUE; mouse_off = hide_mouse(display, MIN(x1, x2), MIN(y1, y2), MAX(x1, x2) - MIN(x1, x2), @@ -894,8 +890,8 @@ Bool XQueryPointer(Display *display, Window window, Window *root, Window *child, int *root_x, int *root_y, int *win_x, int *win_y, unsigned int *mask) { - *win_x = mouse_x - display->screens[display->default_screen].x; - *win_y = mouse_y - display->screens[display->default_screen].y; + *win_x = mouse_x - AllegroDefaultScreen().x; + *win_y = mouse_y - AllegroDefaultScreen().y; return True; } @@ -916,7 +912,7 @@ boolean MSDOSOpenAudio(void) return allegro_init_audio(); } -boolean MSDOSCloseAudio(void) +void MSDOSCloseAudio(void) { /* nothing to be done here */ } diff --git a/src/libgame/msdos.h b/src/libgame/msdos.h index 26a3f791..12b0bb6d 100644 --- a/src/libgame/msdos.h +++ b/src/libgame/msdos.h @@ -447,7 +447,6 @@ /* end of X11 keyboard mapping */ -#define MOUSE_FILENAME "mouse.pcx" #define JOYSTICK_FILENAME "joystick.cnf" #define screen myscreen @@ -705,7 +704,7 @@ void XAutoRepeatOn(Display *); void XAutoRepeatOff(Display *); boolean MSDOSOpenAudio(void); -boolean MSDOSCloseAudio(void); +void MSDOSCloseAudio(void); void NetworkServer(int, int); diff --git a/src/libgame/sdl.c b/src/libgame/sdl.c index edb861d9..e732b111 100644 --- a/src/libgame/sdl.c +++ b/src/libgame/sdl.c @@ -53,7 +53,7 @@ inline void SDLInitVideoBuffer(DrawBuffer *backbuffer, DrawWindow *window, should never be drawn to directly, it would do no harm nevertheless. */ /* create additional (symbolic) buffer for double-buffering */ - *window = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH); + *window = CreateBitmap(video.width, video.height, video.depth); } inline boolean SDLSetVideoMode(DrawBuffer *backbuffer, boolean fullscreen) diff --git a/src/libgame/sdl.h b/src/libgame/sdl.h index a7147130..768dc6fa 100644 --- a/src/libgame/sdl.h +++ b/src/libgame/sdl.h @@ -297,7 +297,7 @@ typedef int Colormap; /* SDL function definitions */ inline void SDLInitVideoDisplay(void); -inline void SDLInitVideoBuffer(DrawBuffer *, DrawWindow *); +inline void SDLInitVideoBuffer(DrawBuffer *, DrawWindow *, boolean); inline boolean SDLSetVideoMode(DrawBuffer *, boolean); inline void SDLCopyArea(SDL_Surface *, SDL_Surface *, int, int, int, int, int, int); diff --git a/src/libgame/sound.h b/src/libgame/sound.h index 199ef755..238a5b19 100644 --- a/src/libgame/sound.h +++ b/src/libgame/sound.h @@ -14,9 +14,12 @@ #ifndef SOUND_H #define SOUND_H -#include #include +#if defined(PLATFORM_LINUX) +#include +#endif + #define SND_BLOCKSIZE 4096 #if defined(PLATFORM_LINUX) diff --git a/src/libgame/system.c b/src/libgame/system.c index ee5e87ce..3d26c3ce 100644 --- a/src/libgame/system.c +++ b/src/libgame/system.c @@ -14,20 +14,20 @@ #include "libgame.h" - /* ========================================================================= */ /* internal variables */ /* ========================================================================= */ -Display *display; -Visual *visual; -int screen; -Colormap cmap; +Display *display = NULL; +Visual *visual = NULL; +int screen = 0; +Colormap cmap = None; DrawWindow window = None; -GC gc; +DrawBuffer backbuffer = None; +GC gc = None; -int FrameCounter; +int FrameCounter = 0; /* ========================================================================= */ @@ -52,7 +52,8 @@ inline static int GetRealDepth(int depth) inline void InitProgramInfo(char *command_name, char *program_title, char *window_title, char *icon_title, char *x11_icon_filename, - char *x11_iconmask_filename) + char *x11_iconmask_filename, + char *msdos_pointer_filename) { program.command_name = command_name; program.program_title = program_title; @@ -60,6 +61,15 @@ inline void InitProgramInfo(char *command_name, char *program_title, program.icon_title = icon_title; program.x11_icon_filename = x11_icon_filename; program.x11_iconmask_filename = x11_iconmask_filename; + program.msdos_pointer_filename = msdos_pointer_filename; +} + +inline void InitScrollbufferSize(int scrollbuffer_width, + int scrollbuffer_height) +{ + /* currently only used by MSDOS code to alloc VRAM buffer, if available */ + video.scrollbuffer_width = scrollbuffer_width; + video.scrollbuffer_height = scrollbuffer_height; } inline void InitVideoDisplay(void) @@ -274,7 +284,7 @@ inline boolean ChangeVideoModeIfNeeded(boolean fullscreen) #ifdef TARGET_SDL if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)|| (!fullscreen && video.fullscreen_enabled)) - fullscreen = SetVideoMode(fullscreen_wanted); + fullscreen = SetVideoMode(fullscreen); #endif return fullscreen; diff --git a/src/libgame/system.h b/src/libgame/system.h index 5b9a1ef5..808f752d 100644 --- a/src/libgame/system.h +++ b/src/libgame/system.h @@ -15,7 +15,9 @@ #ifndef SYSTEM_H #define SYSTEM_H +/* #include "libgame.h" +*/ #if defined(PLATFORM_MSDOS) #include "msdos.h" @@ -51,12 +53,14 @@ struct ProgramInfo char *icon_title; char *x11_icon_filename; char *x11_iconmask_filename; + char *msdos_pointer_filename; }; struct VideoSystemInfo { int default_depth; int width, height, depth; + int scrollbuffer_width, scrollbuffer_height; boolean fullscreen_available; boolean fullscreen_enabled; }; @@ -104,6 +108,7 @@ extern int screen; extern Colormap cmap; extern DrawWindow window; +extern DrawBuffer backbuffer; extern GC gc; extern int FrameCounter; @@ -111,7 +116,9 @@ extern int FrameCounter; /* function definitions */ -inline void InitProgramInfo(char *, char *, char *, char *, char *, char *); +inline void InitProgramInfo(char *, char *, char *, char *, char *, char *, + char *); +inline void InitScrollbufferSize(int, int); inline void InitVideoDisplay(void); inline void InitVideoBuffer(DrawBuffer *,DrawWindow *, int, int, int, boolean); inline Bitmap CreateBitmap(int, int, int); diff --git a/src/libgame/x11.c b/src/libgame/x11.c index 5d77d49d..4f0a25e4 100644 --- a/src/libgame/x11.c +++ b/src/libgame/x11.c @@ -16,18 +16,6 @@ #if defined(TARGET_X11) -#if 0 -#include "main_TMP.h" -#endif - -#if 0 -struct IconFileInfo -{ - char *picture_filename; - char *picturemask_filename; -}; -#endif - static void X11InitDisplay(); static DrawWindow X11InitWindow(); diff --git a/src/main.c b/src/main.c index 8bf9e775..92e8b38a 100644 --- a/src/main.c +++ b/src/main.c @@ -25,6 +25,7 @@ #if 0 DrawWindow window = None; +DrawBuffer backbuffer; GC gc; #endif @@ -33,7 +34,7 @@ Bitmap pix[NUM_BITMAPS]; Bitmap pix_masked[NUM_BITMAPS], tile_masked[NUM_TILES]; Pixmap clipmask[NUM_BITMAPS], tile_clipmask[NUM_TILES]; -DrawBuffer drawto, drawto_field, backbuffer, fieldbuffer; +DrawBuffer drawto, drawto_field, fieldbuffer; #if 0 Colormap cmap; #endif diff --git a/src/main.h b/src/main.h index 9eb316c2..f2ce895c 100644 --- a/src/main.h +++ b/src/main.h @@ -437,6 +437,7 @@ struct GlobalInfo #if 0 extern DrawWindow window; +extern DrawBuffer backbuffer; extern GC gc; #endif @@ -445,7 +446,7 @@ extern Bitmap pix[]; extern Bitmap pix_masked[], tile_masked[]; extern Pixmap clipmask[], tile_clipmask[]; -extern DrawBuffer drawto, drawto_field, backbuffer, fieldbuffer; +extern DrawBuffer drawto, drawto_field, fieldbuffer; #if 0 extern Colormap cmap; #endif @@ -1667,6 +1668,10 @@ extern int num_element_info; #define WINDOW_SUBTITLE_STRING PROGRAM_RIGHTS_STRING " " PROGRAM_AUTHOR_STRING #define ICON_TITLE_STRING PROGRAM_TITLE_STRING +#define X11_ICON_FILENAME "rocks_icon.xbm" +#define X11_ICONMASK_FILENAME "rocks_iconmask.xbm" +#define MSDOS_POINTER_FILENAME "mouse.pcx" + /* default name for empty highscore entry */ #define EMPTY_PLAYER_NAME "no name"