X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fgadgets.c;h=a134b04921c77e6367249607564f5e6d071e9918;hb=e2b2b44c56f55520c8cc43cf361c83a12e60f7b0;hp=8601256cbf3ed1b2da04be5a9422d40f62bf6efd;hpb=b876f418a4aaf55280b4b5da38c175997be01360;p=rocksndiamonds.git diff --git a/src/libgame/gadgets.c b/src/libgame/gadgets.c index 8601256c..a134b049 100644 --- a/src/libgame/gadgets.c +++ b/src/libgame/gadgets.c @@ -776,6 +776,7 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap) case GDI_NUMBER_VALUE: gi->textinput.number_value = va_arg(ap, long); sprintf(gi->textinput.value, "%d", gi->textinput.number_value); + strcpy(gi->textinput.last_value, gi->textinput.value); gi->textinput.cursor_position = strlen(gi->textinput.value); break; @@ -785,6 +786,7 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap) { gi->textinput.number_value = gi->textinput.number_min; sprintf(gi->textinput.value, "%d", gi->textinput.number_value); + strcpy(gi->textinput.last_value, gi->textinput.value); } break; @@ -794,6 +796,7 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap) { gi->textinput.number_value = gi->textinput.number_max; sprintf(gi->textinput.value, "%d", gi->textinput.number_value); + strcpy(gi->textinput.last_value, gi->textinput.value); } break; @@ -805,12 +808,15 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap) max_textsize = MIN(gi->textinput.size, MAX_GADGET_TEXTSIZE - 1); strncpy(gi->textinput.value, va_arg(ap, char *), max_textsize); + strcpy(gi->textinput.last_value, gi->textinput.value); + gi->textinput.value[max_textsize] = '\0'; gi->textinput.cursor_position = strlen(gi->textinput.value); /* same tag also used for other gadget definitions */ strcpy(gi->textbutton.value, gi->textinput.value); strcpy(gi->textarea.value, gi->textinput.value); + strcpy(gi->textarea.last_value, gi->textinput.value); } break; @@ -821,10 +827,17 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap) gi->textinput.size = max_textsize; gi->textinput.value[max_textsize] = '\0'; + strcpy(gi->textinput.last_value, gi->textinput.value); /* same tag also used for other gadget definitions */ - strcpy(gi->textbutton.value, gi->textinput.value); - gi->textbutton.size = gi->textinput.size; + + gi->textarea.size = max_textsize; + gi->textarea.value[max_textsize] = '\0'; + strcpy(gi->textarea.last_value, gi->textinput.value); + + gi->textbutton.size = max_textsize; + gi->textbutton.value[max_textsize] = '\0'; + gi->selectbox.size = gi->textinput.size; } break; @@ -1055,7 +1068,11 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap) getFontCharSource(font_nr, FONT_ASCII_CURSOR, &src_bitmap, &src_x, &src_y); src_x += font_width / 2; src_y += font_height / 2; - gi->selectbox.inverse_color = GetPixel(src_bitmap, src_x, src_y); + + /* there may be esoteric cases with missing or too small font bitmap */ + if (src_bitmap != NULL && + src_x < src_bitmap->width && src_y < src_bitmap->height) + gi->selectbox.inverse_color = GetPixel(src_bitmap, src_x, src_y); /* always start with closed selectbox */ gi->selectbox.open = FALSE; @@ -1088,16 +1105,23 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap) if (gi->type & GD_TYPE_SCROLLBAR) { struct GadgetScrollbar *gs = &gi->scrollbar; + int scrollbar_size_cmp; 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_min = (gi->type == GD_TYPE_SCROLLBAR_VERTICAL ? + gi->width : gi->height); 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; + + scrollbar_size_cmp = gs->size_max * gs->items_visible / gs->items_max; + gs->size = MAX(scrollbar_size_cmp, gs->size_min); + gs->size_max_cmp = (gs->size_max - (gs->size - scrollbar_size_cmp)); + + gs->position = gs->size_max_cmp * gs->item_position / gs->items_max; gs->position_max = gs->size_max - gs->size; gs->correction = gs->size_max / gs->items_max / 2; @@ -1296,21 +1320,33 @@ void RemapAllGadgets() MultiMapGadgets(MULTIMAP_ALL | MULTIMAP_REMAP); } -static boolean anyTextInputGadgetActive() +boolean anyTextInputGadgetActive() { return (last_gi && (last_gi->type & GD_TYPE_TEXT_INPUT) && last_gi->mapped); } -static boolean anyTextAreaGadgetActive() +boolean anyTextAreaGadgetActive() { return (last_gi && (last_gi->type & GD_TYPE_TEXT_AREA) && last_gi->mapped); } -static boolean anySelectboxGadgetActive() +boolean anySelectboxGadgetActive() { return (last_gi && (last_gi->type & GD_TYPE_SELECTBOX) && last_gi->mapped); } +boolean anyScrollbarGadgetActive() +{ + return (last_gi && (last_gi->type & GD_TYPE_SCROLLBAR) && last_gi->mapped); +} + +boolean anyTextGadgetActive() +{ + return (anyTextInputGadgetActive() || + anyTextAreaGadgetActive() || + anySelectboxGadgetActive()); +} + static boolean insideSelectboxLine(struct GadgetInfo *gi, int mx, int my) { return(gi != NULL && @@ -1327,15 +1363,11 @@ static boolean insideSelectboxArea(struct GadgetInfo *gi, int mx, int my) my >= gi->selectbox.y && my < gi->selectbox.y + gi->selectbox.height); } -boolean anyTextGadgetActive() -{ - return (anyTextInputGadgetActive() || - anyTextAreaGadgetActive() || - anySelectboxGadgetActive()); -} - void ClickOnGadget(struct GadgetInfo *gi, int button) { + if (!gi->mapped) + return; + /* simulate releasing mouse button over last gadget, if still pressed */ if (button_status) HandleGadgets(-1, -1, 0); @@ -1429,14 +1461,35 @@ boolean HandleGadgets(int mx, int my, int button) button != 0 && !motion_status && new_gi != last_gi) #endif { - CheckRangeOfNumericInputGadget(last_gi); /* in case of numeric gadget */ + struct GadgetInfo *gi = last_gi; + boolean gadget_changed = (gi->event_mask & GD_EVENT_TEXT_LEAVING); - DrawGadget(last_gi, DG_UNPRESSED, last_gi->direct_draw); + /* check if text gadget has changed its value */ + if (gi->type & GD_TYPE_TEXT_INPUT) + { + CheckRangeOfNumericInputGadget(gi); - last_gi->event.type = GD_EVENT_TEXT_LEAVING; + if (strcmp(gi->textinput.value, gi->textinput.last_value) != 0) + strcpy(gi->textinput.last_value, gi->textinput.value); + else + gadget_changed = FALSE; + } - if (last_gi->event_mask & GD_EVENT_TEXT_LEAVING) - last_gi->callback_action(last_gi); + /* selectbox does not change its value when closed by clicking outside */ + if (gi->type & GD_TYPE_SELECTBOX) + gadget_changed = FALSE; + + DrawGadget(gi, DG_UNPRESSED, gi->direct_draw); + + gi->event.type = GD_EVENT_TEXT_LEAVING; + +#if 1 + if (gadget_changed && !(gi->type & GD_TYPE_SELECTBOX)) + gi->callback_action(gi); +#else + if (gi->event_mask & GD_EVENT_TEXT_LEAVING) + gi->callback_action(gi); +#endif last_gi = NULL; @@ -1752,7 +1805,7 @@ boolean HandleGadgets(int mx, int my, int button) gs->position = gs->position_max; gs->item_position = - gs->items_max * (gs->position + gs->correction) / gs->size_max; + gs->items_max * (gs->position + gs->correction) / gs->size_max_cmp; if (gs->item_position < 0) gs->item_position = 0; @@ -1781,20 +1834,29 @@ boolean HandleGadgets(int mx, int my, int button) if (gadget_released_inside) { boolean deactivate_gadget = TRUE; + boolean gadget_changed = TRUE; if (gi->type & GD_TYPE_SELECTBOX) { #if 1 if (mouse_released_where_pressed || !gadget_released_inside_select_area) /* selectbox stays open */ + { deactivate_gadget = FALSE; + gadget_changed = FALSE; + } #else if (gadget_released_inside_select_line || gadget_released_off_borders) /* selectbox stays open */ + { deactivate_gadget = FALSE; + gadget_changed = FALSE; + } #endif - else + else if (gi->selectbox.index != gi->selectbox.current_index) gi->selectbox.index = gi->selectbox.current_index; + else + gadget_changed = FALSE; } if (deactivate_gadget && @@ -1805,8 +1867,15 @@ boolean HandleGadgets(int mx, int my, int button) gi->state = GD_BUTTON_UNPRESSED; gi->event.type = GD_EVENT_RELEASED; +#if 1 + if ((gi->event_mask & GD_EVENT_RELEASED) && gadget_changed) + { + gi->callback_action(gi); + } +#else if ((gi->event_mask & GD_EVENT_RELEASED) && deactivate_gadget) gi->callback_action(gi); +#endif } if (gadget_released_off_borders) @@ -1856,10 +1925,24 @@ boolean HandleGadgetsKeyInput(Key key) if (key == KSYM_Return) /* valid for both text input and selectbox */ { + boolean gadget_changed = (gi->event_mask & GD_EVENT_TEXT_RETURN); + if (gi->type & GD_TYPE_TEXT_INPUT) + { CheckRangeOfNumericInputGadget(gi); + + if (strcmp(gi->textinput.value, gi->textinput.last_value) != 0) + strcpy(gi->textinput.last_value, gi->textinput.value); + else + gadget_changed = FALSE; + } else if (gi->type & GD_TYPE_SELECTBOX) - gi->selectbox.index = gi->selectbox.current_index; + { + if (gi->selectbox.index != gi->selectbox.current_index) + gi->selectbox.index = gi->selectbox.current_index; + else + gadget_changed = FALSE; + } if (gi->type & GD_TYPE_TEXT_AREA) { @@ -1876,8 +1959,13 @@ boolean HandleGadgetsKeyInput(Key key) last_gi = NULL; } +#if 1 + if (gadget_changed) + gi->callback_action(gi); +#else if (gi->event_mask & GD_EVENT_TEXT_RETURN) gi->callback_action(gi); +#endif } else if (gi->type & GD_TYPE_TEXT_INPUT) /* only valid for text input */ {