From 6ed4958820f8f97174ca47594dcc6f00ee31b2cb Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Thu, 3 Apr 2003 21:09:11 +0200 Subject: [PATCH] rnd-20030403-2-src --- Makefile | 4 +- src/conftime.h | 2 +- src/editor.c | 14 +- src/init.c | 11 +- src/libgame/gadgets.c | 453 +++++++++++++++++++++++++++++++++++------- src/libgame/gadgets.h | 11 + src/libgame/system.c | 31 ++- src/libgame/system.h | 5 +- src/libgame/text.c | 42 +++- src/libgame/text.h | 2 + 10 files changed, 485 insertions(+), 90 deletions(-) diff --git a/Makefile b/Makefile index ea7b1525..a5b3d976 100644 --- a/Makefile +++ b/Makefile @@ -49,8 +49,8 @@ CROSS_PATH_WIN32=/usr/local/cross-tools/i386-mingw32msvc SRC_DIR = src MAKE_CMD = $(MAKE) -C $(SRC_DIR) -# DEFAULT_TARGET = x11 -DEFAULT_TARGET = sdl +DEFAULT_TARGET = x11 +# DEFAULT_TARGET = sdl all: @$(MAKE_CMD) TARGET=$(DEFAULT_TARGET) diff --git a/src/conftime.h b/src/conftime.h index c71f530c..8f9e2ea2 100644 --- a/src/conftime.h +++ b/src/conftime.h @@ -1 +1 @@ -#define COMPILE_DATE_STRING "[2003-04-03 02:41]" +#define COMPILE_DATE_STRING "[2003-04-03 21:08]" diff --git a/src/editor.c b/src/editor.c index 00cda340..2b9a9088 100644 --- a/src/editor.c +++ b/src/editor.c @@ -573,7 +573,8 @@ static char *test_values[] = "test 1", "test 2", "dieser test-text ist viel zu lang fuer die selectbox", - "letzter text" + "letzter text", + NULL }; static int test_index = 0; @@ -2216,7 +2217,8 @@ static void CreateSelectboxGadgets() char infotext[MAX_OUTPUT_LINESIZE + 1]; int id = selectbox_info[i].gadget_id; - event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING; + event_mask = GD_EVENT_RELEASED | + GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING; gd_x = DOOR_GFX_PAGEX4 + ED_SELECTBOX_XPOS; gd_y = DOOR_GFX_PAGEY1 + ED_SELECTBOX_YPOS; @@ -3395,8 +3397,8 @@ static void DrawLine(int from_x, int from_y, int to_x, int to_y, } } -static void DrawRectangle(int from_x, int from_y, int to_x, int to_y, - int element, boolean change_level) +static void DrawBox(int from_x, int from_y, int to_x, int to_y, + int element, boolean change_level) { DrawLine(from_x, from_y, from_x, to_y, element, change_level); DrawLine(from_x, to_y, to_x, to_y, element, change_level); @@ -3518,7 +3520,7 @@ static void SelectArea(int from_x, int from_y, int to_x, int to_y, int element, boolean change_level) { if (element == -1 || change_level) - DrawRectangle(from_x, from_y, to_x, to_y, -1, FALSE); + DrawBox(from_x, from_y, to_x, to_y, -1, FALSE); else DrawAreaBorder(from_x, from_y, to_x, to_y); } @@ -4098,7 +4100,7 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) else if (drawing_function == GADGET_ID_ARC) draw_func = DrawArc; else if (drawing_function == GADGET_ID_RECTANGLE) - draw_func = DrawRectangle; + draw_func = DrawBox; else if (drawing_function == GADGET_ID_FILLED_BOX) draw_func = DrawFilledBox; else if (drawing_function == GADGET_ID_GRAB_BRUSH) diff --git a/src/init.c b/src/init.c index 9b57d1b0..e766a52d 100644 --- a/src/init.c +++ b/src/init.c @@ -2539,17 +2539,18 @@ void InitGfx() if (filename_font_initial == NULL) /* should not happen */ Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL); + /* create additional image buffers for double-buffering */ + bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH); + bitmap_db_door = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH); + /* initialize screen properties */ InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE, - REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE); + REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, + bitmap_db_field); InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE); InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE); InitGfxScrollbufferInfo(FXSIZE, FYSIZE); - /* create additional image buffers for double-buffering */ - bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH); - bitmap_db_door = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH); - bitmap_font_initial = LoadCustomImage(filename_font_initial); for (j=0; j < NUM_INITIAL_FONTS; j++) diff --git a/src/libgame/gadgets.c b/src/libgame/gadgets.c index 00f54c6f..45744a8c 100644 --- a/src/libgame/gadgets.c +++ b/src/libgame/gadgets.c @@ -85,9 +85,12 @@ static struct GadgetInfo *getGadgetInfoFromMousePosition(int mx, int my) while (gi) { if (gi->mapped && - mx >= gi->x && mx < gi->x + gi->width && - my >= gi->y && my < gi->y + gi->height) - break; + ((mx >= gi->x && mx < gi->x + gi->width && + my >= gi->y && my < gi->y + gi->height) || + (gi->type & GD_TYPE_SELECTBOX && gi->selectbox.open && + mx >= gi->selectbox.x && mx < gi->selectbox.x+gi->selectbox.width && + my >= gi->selectbox.y && my < gi->selectbox.y+gi->selectbox.height))) + break; gi = gi->next; } @@ -111,6 +114,7 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct) struct GadgetDesign *gd = (gi->checked ? &gi->alt_design[state] : &gi->design[state]); + boolean redraw_selectbox = FALSE; switch (gi->type) { @@ -139,15 +143,12 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct) int font_width = getFontWidth(font_type); int border = gi->border.size; - strcpy(text, gi->text.value); - strcat(text, " "); - /* left part of gadget */ BlitBitmapOnBackground(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++) + for (i=0; i < gi->text.size + 1; i++) BlitBitmapOnBackground(gd->bitmap, drawto, gd->x + border, gd->y, font_width, gi->height, gi->x + border + i * font_width, gi->y); @@ -157,6 +158,10 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct) gd->x + gi->border.width - border, gd->y,border, gi->height, gi->x + gi->width - border, gi->y); + /* set text value */ + strcpy(text, gi->text.value); + strcat(text, " "); + /* gadget text value */ DrawTextExt(drawto, gi->x + border, gi->y + border, text, @@ -182,20 +187,19 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct) char text[MAX_GADGET_TEXTSIZE + 1]; int font_type = gi->selectbox.font_type; int font_width = getFontWidth(font_type); + int font_height = getFontHeight(font_type); int border = gi->border.size; int button = gi->border.size_selectbutton; int width_inner = gi->border.width - button - 2 * border; - - strncpy(text, gi->selectbox.values[gi->selectbox.index], - MAX_GADGET_TEXTSIZE); - text[MAX_GADGET_TEXTSIZE] = '\0'; + int box_width = gi->selectbox.width; + int box_height = gi->selectbox.height; /* left part of gadget */ BlitBitmapOnBackground(gd->bitmap, drawto, gd->x, gd->y, border, gi->height, gi->x, gi->y); /* middle part of gadget */ - for (i=0; i <= gi->selectbox.size; i++) + for (i=0; i < gi->selectbox.size; i++) BlitBitmapOnBackground(gd->bitmap, drawto, gd->x + border, gd->y, font_width, gi->height, gi->x + border + i * font_width, gi->y); @@ -211,10 +215,154 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct) gd->x + gi->border.width - border, gd->y,border, gi->height, gi->x + gi->width - border, gi->y); + /* set text value */ + strncpy(text, gi->selectbox.values[gi->selectbox.index], + gi->selectbox.size); + text[gi->selectbox.size] = '\0'; + /* gadget text value */ - DrawTextExt(drawto, - gi->x + border, gi->y + border, text, + DrawTextExt(drawto, gi->x + border, gi->y + border, text, font_type, FONT_MASKED); + + if (pressed) + { + if (!gi->selectbox.open) + { + gi->selectbox.open = TRUE; + gi->selectbox.stay_open = FALSE; + gi->selectbox.current_index = gi->selectbox.index; + + /* save background under selectbox */ + BlitBitmap(drawto, gfx.field_save_buffer, + gi->selectbox.x, gi->selectbox.y, + gi->selectbox.width, gi->selectbox.height, + gi->selectbox.x, gi->selectbox.y); + } + + /* draw open selectbox */ + + /* top left part of gadget border */ + BlitBitmapOnBackground(gd->bitmap, drawto, gd->x, gd->y, + border, border, + gi->selectbox.x, gi->selectbox.y); + + /* top middle part of gadget border */ + for (i=0; i < gi->selectbox.size; i++) + BlitBitmapOnBackground(gd->bitmap, drawto, gd->x + border, gd->y, + font_width, border, + gi->selectbox.x + border + i * font_width, + gi->selectbox.y); + + /* top button part of gadget border */ + BlitBitmapOnBackground(gd->bitmap, drawto, + gd->x + border + width_inner, gd->y, + button, border, + gi->selectbox.x + box_width - border - button, + gi->selectbox.y); + + /* top right part of gadget border */ + BlitBitmapOnBackground(gd->bitmap, drawto, + gd->x + gi->border.width - border, gd->y, + border, border, + gi->selectbox.x + box_width - border, + gi->selectbox.y); + + /* left and right part of gadget border for each row */ + for (i=0; i < gi->selectbox.num_values; i++) + { + BlitBitmapOnBackground(gd->bitmap, drawto, gd->x, gd->y + border, + border, font_height, + gi->selectbox.x, + gi->selectbox.y + border + i * font_height); + BlitBitmapOnBackground(gd->bitmap, drawto, + gd->x + gi->border.width - border, + gd->y + border, + border, font_height, + gi->selectbox.x + box_width - border, + gi->selectbox.y + border + i * font_height); + } + + /* bottom left part of gadget border */ + BlitBitmapOnBackground(gd->bitmap, drawto, + gd->x, gd->y + gi->height - border, + border, border, + gi->selectbox.x, + gi->selectbox.y + box_height - border); + + /* bottom middle part of gadget border */ + for (i=0; i < gi->selectbox.size; i++) + BlitBitmapOnBackground(gd->bitmap, drawto, + gd->x + border, gd->y + gi->height - border, + font_width, border, + gi->selectbox.x + border + i * font_width, + gi->selectbox.y + box_height - border); + + /* bottom button part of gadget border */ + BlitBitmapOnBackground(gd->bitmap, drawto, + gd->x + border + width_inner, + gd->y + gi->height - border, + button, border, + gi->selectbox.x + box_width - border - button, + gi->selectbox.y + box_height - border); + + /* bottom right part of gadget border */ + BlitBitmapOnBackground(gd->bitmap, drawto, + gd->x + gi->border.width - border, + gd->y + gi->height - border, + border, border, + gi->selectbox.x + box_width - border, + gi->selectbox.y + box_height - border); + + ClearRectangleOnBackground(drawto, + gi->selectbox.x + border, + gi->selectbox.y + border, + gi->selectbox.width - 2 * border, + gi->selectbox.height - 2 * border); + + /* selectbox text values */ + for (i=0; i < gi->selectbox.num_values; i++) + { + if (i == gi->selectbox.current_index) + { + DrawRectangle(drawto, + gi->selectbox.x + border, + gi->selectbox.y + border + i * font_height, + gi->selectbox.width - 2 * border, font_height, + gi->selectbox.reverse_color); + + text[0] = '~'; + strncpy(&text[1], gi->selectbox.values[i], gi->selectbox.size); + text[1 + gi->selectbox.size] = '\0'; + } + else + { + strncpy(text, gi->selectbox.values[i], gi->selectbox.size); + text[gi->selectbox.size] = '\0'; + } + + DrawTextExt(drawto, + gi->selectbox.x + border, + gi->selectbox.y + border + i * font_height, text, + font_type, FONT_MASKED); + } + + redraw_selectbox = TRUE; + } + else if (gi->selectbox.open) + { + gi->selectbox.open = FALSE; + + /* redraw closed selectbox */ + DrawGadget(gi, FALSE, FALSE); + + /* restore background under selectbox */ + BlitBitmap(gfx.field_save_buffer, drawto, + gi->selectbox.x, gi->selectbox.y, + gi->selectbox.width, gi->selectbox.height, + gi->selectbox.x, gi->selectbox.y); + + redraw_selectbox = TRUE; + } } break; @@ -317,8 +465,16 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct) } if (direct) + { BlitBitmap(drawto, window, gi->x, gi->y, gi->width, gi->height, gi->x, gi->y); + + if (gi->type == GD_TYPE_SELECTBOX && redraw_selectbox) + BlitBitmap(drawto, window, + gi->selectbox.x, gi->selectbox.y, + gi->selectbox.width, gi->selectbox.height, + gi->selectbox.x, gi->selectbox.y); + } else redraw_mask |= (gi->x < gfx.sx + gfx.sxsize ? REDRAW_FIELD : gi->y < gfx.dy + gfx.dysize ? REDRAW_DOOR_1 : @@ -600,13 +756,44 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap) if (gi->type & GD_TYPE_SELECTBOX) { + int font_nr = gi->selectbox.font_type; + int font_bitmap_id = gfx.select_font_function(font_nr); + struct FontBitmapInfo *font = &gfx.font_bitmap_info[font_bitmap_id]; int font_width = getFontWidth(gi->selectbox.font_type); int font_height = getFontHeight(gi->selectbox.font_type); int border_size = gi->border.size; int button_size = gi->border.size_selectbutton; + int src_x, src_y; gi->width = 2 * border_size + gi->text.size * font_width + button_size; gi->height = 2 * border_size + font_height; + + if (gi->selectbox.values == NULL) + Error(ERR_EXIT, "selectbox gadget incomplete (missing values array)"); + + gi->selectbox.num_values = 0; + while (gi->selectbox.values[gi->selectbox.num_values] != NULL) + gi->selectbox.num_values++; + + /* calculate values for open selectbox */ + gi->selectbox.width = gi->width; + gi->selectbox.height = + 2 * border_size + gi->selectbox.num_values * font_height; + + gi->selectbox.x = gi->x; + gi->selectbox.y = gi->y + gi->height; + if (gi->selectbox.y + gi->selectbox.height > gfx.real_sy + gfx.full_sysize) + gi->selectbox.y = gi->y - gi->selectbox.height; + if (gi->selectbox.y < 0) + gi->selectbox.y = gfx.real_sy + gfx.full_sysize - gi->selectbox.height; + + if (!getFontChar(font_nr, '|', &src_x, &src_y)) + Error(ERR_EXIT, "selectbox gadget incomplete (cannot get cursor)"); + + gi->selectbox.reverse_color = GetPixel(font->bitmap, src_x, src_y); + + /* always start with closed selectbox */ + gi->selectbox.open = FALSE; } if (gi->type & GD_TYPE_TEXTINPUT_NUMERIC) @@ -809,9 +996,19 @@ void RemapAllGadgets() MultiMapGadgets(MULTIMAP_ALL | MULTIMAP_REMAP); } +boolean anyTextInputGadgetActive() +{ + return (last_gi && (last_gi->type & GD_TYPE_TEXTINPUT) && last_gi->mapped); +} + +boolean anySelectboxGadgetActive() +{ + return (last_gi && (last_gi->type & GD_TYPE_SELECTBOX) && last_gi->mapped); +} + boolean anyTextGadgetActive() { - return (last_gi && last_gi->type & GD_TYPE_TEXTINPUT && last_gi->mapped); + return (anyTextInputGadgetActive() || anySelectboxGadgetActive()); } void ClickOnGadget(struct GadgetInfo *gi, int button) @@ -845,6 +1042,8 @@ void HandleGadgets(int mx, int my, int button) boolean gadget_moving_off_borders; boolean gadget_released; boolean gadget_released_inside; + boolean gadget_released_inside_select_line; + boolean gadget_released_inside_select_area; boolean gadget_released_off_borders; boolean changed_position = FALSE; @@ -866,23 +1065,25 @@ void HandleGadgets(int mx, int my, int button) last_my = my; /* special treatment for text and number input gadgets */ - if (anyTextGadgetActive() && button != 0 && !motion_status) + if (anyTextInputGadgetActive() && button != 0 && !motion_status) { struct GadgetInfo *gi = last_gi; if (new_gi == last_gi) { + int old_cursor_position = gi->text.cursor_position; + /* if mouse button pressed inside activated text gadget, set cursor */ gi->text.cursor_position = - (mx - gi->x - gi->border.size) / - getFontWidth(gi->text.font_type); + (mx - gi->x - gi->border.size) / getFontWidth(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); + if (gi->text.cursor_position != old_cursor_position) + DrawGadget(gi, DG_PRESSED, DG_DIRECT); } else { @@ -899,6 +1100,43 @@ void HandleGadgets(int mx, int my, int button) } } + /* special treatment for selectbox gadgets */ + if (anySelectboxGadgetActive() && button != 0 && !motion_status) + { + struct GadgetInfo *gi = last_gi; + + if (new_gi == last_gi) + { + int old_index = gi->selectbox.current_index; + + /* if mouse button pressed inside activated selectbox, select value */ + if (my >= gi->selectbox.y && my < gi->selectbox.y + gi->selectbox.height) + gi->selectbox.current_index = + (my - gi->selectbox.y - gi->border.size) / + getFontWidth(gi->selectbox.font_type); + + if (gi->selectbox.current_index < 0) + gi->selectbox.current_index = 0; + else if (gi->selectbox.current_index > gi->selectbox.num_values - 1) + gi->selectbox.current_index = gi->selectbox.num_values - 1; + + if (gi->selectbox.current_index != old_index) + DrawGadget(gi, DG_PRESSED, DG_DIRECT); + } + else + { + /* if mouse button pressed outside selectbox gadget, deactivate it */ + 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 = @@ -912,6 +1150,24 @@ void HandleGadgets(int mx, int my, int button) gadget_moving_inside = (gadget_moving && new_gi == last_gi); gadget_moving_off_borders = (gadget_moving && new_gi != last_gi); + /* when handling selectbox, set additional state values */ + if (gadget_released_inside && (last_gi->type & GD_TYPE_SELECTBOX)) + { + struct GadgetInfo *gi = last_gi; + + gadget_released_inside_select_line = + (mx >= gi->x && mx < gi->x + gi->width && + my >= gi->y && my < gi->y + gi->height); + gadget_released_inside_select_area = + (mx >= gi->selectbox.x && mx < gi->selectbox.x+gi->selectbox.width && + my >= gi->selectbox.y && my < gi->selectbox.y+gi->selectbox.height); + } + else + { + gadget_released_inside_select_line = FALSE; + gadget_released_inside_select_area = FALSE; + } + /* if new gadget pressed, store this gadget */ if (gadget_pressed) last_gi = new_gi; @@ -925,8 +1181,15 @@ void HandleGadgets(int mx, int my, int button) (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; + if (gadget_released) + { + if ((last_gi->type & GD_TYPE_SELECTBOX) && + (gadget_released_inside_select_line || + gadget_released_off_borders)) /* selectbox stays open */ + gi->selectbox.stay_open = TRUE; + else if (!(last_gi->type & GD_TYPE_TEXTINPUT)) /* text input stays open */ + last_gi = NULL; + } /* modify event position values even if no gadget is pressed */ if (button == 0 && !release_event) @@ -1097,8 +1360,25 @@ void HandleGadgets(int mx, int my, int button) else if (gadget_moving_off_borders && gi->state == GD_BUTTON_PRESSED) DrawGadget(gi, DG_UNPRESSED, DG_DIRECT); } + else if (gi->type & GD_TYPE_SELECTBOX) + { + int old_index = gi->selectbox.current_index; - if (gi->type & GD_TYPE_SCROLLBAR) + /* if mouse moving inside activated selectbox, select value */ + if (my >= gi->selectbox.y && my < gi->selectbox.y + gi->selectbox.height) + gi->selectbox.current_index = + (my - gi->selectbox.y - gi->border.size) / + getFontWidth(gi->selectbox.font_type); + + if (gi->selectbox.current_index < 0) + gi->selectbox.current_index = 0; + else if (gi->selectbox.current_index > gi->selectbox.num_values - 1) + gi->selectbox.current_index = gi->selectbox.num_values - 1; + + if (gi->selectbox.current_index != old_index) + DrawGadget(gi, DG_PRESSED, DG_DIRECT); + } + else if (gi->type & GD_TYPE_SCROLLBAR) { struct GadgetScrollbar *gs = &gi->scrollbar; int old_item_position = gs->item_position; @@ -1139,13 +1419,25 @@ void HandleGadgets(int mx, int my, int button) if (gadget_released_inside) { - if (!(gi->type & GD_TYPE_TEXTINPUT)) + boolean deactivate_gadget = TRUE; + + if (gi->type & GD_TYPE_SELECTBOX) + { + if (gadget_released_inside_select_line || + gadget_released_off_borders) /* selectbox stays open */ + deactivate_gadget = FALSE; + else + gi->selectbox.index = gi->selectbox.current_index; + } + + if (deactivate_gadget && + !(gi->type & GD_TYPE_TEXTINPUT)) /* text input stays open */ DrawGadget(gi, DG_UNPRESSED, DG_DIRECT); gi->state = GD_BUTTON_UNPRESSED; gi->event.type = GD_EVENT_RELEASED; - if (gi->event_mask & GD_EVENT_RELEASED) + if ((gi->event_mask & GD_EVENT_RELEASED) && deactivate_gadget) gi->callback_action(gi); } @@ -1165,56 +1457,18 @@ void HandleGadgets(int mx, int my, int button) 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) + if (gi == NULL || !gi->mapped || + !((gi->type & GD_TYPE_TEXTINPUT) || (gi->type & GD_TYPE_SELECTBOX))) 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) + if (key == KSYM_Return) /* valid for both text input and selectbox */ { - 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); + if (gi->type & GD_TYPE_TEXTINPUT) + CheckRangeOfNumericInputGadget(gi); + else if (gi->type & GD_TYPE_SELECTBOX) + gi->selectbox.index = gi->selectbox.current_index; + DrawGadget(gi, DG_UNPRESSED, DG_DIRECT); gi->event.type = GD_EVENT_TEXT_RETURN; @@ -1224,4 +1478,63 @@ void HandleGadgetsKeyInput(Key key) last_gi = NULL; } + else if (gi->type & GD_TYPE_TEXTINPUT) /* only valid for text input */ + { + char text[MAX_GADGET_TEXTSIZE]; + int text_length = strlen(gi->text.value); + int cursor_pos = gi->text.cursor_position; + char letter = getCharFromKey(key); + boolean 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 (gi->type & GD_TYPE_SELECTBOX) /* only valid for selectbox */ + { + int index = gi->selectbox.current_index; + int num_values = gi->selectbox.num_values; + + if (key == KSYM_Up && index > 0) + { + gi->selectbox.current_index--; + DrawGadget(gi, DG_PRESSED, DG_DIRECT); + } + else if (key == KSYM_Down && index < num_values - 1) + { + gi->selectbox.current_index++; + DrawGadget(gi, DG_PRESSED, DG_DIRECT); + } + } } diff --git a/src/libgame/gadgets.h b/src/libgame/gadgets.h index e1208994..4ee06dbb 100644 --- a/src/libgame/gadgets.h +++ b/src/libgame/gadgets.h @@ -154,6 +154,17 @@ struct GadgetSelectbox int index; /* index of actual text string */ int size; /* maximal size of text strings */ int font_type; /* font to use for text input */ + + /* automatically determined values */ + int x, y; /* open selectbox position */ + int width, height; /* open selectbox size */ + int num_values; /* number of text strings */ + Pixel reverse_color; /* color for highlighting */ + + /* runtime values */ + boolean open; /* opening state of selectbox */ + boolean stay_open; /* open after button release */ + int current_index; /* index of text while selecting */ }; struct GadgetScrollbar diff --git a/src/libgame/system.c b/src/libgame/system.c index 1e628241..7d25d4cd 100644 --- a/src/libgame/system.c +++ b/src/libgame/system.c @@ -129,7 +129,8 @@ void ClosePlatformDependantStuff(void) void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize, int real_sx, int real_sy, - int full_sxsize, int full_sysize) + int full_sxsize, int full_sysize, + Bitmap *field_save_buffer) { gfx.sx = sx; gfx.sy = sy; @@ -140,6 +141,8 @@ void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize, gfx.full_sxsize = full_sxsize; gfx.full_sysize = full_sysize; + gfx.field_save_buffer = field_save_buffer; + gfx.background_bitmap = NULL; gfx.background_bitmap_mask = REDRAW_NONE; @@ -479,6 +482,31 @@ inline void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap, #endif } +inline void DrawRectangle(Bitmap *bitmap, int x, int y, int width, int height, + Pixel color) +{ + if (DrawingDeactivated(x, y, width, height)) + return; + +#ifdef TARGET_SDL + SDLFillRectangle(bitmap, x, y, width, height, color); +#else + XSetForeground(display, bitmap->gc, color); + XFillRectangle(display, bitmap->drawable, bitmap->gc, x, y, width, height); + XSetForeground(display, bitmap->gc, BlackPixel(display, screen)); +#endif +} + +#if 1 +inline void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height) +{ +#ifdef TARGET_SDL + DrawRectangle(bitmap, x, y, width, height, 0x000000); +#else + DrawRectangle(bitmap, x, y, width, height, 0x000000); +#endif +} +#else inline void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height) { if (DrawingDeactivated(x, y, width, height)) @@ -490,6 +518,7 @@ inline void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height) XFillRectangle(display, bitmap->drawable, bitmap->gc, x, y, width, height); #endif } +#endif inline void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y, int width, int height) diff --git a/src/libgame/system.h b/src/libgame/system.h index 2abb3cdd..c5afeada 100644 --- a/src/libgame/system.h +++ b/src/libgame/system.h @@ -328,6 +328,8 @@ struct GfxInfo int draw_deactivation_mask; int draw_background_mask; + Bitmap *field_save_buffer; + Bitmap *background_bitmap; int background_bitmap_mask; @@ -636,7 +638,7 @@ void InitExitFunction(void (*exit_function)(int)); void InitPlatformDependantStuff(void); void ClosePlatformDependantStuff(void); -void InitGfxFieldInfo(int, int, int, int, int, int, int, int); +void InitGfxFieldInfo(int, int, int, int, int, int, int, int, Bitmap *); void InitGfxDoor1Info(int, int, int, int); void InitGfxDoor2Info(int, int, int, int); void InitGfxScrollbufferInfo(int, int); @@ -652,6 +654,7 @@ inline Bitmap *CreateBitmapStruct(void); inline Bitmap *CreateBitmap(int, int, int); inline void FreeBitmap(Bitmap *); inline void BlitBitmap(Bitmap *, Bitmap *, int, int, int, int, int, int); +inline void DrawRectangle(Bitmap *, int, int, int, int, Pixel); inline void ClearRectangle(Bitmap *, int, int, int, int); inline void ClearRectangleOnBackground(Bitmap *, int, int, int, int); inline void SetClipMask(Bitmap *, GC, Pixmap); diff --git a/src/libgame/text.c b/src/libgame/text.c index 890d1886..61800916 100644 --- a/src/libgame/text.c +++ b/src/libgame/text.c @@ -135,6 +135,29 @@ int getFontHeight(int font_nr) return gfx.font_bitmap_info[font_bitmap_id].height; } +boolean getFontChar(int font_nr, char c, int *src_x, int *src_y) +{ + int font_bitmap_id = gfx.select_font_function(font_nr); + struct FontBitmapInfo *font = &gfx.font_bitmap_info[font_bitmap_id]; + + if ((c >= 32 && c <= 95) || c == '°' || c == '´' || c == '|') + { + *src_x = font->src_x + ((c - 32) % FONT_CHARS_PER_LINE) * font->width; + *src_y = font->src_y + ((c - 32) / FONT_CHARS_PER_LINE) * font->height; + + /* map '°' and 'TM' signs and cursor */ + if (c == '°' || c == '´' || c == '|') + { + *src_x = font->src_x + FONT_CHARS_PER_LINE * font->width; + *src_y = font->src_y + (c == '°' ? 1 : c == '´' ? 2 : 3) * font->height; + } + + return TRUE; + } + + return FALSE; +} + void DrawInitText(char *text, int ypos, int font_nr) { if (window && @@ -202,6 +225,8 @@ void DrawTextExt(DrawBuffer *dst_bitmap, int dst_x, int dst_y, char *text, int font_bitmap_id = gfx.select_font_function(font_nr); struct FontBitmapInfo *font = &gfx.font_bitmap_info[font_bitmap_id]; boolean print_inverse = FALSE; + boolean print_inverse_cursor = FALSE; + int src_x, src_y; if (font->bitmap == NULL) return; @@ -217,6 +242,9 @@ void DrawTextExt(DrawBuffer *dst_bitmap, int dst_x, int dst_y, char *text, if (c == '~') { print_inverse = TRUE; + if (strlen(text) == 1) + print_inverse_cursor = TRUE; + continue; } @@ -233,6 +261,10 @@ void DrawTextExt(DrawBuffer *dst_bitmap, int dst_x, int dst_y, char *text, else if (c == '\\') /* bad luck ... */ c = '/'; +#if 1 + if (getFontChar(font_nr, c, &src_x, &src_y)) + { +#else if ((c >= 32 && c <= 95) || c == '°' || c == '´' || c == '|') { int src_x= font->src_x + ((c - 32) % FONT_CHARS_PER_LINE) * font->width; @@ -243,14 +275,16 @@ void DrawTextExt(DrawBuffer *dst_bitmap, int dst_x, int dst_y, char *text, src_x = font->src_x + FONT_CHARS_PER_LINE * font->width; src_y = font->src_y + (c == '°' ? 1 : c == '´' ? 2 : 3) * font->height; } +#endif if (print_inverse) /* special mode for text gadgets */ { /* first step: draw solid colored rectangle (use "cursor" character) */ - BlitBitmap(font->bitmap, dst_bitmap, - font->src_x + FONT_CHARS_PER_LINE * font->width, - font->src_y + 3 * font->height, - font->width, font->height, dst_x, dst_y); + if (print_inverse_cursor) + BlitBitmap(font->bitmap, dst_bitmap, + font->src_x + FONT_CHARS_PER_LINE * font->width, + font->src_y + 3 * font->height, + font->width, font->height, dst_x, dst_y); /* second step: draw masked black rectangle (use "space" character) */ SetClipOrigin(font->bitmap, font->bitmap->stored_clip_gc, diff --git a/src/libgame/text.h b/src/libgame/text.h index d5a12ecd..c1915d47 100644 --- a/src/libgame/text.h +++ b/src/libgame/text.h @@ -44,6 +44,8 @@ void InitFontInfo(struct FontBitmapInfo *, int, int (*select_font_function)(int)); int getFontWidth(int); int getFontHeight(int); +boolean getFontChar(int, char, int *, int *); + void DrawInitText(char *, int, int); void DrawTextF(int, int, int, char *, ...); void DrawTextFCentered(int, int, char *, ...); -- 2.34.1