added handling of unselectable selectbox options
[rocksndiamonds.git] / src / libgame / gadgets.c
index 3781aeb416c1497163820c819992baad3fb222bd..1c52ec5d422e5ce591426280d792a62af9871c49 100644 (file)
@@ -1,15 +1,13 @@
-/***********************************************************
-* Artsoft Retro-Game Library                               *
-*----------------------------------------------------------*
-* (c) 1994-2006 Artsoft Entertainment                      *
-*               Holger Schemel                             *
-*               Detmolder Strasse 189                      *
-*               33604 Bielefeld                            *
-*               Germany                                    *
-*               e-mail: info@artsoft.org                   *
-*----------------------------------------------------------*
-* gadgets.c                                                *
-***********************************************************/
+// ============================================================================
+// Artsoft Retro-Game Library
+// ----------------------------------------------------------------------------
+// (c) 1995-2014 by Artsoft Entertainment
+//                         Holger Schemel
+//                 info@artsoft.org
+//                 http://www.artsoft.org/
+// ----------------------------------------------------------------------------
+// gadgets.c
+// ============================================================================
 
 #include <stdarg.h>
 #include <string.h>
 
 #define GADGET_DEACTIVATED(g)  ((g)->x < 0 || (g)->y < 0)
 
+#define OPTION_TEXT_SELECTABLE(g, t)                                   \
+  (t[0] != g->selectbox.char_unselectable &&                           \
+   t[0] != '\0' &&                                                     \
+   !strEqual(t, " "))
+#define CURRENT_OPTION_SELECTABLE(g)                                   \
+  OPTION_TEXT_SELECTABLE(g, g->selectbox.options[g->selectbox.current_index].text)
+
 
 static struct GadgetInfo *gadget_list_first_entry = NULL;
 static struct GadgetInfo *gadget_list_last_entry = NULL;
@@ -384,16 +389,9 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
                                   gi->height - 2 * border_y);
 
        /* gadget text value */
-#if 1
        DrawTextBuffer(gi->x + border_x, gi->y + border_y, gi->textarea.value,
                       font_nr, gi->textarea.xsize, -1, gi->textarea.ysize, 0,
                       BLIT_ON_BACKGROUND, FALSE, FALSE, FALSE);
-#else
-       DrawTextToTextArea(gi->x + border_x, gi->y + border_y,
-                          gi->textarea.value, font_nr, gi->textarea.xsize,
-                          gi->textarea.xsize, gi->textarea.ysize,
-                          BLIT_ON_BACKGROUND);
-#endif
 
        cursor_letter = gi->textarea.value[gi->textarea.cursor_position];
        cursor_string[0] = (cursor_letter != '\0' ? cursor_letter : ' ');
@@ -413,7 +411,8 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
       {
        int i;
        char text[MAX_GADGET_TEXTSIZE + 1];
-       int font_nr = (pressed ? gi->font_active : gi->font);
+       int font_nr_default = (pressed ? gi->font_active : gi->font);
+       int font_nr = font_nr_default;
        int font_width = getFontWidth(font_nr);
        int font_height = getFontHeight(font_nr);
        int border_x = gi->border.xsize;
@@ -450,6 +449,10 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
                gi->selectbox.size);
        text[gi->selectbox.size] = '\0';
 
+       /* set font value */
+       font_nr = (OPTION_TEXT_SELECTABLE(gi, text) ? font_nr_default :
+                  gi->font_unselectable);
+
        /* gadget text value */
        DrawTextExt(drawto, gi->x + border_x, gi->y + border_y, text,
                    font_nr, BLIT_MASKED);
@@ -558,7 +561,11 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
            strncpy(text, gi->selectbox.options[i].text, gi->selectbox.size);
            text[gi->selectbox.size] = '\0';
 
-           if (i == gi->selectbox.current_index)
+           font_nr = (OPTION_TEXT_SELECTABLE(gi, text) ? font_nr_default :
+                      gi->font_unselectable);
+
+           if (i == gi->selectbox.current_index &&
+               OPTION_TEXT_SELECTABLE(gi, text))
            {
              FillRectangle(drawto,
                            gi->selectbox.x + border_x,
@@ -710,7 +717,6 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
   }
   else
   {
-#if 1
     int x = gi->x;
     int y = gi->y;
 
@@ -718,11 +724,6 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
                    IN_GFX_DOOR_1(x, y) ? REDRAW_DOOR_1 :
                    IN_GFX_DOOR_2(x, y) ? REDRAW_DOOR_2 :
                    IN_GFX_DOOR_3(x, y) ? REDRAW_DOOR_3 : REDRAW_ALL);
-#else
-    redraw_mask |= (gi->x < gfx.sx + gfx.sxsize ? REDRAW_FIELD :
-                   gi->y < gfx.dy + gfx.dysize ? REDRAW_DOOR_1 :
-                   gi->y > gfx.vy ? REDRAW_DOOR_2 : REDRAW_DOOR_3);
-#endif
   }
 }
 
