From e6856beb007b3f09036a04290c6b162953ddfece Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Mon, 4 Jan 1999 18:51:46 +0100 Subject: [PATCH] rnd-19990104-2 --- src/buttons.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++---- src/buttons.h | 25 +++++---- src/editor.c | 105 +++++++++++++++++++++++++++--------- src/events.c | 2 + src/main.h | 2 +- src/misc.c | 19 +++++++ src/misc.h | 1 + 7 files changed, 252 insertions(+), 46 deletions(-) diff --git a/src/buttons.c b/src/buttons.c index 2d6c173e..77c37437 100644 --- a/src/buttons.c +++ b/src/buttons.c @@ -1586,7 +1586,35 @@ struct GadgetInfo *CreateGadget(int first_tag, ...) break; case GDI_TEXT_VALUE: - strcpy(new_gadget->text_value, va_arg(ap, char *)); + { + int max_textsize = MAX_GADGET_TEXTSIZE; + + if (new_gadget->text_size) + max_textsize = MIN(new_gadget->text_size, MAX_GADGET_TEXTSIZE - 1); + + strncpy(new_gadget->text_value, va_arg(ap, char *), max_textsize); + new_gadget->text_value[max_textsize] = '\0'; + } + break; + + case GDI_TEXT_SIZE: + { + int tag_value = va_arg(ap, int); + int max_textsize = MIN(tag_value, MAX_GADGET_TEXTSIZE - 1); + + new_gadget->text_size = max_textsize; + new_gadget->text_value[max_textsize] = '\0'; + + if (new_gadget->width == 0 && new_gadget->height == 0) + { + new_gadget->width = (new_gadget->text_size + 1) * FONT2_XSIZE + 6; + new_gadget->height = ED_WIN_COUNT_YSIZE; + } + } + break; + + case GDI_TEXT_BORDER: + new_gadget->text_border = va_arg(ap, int); break; case GDI_DESIGN_UNPRESSED: @@ -1735,12 +1763,52 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct) &gi->alt_design[state] : &gi->design[state]); - if (gi->type != GD_TYPE_NORMAL_BUTTON && - gi->type != GD_TYPE_RADIO_BUTTON) - return; + switch (gi->type) + { + case GD_TYPE_NORMAL_BUTTON: + case GD_TYPE_RADIO_BUTTON: + XCopyArea(display, gd->pixmap, drawto, gc, + gd->x, gd->y, gi->width, gi->height, gi->x, gi->y); + break; - XCopyArea(display, gd->pixmap, drawto, gc, - gd->x, gd->y, gi->width, gi->height, gi->x, gi->y); + case GD_TYPE_TEXTINPUT: + { + int i; + + /* left part of gadget */ + XCopyArea(display, gd->pixmap, drawto, gc, + gd->x, gd->y, + gi->text_border, gi->height, + gi->x, gi->y); + + /* middle part of gadget */ + for (i=0; i<=gi->text_size; i++) + XCopyArea(display, gd->pixmap, drawto, gc, + gd->x + gi->text_border, gd->y, + FONT2_XSIZE, gi->height, + gi->x + gi->text_border + i * FONT2_XSIZE, gi->y); + + /* right part of gadget */ + XCopyArea(display, gd->pixmap, drawto, gc, + gd->x + ED_WIN_COUNT_XSIZE - gi->text_border, gd->y, + gi->text_border, gi->height, + gi->x + gi->width - gi->text_border, gi->y); + + /* gadget text value */ + DrawText(gi->x + gi->text_border, gi->y + gi->text_border, + gi->text_value, FS_SMALL, (pressed ? FC_GREEN : FC_YELLOW)); + + /* draw cursor, if active */ + DrawText(gi->x + gi->text_border + strlen(gi->text_value)*FONT2_XSIZE, + gi->y + gi->text_border, + (pressed ? "<" : " "), + FS_SMALL, FC_RED); + } + break; + + default: + return; + } if (direct) XCopyArea(display, drawto, window, gc, @@ -1780,9 +1848,10 @@ void UnmapGadget(struct GadgetInfo *gi) gi->mapped = FALSE; } +static struct GadgetInfo *last_gi = NULL; + void HandleGadgets(int mx, int my, int button) { - static struct GadgetInfo *last_gi = NULL; static unsigned long pressed_delay = 0; struct GadgetInfo *new_gi, *gi; @@ -1793,11 +1862,25 @@ void HandleGadgets(int mx, int my, int button) boolean gadget_released; boolean gadget_released_off_borders; - if (gadget_list_first_entry == NULL) + if (gadget_list_first_entry == NULL) /* no gadgets defined */ return; new_gi = getGadgetInfoFromMousePosition(mx, my); + /* if mouse button pressed outside text input gadget, deactivate it */ + if (last_gi && last_gi->type == GD_TYPE_TEXTINPUT && + button != 0 && new_gi != last_gi && !motion_status) + { + struct GadgetInfo *gi = last_gi; + + DrawGadget(gi, DG_UNPRESSED, DG_DIRECT); + + if (gi->event_mask & GD_EVENT_TEXT_LEAVING) + gi->callback(gi); + + last_gi = NULL; + } + gadget_pressed = (button != 0 && last_gi == NULL && new_gi != NULL && !motion_status); gadget_pressed_repeated = @@ -1811,12 +1894,15 @@ void HandleGadgets(int mx, int my, int button) gadget_released_off_borders = (button == 0 && last_gi != NULL && new_gi != last_gi); + /* if new gadget pressed, store this gadget */ if (gadget_pressed) last_gi = new_gi; + /* 'gi' is actually handled gadget */ gi = last_gi; - if (button == 0) + /* 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 (gi) @@ -1890,7 +1976,8 @@ void HandleGadgets(int mx, int my, int button) if (gadget_moving_off_borders) { - if (gi->state == GD_BUTTON_PRESSED) + if (gi->state == GD_BUTTON_PRESSED && + gi->type != GD_TYPE_TEXTINPUT) DrawGadget(gi, DG_UNPRESSED, DG_DIRECT); gi->state = GD_BUTTON_UNPRESSED; @@ -1904,7 +1991,8 @@ void HandleGadgets(int mx, int my, int button) if (gadget_released) { - DrawGadget(gi, DG_UNPRESSED, DG_DIRECT); + if (gi->type != GD_TYPE_TEXTINPUT) + DrawGadget(gi, DG_UNPRESSED, DG_DIRECT); gi->state = GD_BUTTON_UNPRESSED; gi->event.type = GD_EVENT_RELEASED; @@ -1922,3 +2010,37 @@ void HandleGadgets(int mx, int my, int button) gi->callback(gi); } } + +void HandleGadgetsKeyInput(KeySym key) +{ + struct GadgetInfo *gi = last_gi; + int text_length; + char letter; + + if (gi == NULL || gi->type != GD_TYPE_TEXTINPUT) + return; + + text_length = strlen(gi->text_value); + letter = getCharFromKeySym(key); + + if (letter && text_length < gi->text_size) + { + gi->text_value[text_length] = letter; + gi->text_value[text_length + 1] = '\0'; + DrawGadget(gi, DG_PRESSED, DG_DIRECT); + } + else if ((key == XK_Delete || key == XK_BackSpace) && text_length > 0) + { + gi->text_value[text_length - 1] = '\0'; + DrawGadget(gi, DG_PRESSED, DG_DIRECT); + } + else if (key == XK_Return) + { + DrawGadget(gi, DG_UNPRESSED, DG_DIRECT); + + if (gi->event_mask & GD_EVENT_TEXT_RETURN) + gi->callback(gi); + + last_gi = NULL; + } +} diff --git a/src/buttons.h b/src/buttons.h index e3ba29be..5dfeb377 100644 --- a/src/buttons.h +++ b/src/buttons.h @@ -288,6 +288,8 @@ int CheckCountButtons(int, int, int); #define GD_EVENT_MOVING (1<<2) #define GD_EVENT_REPEATED (1<<3) #define GD_EVENT_OFF_BORDERS (1<<4) +#define GD_EVENT_TEXT_RETURN (1<<5) +#define GD_EVENT_TEXT_LEAVING (1<<6) /* gadget button states */ #define GD_BUTTON_UNPRESSED 0 @@ -311,15 +313,17 @@ int CheckCountButtons(int, int, int); #define GDI_NUMBER_MIN 11 #define GDI_NUMBER_MAX 12 #define GDI_TEXT_VALUE 13 -#define GDI_DESIGN_UNPRESSED 14 -#define GDI_DESIGN_PRESSED 15 -#define GDI_ALT_DESIGN_UNPRESSED 16 -#define GDI_ALT_DESIGN_PRESSED 17 -#define GDI_EVENT_MASK 18 -#define GDI_EVENT 19 -#define GDI_CALLBACK 20 -#define GDI_AREA_SIZE 21 -#define GDI_ITEM_SIZE 22 +#define GDI_TEXT_SIZE 14 +#define GDI_TEXT_BORDER 15 +#define GDI_DESIGN_UNPRESSED 16 +#define GDI_DESIGN_PRESSED 17 +#define GDI_ALT_DESIGN_UNPRESSED 18 +#define GDI_ALT_DESIGN_PRESSED 19 +#define GDI_EVENT_MASK 20 +#define GDI_EVENT 21 +#define GDI_CALLBACK 22 +#define GDI_AREA_SIZE 23 +#define GDI_ITEM_SIZE 24 typedef void (*gadget_callback_function)(void *); @@ -356,6 +360,8 @@ struct GadgetInfo boolean mapped; /* gadget is active */ long number_value; char text_value[MAX_GADGET_TEXTSIZE]; + int text_size; /* maximal size of input text */ + int text_border; /* border size of text input gadget */ struct GadgetDesign design[2]; /* 0: normal; 1: pressed */ struct GadgetDesign alt_design[2]; /* alternative design */ unsigned long event_mask; /* possible events for this gadget */ @@ -374,5 +380,6 @@ void MapGadget(struct GadgetInfo *); void UnmapGadget(struct GadgetInfo *); void HandleGadgets(int, int, int); +void HandleGadgetsKeyInput(KeySym); #endif diff --git a/src/editor.c b/src/editor.c index 1e4d4f5f..d92e2778 100644 --- a/src/editor.c +++ b/src/editor.c @@ -121,7 +121,10 @@ #define ED_CTRL_ID_ELEMCONT_7 34 #define ED_CTRL_ID_AMOEBA_CONTENT 35 -#define ED_NUM_GADGETS 36 +/* text input identifiers */ +#define ED_CTRL_ID_LEVEL_NAME 36 + +#define ED_NUM_GADGETS 37 /* values for counter gadgets */ #define ED_COUNTER_SCORE 0 @@ -145,9 +148,10 @@ static struct static void DrawDrawingWindow(); static void DrawPropertiesWindow(); static void CopyLevelToUndoBuffer(); -static void HandleDrawingAreas(struct GadgetInfo *); -static void HandleCounterButtons(struct GadgetInfo *); static void HandleControlButtons(struct GadgetInfo *); +static void HandleCounterButtons(struct GadgetInfo *); +static void HandleDrawingAreas(struct GadgetInfo *); +static void HandleTextInputGadgets(struct GadgetInfo *); static struct GadgetInfo *level_editor_gadget[ED_NUM_GADGETS]; static boolean level_editor_gadgets_created = FALSE; @@ -796,6 +800,39 @@ static void CreateDrawingAreas() level_editor_gadget[id] = gi; } +static void CreateTextInputGadgets() +{ + Pixmap gd_pixmap = pix[PIX_DOOR]; + int gd_x, gd_y; + struct GadgetInfo *gi; + unsigned long event_mask; + int id; + + gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS; + gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS; + event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING; + + /* text input gadget for the level name */ + id = ED_CTRL_ID_LEVEL_NAME; + gi = CreateGadget(GDI_CUSTOM_ID, id, + GDI_X, SX + ED_COUNT_ELEMCONT_XPOS, + GDI_Y, SY + ED_AREA_ELEMCONT_YPOS + 3 * TILEX, + GDI_TYPE, GD_TYPE_TEXTINPUT, + GDI_TEXT_VALUE, level.name, + GDI_TEXT_SIZE, 30, + GDI_TEXT_BORDER, 3, + GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x, gd_y, + GDI_DESIGN_PRESSED, gd_pixmap, gd_x, gd_y, + GDI_EVENT_MASK, event_mask, + GDI_CALLBACK, HandleTextInputGadgets, + GDI_END); + + if (gi == NULL) + Error(ERR_EXIT, "cannot create gadget"); + + level_editor_gadget[id] = gi; +} + static void CreateLevelEditorGadgets() { if (level_editor_gadgets_created) @@ -804,6 +841,7 @@ static void CreateLevelEditorGadgets() CreateControlButtons(); CreateCounterButtons(); CreateDrawingAreas(); + CreateTextInputGadgets(); level_editor_gadgets_created = TRUE; } @@ -829,6 +867,11 @@ static void MapDrawingArea(int id) MapGadget(level_editor_gadget[id]); } +static void MapTextInputGadget(int id) +{ + MapGadget(level_editor_gadget[id]); +} + static void MapMainDrawingArea() { MapDrawingArea(ED_CTRL_ID_DRAWING_LEVEL); @@ -2086,6 +2129,9 @@ static void DrawPropertiesWindow() else DrawElementContentAreas(); } + + /* TEST ONLY: level name text input gadget */ + MapTextInputGadget(ED_CTRL_ID_LEVEL_NAME); } static void swap_numbers(int *i1, int *i2) @@ -2478,7 +2524,11 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) int new_element; int button = gi->event.button; int sx = gi->event.x, sy = gi->event.y; + int min_sx = 0, min_sy = 0; + int max_sx = gi->drawing.area_xsize - 1, max_sy = gi->drawing.area_ysize - 1; int lx, ly; + int min_lx = 0, min_ly = 0; + int max_lx = lev_fieldx - 1, max_ly = lev_fieldy - 1; int x, y; /* @@ -2489,23 +2539,24 @@ static void HandleDrawingAreas(struct GadgetInfo *gi) button_press_event = (gi->event.type == GD_EVENT_PRESSED); button_release_event = (gi->event.type == GD_EVENT_RELEASED); + /* make sure to stay inside drawing area boundaries */ + sx = (sx < min_sx ? min_sx : sx > max_sx ? max_sx : sx); + sy = (sy < min_sy ? min_sy : sy > max_sy ? max_sy : sy); + if (draw_level) { - sx = (sx < 0 ? 0 : sx > 2*SCR_FIELDX - 1 ? 2*SCR_FIELDX - 1 : sx); - sy = (sy < 0 ? 0 : sy > 2*SCR_FIELDY - 1 ? 2*SCR_FIELDY - 1 : sy); + /* get positions inside level field */ lx = sx + level_xpos; ly = sy + level_ypos; - lx = (lx < 0 ? 0 : lx > lev_fieldx - 1 ? lev_fieldx - 1 : lx); - ly = (ly < 0 ? 0 : ly > lev_fieldy - 1 ? lev_fieldy - 1 : ly); + /* make sure to stay inside level field boundaries */ + lx = (lx < min_lx ? min_lx : lx > max_lx ? max_lx : lx); + ly = (ly < min_ly ? min_ly : ly > max_ly ? max_ly : ly); + + /* correct drawing area positions accordingly */ sx = lx - level_xpos; sy = ly - level_ypos; } - else - { - sx = (sx < 0 ? 0 : sx > 2 ? 2 : sx); - sy = (sy < 0 ? 0 : sy > 2 ? 2 : sy); - } if (button_press_event) started_inside_drawing_area = inside_drawing_area; @@ -2971,19 +3022,7 @@ void HandleLevelEditorKeyInput(KeySym key) { if (edit_mode == ED_MODE_DRAWING && drawing_function == ED_CTRL_ID_TEXT) { - char *keyname = getKeyNameFromKeySym(key); - char letter = 0; - - if (strlen(keyname) == 1) - letter = keyname[0]; - else if (strcmp(keyname, "space") == 0) - letter = ' '; - else if (strcmp(keyname, "less") == 0) - letter = '<'; - else if (strcmp(keyname, "equal") == 0) - letter = '='; - else if (strcmp(keyname, "greater") == 0) - letter = '>'; + char letter = getCharFromKeySym(key); /* map lower case letters to upper case */ if (letter >= 'a' && letter <= 'z') @@ -3003,3 +3042,19 @@ void HandleLevelEditorKeyInput(KeySym key) DrawLevelText(0, 0, 0, TEXT_NEWLINE); } } + + +static void HandleTextInputGadgets(struct GadgetInfo *gi) +{ + int id = gi->custom_id; + + switch (id) + { + case ED_CTRL_ID_LEVEL_NAME: + strcpy(level.name, gi->text_value); + break; + + default: + break; + } +} diff --git a/src/events.c b/src/events.c index f4ab83e3..e3ebe5f9 100644 --- a/src/events.c +++ b/src/events.c @@ -461,6 +461,8 @@ void HandleKey(KeySym key, int key_status) + HandleGadgetsKeyInput(key); + switch(game_status) { case TYPENAME: diff --git a/src/main.h b/src/main.h index 26251e84..8b20fb7a 100644 --- a/src/main.h +++ b/src/main.h @@ -523,7 +523,7 @@ extern int num_bg_loops; #define MINI_MORE_STARTX 0 #define MINI_MORE_STARTY 160 #define MICRO_MORE_STARTX 0 -#define MICRO_MORE_STARTY 208 +#define MICRO_MORE_STARTY 240 #define MORE_PER_LINE 16 #define MINI_MORE_PER_LINE 16 #define MICRO_MORE_PER_LINE 16 diff --git a/src/misc.c b/src/misc.c index 7f6bc4bc..3b3f6a04 100644 --- a/src/misc.c +++ b/src/misc.c @@ -819,6 +819,25 @@ KeySym getKeySymFromX11KeyName(char *x11name) return keysym; } +char getCharFromKeySym(KeySym keysym) +{ + char *keyname = getKeyNameFromKeySym(keysym); + char letter = 0; + + if (strlen(keyname) == 1) + letter = keyname[0]; + else if (strcmp(keyname, "space") == 0) + letter = ' '; + else if (strcmp(keyname, "less") == 0) + letter = '<'; + else if (strcmp(keyname, "equal") == 0) + letter = '='; + else if (strcmp(keyname, "greater") == 0) + letter = '>'; + + return letter; +} + #define TRANSLATE_JOYSYMBOL_TO_JOYNAME 0 #define TRANSLATE_JOYNAME_TO_JOYSYMBOL 1 diff --git a/src/misc.h b/src/misc.h index ae8ae79e..c1c18bb5 100644 --- a/src/misc.h +++ b/src/misc.h @@ -58,6 +58,7 @@ void *checked_calloc(unsigned long); char *getKeyNameFromKeySym(KeySym); char *getX11KeyNameFromKeySym(KeySym); KeySym getKeySymFromX11KeyName(char *); +char getCharFromKeySym(KeySym); char *getJoyNameFromJoySymbol(int); int getJoySymbolFromJoyName(char *); int getJoystickNrFromDeviceName(char *); -- 2.34.1