* buttons.c *
***********************************************************/
+#include <stdarg.h>
+
#include "buttons.h"
#include "tools.h"
#include "misc.h"
BackToFront();
return(return_code);
}
+
+
+/* NEW GADGET STUFF -------------------------------------------------------- */
+
+
+static struct GadgetInfo *gadget_list_first_entry = NULL;
+static struct GadgetInfo *gadget_list_last_entry = NULL;
+
+static struct GadgetInfo *getGadgetInfoFromMousePosition(int mx, int my)
+{
+ struct GadgetInfo *gi = gadget_list_first_entry;
+
+ while (gi)
+ {
+ if (mx >= gi->x && mx < gi->x + gi->width &&
+ my >= gi->y && my < gi->y + gi->height)
+ break;
+
+ gi = gi->next;
+ }
+
+ return gi;
+}
+
+struct GadgetInfo *CreateGadget(int first_tag, ...)
+{
+ struct GadgetInfo *new_gadget = checked_malloc(sizeof(struct GadgetInfo));
+ int tag = first_tag;
+ va_list ap;
+
+ va_start(ap, first_tag);
+
+ /* always start with reliable default values */
+ memset(new_gadget, 0, sizeof(struct GadgetInfo));
+
+ while (tag != GDI_END)
+ {
+ printf("tag: %d\n", tag);
+
+
+ switch(tag)
+ {
+ case GDI_X:
+ new_gadget->x = va_arg(ap, int);
+ break;
+ case GDI_Y:
+ new_gadget->y = va_arg(ap, int);
+ break;
+ case GDI_WIDTH:
+ new_gadget->width = va_arg(ap, int);
+ break;
+ case GDI_HEIGHT:
+ new_gadget->height = va_arg(ap, int);
+ break;
+ case GDI_TYPE:
+ new_gadget->type = va_arg(ap, unsigned long);
+ break;
+ case GDI_STATE:
+ new_gadget->state = va_arg(ap, unsigned long);
+ break;
+ case GDI_ALT_STATE:
+ new_gadget->state = va_arg(ap, boolean);
+ break;
+ case GDI_NUMBER_VALUE:
+ new_gadget->number_value = va_arg(ap, long);
+ break;
+ case GDI_TEXT_VALUE:
+ strcpy(new_gadget->text_value, va_arg(ap, char *));
+ break;
+ case GDI_DESIGN_UNPRESSED:
+ new_gadget->design[GD_BUTTON_UNPRESSED].pixmap = va_arg(ap, Pixmap);
+ new_gadget->design[GD_BUTTON_UNPRESSED].x = va_arg(ap, int);
+ new_gadget->design[GD_BUTTON_UNPRESSED].y = va_arg(ap, int);
+ break;
+ case GDI_DESIGN_PRESSED:
+ new_gadget->design[GD_BUTTON_PRESSED].pixmap = va_arg(ap, Pixmap);
+ new_gadget->design[GD_BUTTON_PRESSED].x = va_arg(ap, int);
+ new_gadget->design[GD_BUTTON_PRESSED].y = va_arg(ap, int);
+ break;
+ case GDI_ALT_DESIGN_UNPRESSED:
+ new_gadget->alt_design[GD_BUTTON_UNPRESSED].pixmap= va_arg(ap, Pixmap);
+ new_gadget->alt_design[GD_BUTTON_UNPRESSED].x = va_arg(ap, int);
+ new_gadget->alt_design[GD_BUTTON_UNPRESSED].y = va_arg(ap, int);
+ break;
+ case GDI_ALT_DESIGN_PRESSED:
+ new_gadget->alt_design[GD_BUTTON_PRESSED].pixmap = va_arg(ap, Pixmap);
+ new_gadget->alt_design[GD_BUTTON_PRESSED].x = va_arg(ap, int);
+ new_gadget->alt_design[GD_BUTTON_PRESSED].y = va_arg(ap, int);
+ break;
+ case GDI_CALLBACK:
+ new_gadget->callback = va_arg(ap, gadget_callback_function);
+ break;
+
+ default:
+ Error(ERR_EXIT, "CreateGadget(): unknown tag %d", tag);
+ }
+
+ tag = va_arg(ap, int); /* read next tag */
+ }
+
+ va_end(ap);
+
+ /* check if gadget complete */
+ if (!new_gadget->design[GD_BUTTON_UNPRESSED].pixmap ||
+ !new_gadget->design[GD_BUTTON_PRESSED].pixmap)
+ Error(ERR_EXIT, "gadget incomplete (missing Pixmap)");
+
+ /* insert new gadget into gloabl 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 DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
+{
+ int state = (pressed ? 1 : 0);
+ struct GadgetDesign *gd = (gi->alt_state ?
+ &gi->alt_design[state] :
+ &gi->design[state]);
+
+ XCopyArea(display, gd->pixmap, drawto, gc,
+ gd->x, gd->y, gi->width, gi->height, gi->x, gi->y);
+
+ if (direct)
+ XCopyArea(display, gd->pixmap, window, gc,
+ gd->x, gd->y, gi->width, gi->height, gi->x, gi->y);
+}
+
+void MapGadget(struct GadgetInfo *gi)
+{
+ gi->mapped = TRUE;
+
+ DrawGadget(gi, (gi->state == GD_BUTTON_PRESSED), TRUE);
+}
+
+void UnmapGadget(struct GadgetInfo *gi)
+{
+ gi->mapped = FALSE;
+}
+
+void HandleGadgets(int mx, int my, int button)
+{
+ static struct GadgetInfo *choice = NULL;
+ static boolean pressed = FALSE;
+ struct GadgetInfo *new_choice;
+
+ if (gadget_list_first_entry == NULL)
+ return;
+
+ new_choice = getGadgetInfoFromMousePosition(mx,my);
+
+ if (button)
+ {
+ if (!motion_status) /* mouse button just pressed */
+ {
+ if (new_choice != NULL)
+ {
+ choice = new_choice;
+ choice->state = GD_BUTTON_PRESSED;
+ choice->event = GD_EVENT_PRESSED;
+ DrawGadget(choice, TRUE, TRUE);
+ choice->callback(choice);
+ pressed = TRUE;
+ }
+ }
+ else /* mouse movement with pressed mouse button */
+ {
+ if ((new_choice == NULL || new_choice != choice) &&
+ choice != NULL && pressed)
+ {
+ choice->state = GD_BUTTON_UNPRESSED;
+ DrawGadget(choice, FALSE, TRUE);
+ pressed = FALSE;
+ }
+ else if (new_choice != NULL && new_choice == choice)
+ {
+ if (!pressed)
+ DrawGadget(choice, TRUE, TRUE);
+ choice->state = GD_BUTTON_PRESSED;
+
+ /*
+ choice->callback(choice);
+ */
+
+ pressed = TRUE;
+ }
+ }
+ }
+ else /* mouse button just released */
+ {
+ if (new_choice != NULL && new_choice == choice && pressed)
+ {
+ choice->state = GD_BUTTON_UNPRESSED;
+ choice->event = GD_EVENT_RELEASED;
+ DrawGadget(choice, FALSE, TRUE);
+ choice->callback(choice);
+ choice = NULL;
+ pressed = FALSE;
+ }
+ else
+ {
+ choice = NULL;
+ pressed = FALSE;
+ }
+ }
+}
int CheckElemButtons(int, int, int);
int CheckCountButtons(int, int, int);
+
+/* NEW GADGET STUFF -------------------------------------------------------- */
+
+
+/* gadget types */
+#define GD_TYPE_NORMAL_BUTTON (1<<0)
+#define GD_TYPE_TWO_STATE_BUTTON (1<<1)
+#define GD_TYPE_DRAWING_AREA (1<<2)
+#define GD_TYPE_TEXTINPUT (1<<3)
+#define GD_TYPE_TEXTOUTPUT (1<<4)
+#define GD_TYPE_NUMBERINPUT (1<<5)
+#define GD_TYPE_NUMBEROUTPUT (1<<6)
+#define GD_TYPE_SCROLLBAR_VERTICAL (1<<7)
+#define GD_TYPE_SCROLLBAR_HORIZONTAL (1<<8)
+
+/* gadget events */
+#define GD_EVENT_PRESSED (1<<0)
+#define GD_EVENT_RELEASED (1<<1)
+#define GD_EVENT_MOVING (1<<2)
+
+/* gadget button states */
+#define GD_BUTTON_UNPRESSED 0
+#define GD_BUTTON_PRESSED 1
+
+/* gadget structure constants */
+#define MAX_GADGET_TEXTSIZE 1024
+
+/* gadget creation tags */
+#define GDI_END 0
+#define GDI_X 1
+#define GDI_Y 2
+#define GDI_WIDTH 3
+#define GDI_HEIGHT 4
+#define GDI_TYPE 5
+#define GDI_STATE 6
+#define GDI_ALT_STATE 7
+#define GDI_NUMBER_VALUE 8
+#define GDI_TEXT_VALUE 9
+#define GDI_DESIGN_UNPRESSED 10
+#define GDI_DESIGN_PRESSED 11
+#define GDI_ALT_DESIGN_UNPRESSED 12
+#define GDI_ALT_DESIGN_PRESSED 13
+#define GDI_EVENT 14
+#define GDI_CALLBACK 15
+
+typedef void (*gadget_callback_function)(void *);
+
+struct GadgetDesign
+{
+ Pixmap pixmap; /* Pixmap with gadget surface */
+ int x, y; /* position of rectangle in Pixmap */
+};
+
+struct GadgetInfo
+{
+ int x, y; /* gadget position */
+ int width, height; /* gadget size */
+ unsigned long type; /* type (button, text input, ...) */
+ unsigned long state; /* state (pressed, released, ...) */
+ boolean alt_state; /* alternative state */
+ boolean mapped; /* gadget is active */
+ long number_value;
+ char text_value[MAX_GADGET_TEXTSIZE];
+ struct GadgetDesign design[2]; /* 0: normal; 1: pressed */
+ struct GadgetDesign alt_design[2]; /* alternative design */
+ unsigned long event; /* actual gadget event */
+ gadget_callback_function callback;
+ struct GadgetInfo *next; /* next list entry */
+};
+
+
+#if 0
+struct NewGadget
+{
+ int x, y; /* screen position */
+ int width, height; /* screen size */
+ unsigned long type; /* type (button, text input, ...) */
+ struct GadgetDesign *design[2]; /* 0: normal; 1: pressed */
+ struct GadgetDesign *alt_design[2]; /* alternative design */
+ unsigned long value_mask; /* actual gadget event */
+};
+#endif
+
+struct GadgetEvent
+{
+ unsigned long state; /* state (pressed, released, ...) */
+ int x,y; /* position inside drawing area */
+};
+
+struct GadgetInfo *CreateGadget(int, ...);
+void FreeGadget(struct GadgetInfo *);
+
+void MapGadget(struct GadgetInfo *);
+void UnmapGadget(struct GadgetInfo *);
+
+void HandleGadgets(int, int, int);
+
#endif
OpenDoor(DOOR_OPEN_1 | DOOR_OPEN_2);
}
+
+
+void test_func(struct GadgetInfo *gi)
+{
+ if (gi->event == GD_EVENT_PRESSED)
+ printf("test_func: GD_EVENT_PRESSED\n");
+ else if (gi->event == GD_EVENT_RELEASED)
+ printf("test_func: GD_EVENT_RELEASED\n");
+ else
+ printf("test_func: ?\n");
+}
+
+
+
+
+
void DrawControlWindow()
{
int i,x,y;
int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
+
+ {
+ Pixmap gd_pixmap = pix[PIX_DOOR];
+ int gd_x1 = DOOR_GFX_PAGEX4 + ED_BUTTON_MINUS_XPOS;
+ int gd_x2 = DOOR_GFX_PAGEX3 + ED_BUTTON_MINUS_XPOS;
+ int gd_y = DOOR_GFX_PAGEY1 + ED_BUTTON_MINUS_YPOS;
+ struct GadgetInfo *gi;
+
+ gi = CreateGadget(GDI_X, 100,
+ GDI_Y, 100,
+ GDI_WIDTH, ED_BUTTON_MINUS_XSIZE,
+ GDI_HEIGHT, ED_BUTTON_MINUS_YSIZE,
+ GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
+ GDI_STATE, GD_BUTTON_UNPRESSED,
+ GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
+ GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
+ GDI_CALLBACK, test_func,
+ GDI_END);
+
+ if (gi == NULL)
+ Error(ERR_EXIT, "cannot create gadget");
+
+ MapGadget(gi);
+ }
+
+
}
void ScrollMiniLevel(int from_x, int from_y, int scroll)