@@ -888,12 +889,18 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
        gi->font = va_arg(ap, int);
        if (gi->font_active == 0)
          gi->font_active = gi->font;
+       if (gi->font_unselectable == 0)
+         gi->font_unselectable = gi->font;
        break;
 
       case GDI_TEXT_FONT_ACTIVE:
        gi->font_active = va_arg(ap, int);
        break;
 
+      case GDI_TEXT_FONT_UNSELECTABLE:
+       gi->font_unselectable = va_arg(ap, int);
+       break;
+
       case GDI_SELECTBOX_OPTIONS:
        gi->selectbox.options = va_arg(ap, struct ValueTextInfo *);
        break;
@@ -902,6 +909,10 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
        gi->selectbox.index = va_arg(ap, int);
        break;
 
+      case GDI_SELECTBOX_CHAR_UNSELECTABLE:
+       gi->selectbox.char_unselectable = (char)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);
@@ -1263,6 +1274,9 @@ void FreeGadget(struct GadgetInfo *gi)
 {
   struct GadgetInfo *gi_previous = gadget_list_first_entry;
 
+  if (gi == NULL)
+    return;
+
   /* prevent "last_info_gi" from pointing to memory that will be freed */
   if (last_info_gi == gi)
     last_info_gi = NULL;
@@ -1353,7 +1367,6 @@ static void MultiMapGadgets(int mode)
 
   while (gi != NULL)
   {
-#if 1
     int x = gi->x;
     int y = gi->y;
 
@@ -1362,15 +1375,6 @@ static void MultiMapGadgets(int mode)
        (mode & MULTIMAP_DOOR_2 && IN_GFX_DOOR_2(x, y)) ||
        (mode & MULTIMAP_DOOR_3 && IN_GFX_DOOR_3(x, y)) ||
        (mode & MULTIMAP_ALL) == MULTIMAP_ALL)
-#else
-    if ((mode & MULTIMAP_PLAYFIELD &&
-        gi->x < gfx.sx + gfx.sxsize) ||
-       (mode & MULTIMAP_DOOR_1 &&
-        gi->x >= gfx.dx && gi->y < gfx.dy + gfx.dysize) ||
-       (mode & MULTIMAP_DOOR_2 &&
-        gi->x >= gfx.dx && gi->y > gfx.dy + gfx.dysize) ||
-       (mode & MULTIMAP_ALL) == MULTIMAP_ALL)
-#endif
     {
       if (mode & MULTIMAP_UNMAP)
       {
@@ -1486,9 +1490,6 @@ boolean HandleGadgets(int mx, int my, int button)
   boolean gadget_dragging;
   boolean gadget_released;
   boolean gadget_released_inside;
-#if 0
-  boolean gadget_released_inside_select_line;
-#endif
   boolean gadget_released_inside_select_area;
   boolean gadget_released_off_borders;
   boolean changed_position = FALSE;
@@ -1590,19 +1591,9 @@ boolean HandleGadgets(int mx, int my, int button)
 
   /* when handling selectbox, set additional state values */
   if (gadget_released_inside && (last_gi->type & GD_TYPE_SELECTBOX))
-  {
-#if 0
-    gadget_released_inside_select_line = insideSelectboxLine(last_gi, mx, my);
-#endif
     gadget_released_inside_select_area = insideSelectboxArea(last_gi, mx, my);
-  }
   else
-  {
-#if 0
-    gadget_released_inside_select_line = FALSE;
-#endif
     gadget_released_inside_select_area = FALSE;
-  }
 
   /* setting state for handling over-large selectbox */
   if (keep_selectbox_open && (press_event || !mouse_inside_select_line))
@@ -1626,7 +1617,8 @@ boolean HandleGadgets(int mx, int my, int button)
     if (gi->type & GD_TYPE_SELECTBOX &&
        (keep_selectbox_open ||
         mouse_released_where_pressed ||
-        !gadget_released_inside_select_area))       /* selectbox stays open */
+        !gadget_released_inside_select_area ||
+        !CURRENT_OPTION_SELECTABLE(gi)))           /* selectbox stays open */
     {
       gi->selectbox.stay_open = TRUE;
       pressed_mx = 0;
@@ -1984,7 +1976,8 @@ boolean HandleGadgets(int mx, int my, int button)
     {
       if (keep_selectbox_open ||
          mouse_released_where_pressed ||
-         !gadget_released_inside_select_area)       /* selectbox stays open */
+         !gadget_released_inside_select_area ||
+         !CURRENT_OPTION_SELECTABLE(gi))           /* selectbox stays open */
       {
        deactivate_gadget = FALSE;
        gadget_changed = FALSE;