fixed compiler warnings (after adding "-Wstrict-prototypes")
[rocksndiamonds.git] / src / libgame / gadgets.c
index daa045eb4892dd4ea28b98d9def164ad143bf12d..4cf008fc01eaaec6044f85d3de57e00bfd4cad36 100644 (file)
@@ -13,6 +13,7 @@
 #include <string.h>
 
 #include "gadgets.h"
+#include "image.h"
 #include "text.h"
 #include "misc.h"
 
@@ -24,8 +25,6 @@
 #define DG_BUFFERED            0
 #define DG_DIRECT              1
 
-#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' &&                                                     \
@@ -61,7 +60,7 @@ static struct GadgetInfo *getGadgetInfoFromGadgetID(int id)
   return gi;
 }
 
-static int getNewGadgetID()
+static int getNewGadgetID(void)
 {
   int id = next_free_gadget_id++;
 
@@ -220,7 +219,7 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
   int state = (pressed ? GD_BUTTON_PRESSED : GD_BUTTON_UNPRESSED);
   boolean redraw_selectbox = FALSE;
 
-  if (gi == NULL)
+  if (gi == NULL || gi->deactivated)
     return;
 
   gd = (!gi->active ? &gi->alt_design[state] :
@@ -777,13 +776,17 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
 {
   int tag = first_tag;
 
-  if (gi == NULL)
+  if (gi == NULL || gi->deactivated)
     return;
 
   while (tag != GDI_END)
   {
     switch(tag)
     {
+      case GDI_IMAGE_ID:
+       gi->image_id = va_arg(ap, int);
+       break;
+
       case GDI_CUSTOM_ID:
        gi->custom_id = va_arg(ap, int);
        break;
@@ -1097,11 +1100,17 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
     tag = va_arg(ap, int);     /* read next tag */
   }
 
-  /* check if gadget is complete */
+  gi->deactivated = FALSE;
+
+  /* check if gadget has undefined bitmaps */
   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)");
+      (gi->design[GD_BUTTON_UNPRESSED].bitmap == NULL ||
+       gi->design[GD_BUTTON_PRESSED].bitmap == NULL))
+    gi->deactivated = TRUE;
+
+  /* check if gadget is placed off-screen */
+  if (gi->x < 0 || gi->y < 0)
+    gi->deactivated = TRUE;
 
   /* adjust gadget values in relation to other gadget values */
 
@@ -1263,7 +1272,7 @@ void ModifyGadget(struct GadgetInfo *gi, int first_tag, ...)
 
 void RedrawGadget(struct GadgetInfo *gi)
 {
-  if (gi == NULL)
+  if (gi == NULL || gi->deactivated)
     return;
 
   if (gi->mapped)
@@ -1277,6 +1286,7 @@ struct GadgetInfo *CreateGadget(int first_tag, ...)
 
   /* always start with reliable default values */
   new_gadget->id = getNewGadgetID();
+  new_gadget->image_id = -1;
   new_gadget->callback_info = default_callback_info;
   new_gadget->callback_action = default_callback_action;
   new_gadget->active = TRUE;
@@ -1351,7 +1361,7 @@ static struct GadgetInfo *last_gi = NULL;
 
 static void MapGadgetExt(struct GadgetInfo *gi, boolean redraw)
 {
-  if (gi == NULL || gi->mapped || GADGET_DEACTIVATED(gi))
+  if (gi == NULL || gi->deactivated || gi->mapped)
     return;
 
   gi->mapped = TRUE;
@@ -1367,7 +1377,7 @@ void MapGadget(struct GadgetInfo *gi)
 
 void UnmapGadget(struct GadgetInfo *gi)
 {
-  if (gi == NULL || !gi->mapped)
+  if (gi == NULL || gi->deactivated || !gi->mapped)
     return;
 
   gi->mapped = FALSE;
@@ -1422,37 +1432,37 @@ static void MultiMapGadgets(int mode)
   }
 }
 
-void UnmapAllGadgets()
+void UnmapAllGadgets(void)
 {
   MultiMapGadgets(MULTIMAP_ALL | MULTIMAP_UNMAP);
 }
 
-void RemapAllGadgets()
+void RemapAllGadgets(void)
 {
   MultiMapGadgets(MULTIMAP_ALL | MULTIMAP_REMAP);
 }
 
-boolean anyTextInputGadgetActive()
+boolean anyTextInputGadgetActive(void)
 {
   return (last_gi && (last_gi->type & GD_TYPE_TEXT_INPUT) && last_gi->mapped);
 }
 
-boolean anyTextAreaGadgetActive()
+boolean anyTextAreaGadgetActive(void)
 {
   return (last_gi && (last_gi->type & GD_TYPE_TEXT_AREA) && last_gi->mapped);
 }
 
-boolean anySelectboxGadgetActive()
+boolean anySelectboxGadgetActive(void)
 {
   return (last_gi && (last_gi->type & GD_TYPE_SELECTBOX) && last_gi->mapped);
 }
 
-boolean anyScrollbarGadgetActive()
+boolean anyScrollbarGadgetActive(void)
 {
   return (last_gi && (last_gi->type & GD_TYPE_SCROLLBAR) && last_gi->mapped);
 }
 
-boolean anyTextGadgetActive()
+boolean anyTextGadgetActive(void)
 {
   return (anyTextInputGadgetActive() ||
          anyTextAreaGadgetActive() ||
@@ -1477,7 +1487,7 @@ static boolean insideSelectboxArea(struct GadgetInfo *gi, int mx, int my)
 
 void ClickOnGadget(struct GadgetInfo *gi, int button)
 {
-  if (!gi->mapped)
+  if (gi == NULL || gi->deactivated || !gi->mapped)
     return;
 
   /* simulate releasing mouse button over last gadget, if still pressed */
@@ -1601,6 +1611,8 @@ boolean HandleGadgets(int mx, int my, int button)
 
     if (gadget_pressed_inside_select_line)
       new_gi = NULL;
+
+    StopTextInput();
   }
 
   gadget_pressed =
@@ -1675,16 +1687,20 @@ boolean HandleGadgets(int mx, int my, int button)
   {
     int last_x = gi->event.x;
     int last_y = gi->event.y;
+    int last_mx = gi->event.mx;
+    int last_my = gi->event.my;
 
-    gi->event.x = mx - gi->x;
-    gi->event.y = my - gi->y;
+    gi->event.x = gi->event.mx = mx - gi->x;
+    gi->event.y = gi->event.my = 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)
+      if (last_x != gi->event.x || last_y != gi->event.y ||
+         ((last_mx != gi->event.mx || last_my != gi->event.my) &&
+          gi->event_mask & GD_EVENT_PIXEL_PRECISE))
        changed_position = TRUE;
     }
     else if (gi->type & GD_TYPE_TEXT_INPUT && button != 0 && !motion_status)
@@ -1702,6 +1718,9 @@ boolean HandleGadgets(int mx, int my, int button)
 
       if (gi->textinput.cursor_position != old_cursor_position)
        DrawGadget(gi, DG_PRESSED, gi->direct_draw);
+
+      if (press_event)
+       StartTextInput(gi->x, gi->y, gi->width, gi->height);
     }
     else if (gi->type & GD_TYPE_TEXT_AREA && button != 0 && !motion_status)
     {
@@ -1716,6 +1735,9 @@ boolean HandleGadgets(int mx, int my, int button)
 
       if (gi->textarea.cursor_position != old_cursor_position)
        DrawGadget(gi, DG_PRESSED, gi->direct_draw);
+
+      if (press_event)
+       StartTextInput(gi->x, gi->y, gi->width, gi->height);
     }
     else if (gi->type & GD_TYPE_SELECTBOX && gi->selectbox.open &&
             !keep_selectbox_open)
@@ -1746,7 +1768,7 @@ boolean HandleGadgets(int mx, int my, int button)
       new_gi->event.type = GD_EVENT_INFO_ENTERING;
       new_gi->callback_info(new_gi);
     }
-    else if (last_info_gi != NULL)
+    else if (last_info_gi != NULL && last_info_gi->mapped)
     {
       last_info_gi->event.type = GD_EVENT_INFO_LEAVING;
       last_info_gi->callback_info(last_info_gi);
@@ -2072,13 +2094,17 @@ boolean HandleGadgetsKeyInput(Key key)
 {
   struct GadgetInfo *gi = last_gi;
 
-  if (gi == NULL || !gi->mapped ||
+  if (gi == NULL || gi->deactivated || !gi->mapped ||
       !(gi->type & GD_TYPE_TEXT_INPUT ||
        gi->type & GD_TYPE_TEXT_AREA ||
        gi->type & GD_TYPE_SELECTBOX))
     return FALSE;
 
-  if (key == KSYM_Return)      /* valid for both text input and selectbox */
+  if (key == KSYM_Escape)
+  {
+    StopTextInput();
+  }
+  else if (key == KSYM_Return) /* valid for both text input and selectbox */
   {
     boolean gadget_changed = ((gi->event_mask & GD_EVENT_TEXT_RETURN) != 0);
 
@@ -2090,6 +2116,8 @@ boolean HandleGadgetsKeyInput(Key key)
        strcpy(gi->textinput.last_value, gi->textinput.value);
       else
        gadget_changed = FALSE;
+
+      StopTextInput();
     }
     else if (gi->type & GD_TYPE_SELECTBOX)
     {
@@ -2245,3 +2273,43 @@ boolean HandleGadgetsKeyInput(Key key)
 
   return TRUE;
 }
+
+void DumpGadgetIdentifiers(void)
+{
+  struct GadgetInfo *gi;
+
+  Print("Gadgets on current screen:\n");
+
+  for (gi = gadget_list_first_entry; gi != NULL; gi = gi->next)
+  {
+    if (gi->mapped && gi->image_id != -1)
+    {
+      char *token = getTokenFromImageID(gi->image_id);
+      char *prefix = "gfx.";
+
+      if (strPrefix(token, prefix))
+       token = &token[strlen(prefix)];
+
+      Print("- '%s'\n", token);
+    }
+  }
+
+  Print("Done.\n");
+}
+
+boolean DoGadgetAction(int image_id)
+{
+  struct GadgetInfo *gi;
+
+  for (gi = gadget_list_first_entry; gi != NULL; gi = gi->next)
+  {
+    if (gi->mapped && gi->image_id == image_id)
+    {
+      gi->callback_action(gi);
+
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}