diff --git a/src/land.c b/src/land.c index a0ca39d..de3436d 100644 --- a/src/land.c +++ b/src/land.c @@ -247,8 +247,9 @@ static void outfits_open(void) { snprintf(buf, 128, "%s - Outfits", land_planet->name); secondary_wid = window_create(buf, -1, -1, OUTFITS_WIDTH, OUTFITS_HEIGHT); + /* Will allow buying from keyboard. */ - window_setFptr(secondary_wid, outfits_buy); + window_setAccept(secondary_wid, outfits_buy); /* Buttons. */ window_addButton(secondary_wid, -20, 20, @@ -674,8 +675,11 @@ static void shipyard_buy(char* str) { "Do you really want to spend %s on a new ship?", buf)==0) return; - player_newShip(ship, player->solid->pos.x, player->solid->pos.y, - 0., 0., player->solid->dir); + if(player_newShip(ship, player->solid->pos.x, player->solid->pos.y, + 0., 0., player->solid->dir) != 0) { + /* Player actually oborted naming process. */ + return; + } player->credits -= ship->price; /* Auch! Paying is hard! */ diff --git a/src/menu.c b/src/menu.c index fc4e85a..3577771 100644 --- a/src/menu.c +++ b/src/menu.c @@ -161,6 +161,8 @@ void menu_small(void) { wid = window_create("Menu", -1, -1, MENU_WIDTH, MENU_HEIGHT); + window_setCancel(wid, menu_small_close); + window_addButton(wid, 20, 20 + BUTTON_HEIGHT*2 + 20*2, BUTTON_WIDTH, BUTTON_HEIGHT, "btnResume", "Resume", menu_small_close); @@ -176,9 +178,8 @@ void menu_small(void) { } static void menu_small_close(char* str) { - if(strcmp(str, "btnResume")==0) - window_destroy(window_get("Menu")); - + (void)str; + window_destroy(window_get("Menu")); menu_Close(MENU_SMALL); } diff --git a/src/player.c b/src/player.c index 6e713cf..49c765e 100644 --- a/src/player.c +++ b/src/player.c @@ -216,6 +216,12 @@ void player_new(void) { player_name = dialogue_input("Player Name", 3, 20, "Please tell me your name:"); + /* Player cancelled dialogue. */ + if(player_name == NULL) { + menu_main(); + return; + } + if(lfile_fileExists("saves/%s.ls", player_name)) { r = dialogue_YesNo("Overwrite", "You already have a pilot named %s. Overwrite?", player_name); @@ -311,8 +317,12 @@ static void player_newMake(void) { player_message("Welcome to "APPNAME"!"); player_message("v%d.%d.%d", VMAJOR, VMINOR, VREV); - /* Create the player and start the game. */ - player_newShip(ship, x, y, 0., 0., RNG(0, 359)/180.*M_PI); + /* Try to create the pilot, if fails re-ask for player name. */ + if(player_newShip(ship, x, y, 0., 0., RNG(0, 369)/180.*M_PI) != 0) { + player_new(); + return; + } + space_init(sysname); free(sysname); @@ -321,14 +331,15 @@ static void player_newMake(void) { } /** - * @fn void player_newShip(Ship* ship, double px, double py, + * @fn int player_newShip(Ship* ship, double px, double py, * double vx, double vy, double dir) * * @brief Create a new ship for player. + * @return 0 indicates success, -1 means dialogue was cancelled. * * @sa player_newShipMake */ -void player_newShip(Ship* ship, double px, double py, +int player_newShip(Ship* ship, double px, double py, double vx, double vy, double dir) { char* ship_name; @@ -341,11 +352,18 @@ void player_newShip(Ship* ship, double px, double py, player_vy = vy; player_dir = dir; - ship_name = dialogue_input("Player Name", 3, 20, + ship_name = dialogue_input("Ship Name", 3, 20, "Please name your shiny new %s", ship->name); + + /* Dialogue cancelled. */ + if(ship_name == NULL) + return -1; + player_newShipMake(ship_name); free(ship_name); + + return 0; } /** @@ -357,7 +375,7 @@ static void player_newShipMake(char* name) { Vec2 vp, vv; /* Store the current ship if it exists. */ - if(player) { + if(player != NULL) { player_stack = realloc(player_stack, sizeof(Pilot*)*(player_nstack+1)); player_stack[player_nstack] = pilot_copy(player); player_lstack = realloc(player_lstack, sizeof(char*)*(player_nstack+1)); diff --git a/src/player.h b/src/player.h index e43ba45..d440f3b 100644 --- a/src/player.h +++ b/src/player.h @@ -31,7 +31,7 @@ typedef enum RadarShape_ { RADAR_RECT, RADAR_CIRCLE } RadarShape; /* Creation/Cleanup. */ void player_new(void); -void player_newShip(Ship* ship, double px, double py, +int player_newShip(Ship* ship, double px, double py, double vx, double vy, double dir); void player_cleanup(void); int gui_load(const char* name); diff --git a/src/save.c b/src/save.c index 8cb003d..a1f03a7 100644 --- a/src/save.c +++ b/src/save.c @@ -144,7 +144,7 @@ void load_game_menu(void) { "btnDelete", "Del", load_menu_delete); /* Default action. */ - window_setFptr(wid, load_menu_load); + window_setAccept(wid, load_menu_load); } static void load_menu_close(char* str) { diff --git a/src/toolkit.c b/src/toolkit.c index b3cce92..8525025 100644 --- a/src/toolkit.c +++ b/src/toolkit.c @@ -1,3 +1,9 @@ +/** + * @file toolkit.c + * + * @brief Handle window and widgets. + */ + #include #include "lephisto.h" @@ -92,9 +98,10 @@ typedef struct Window_ { int hidden; /* Is it hidden? */ int focus; /* Which window is focused. */ - /* Pointer to a function to run if user hits 'enter' and no button is focused */ - /* nor any other input thiny that catches 'enter'. */ - void(*def_fptr)(char*); + void(*accept_fptr)(char*); /**< Triggered by hitting 'enter' with no widget + that catches the keypress. */ + void(*cancel_fptr)(char*); /**< Triggered by hitting 'escape' with no + widget that catches the keypress. */ double x,y; /* Position. */ double w,h; /* Dimensions. */ @@ -158,6 +165,7 @@ static void dialogue_alertClose(char* str); static void dialogue_msgClose(char* str); static void dialogue_YesNoClose(char* str); static void dialogue_inputClose(char* str); +static void dialogue_inputCancel(char* str); /* Secondary loop hack. */ static int loop_done; static int toolkit_loop(void); @@ -491,9 +499,10 @@ unsigned int window_create(char* name, const int x, const int y, wdw->id = wid; wdw->name = strdup(name); - wdw->hidden = 0; - wdw->focus = -1; - wdw->def_fptr = NULL; + wdw->hidden = 0; + wdw->focus = -1; + wdw->accept_fptr = NULL; + wdw->cancel_fptr = NULL; wdw->w = (double)w; wdw->h = (double)h; @@ -530,12 +539,40 @@ unsigned int window_create(char* name, const int x, const int y, return wid; } -/* Sets the window's default function. */ -void window_setFptr(const unsigned int wid, void(*fptr)(char*)) { +/** + * @fn void window_setAccept(const unsigned int wid, void(*accept)(char*)) + * + * @brief Set the default accept function of the window. + * + * This function is called whenever 'enter' is pressed and the current widget + * does not catch it. NULL disables the accept function. + * @param wid ID of the window to set the accept function. + * @param accept Function to trigger when window is "accepted". Parameter + * passed is window name. + */ +void window_setAccept(const unsigned int wid, void(*accept)(char*)) { Window* wdw; wdw = window_wget(wid); - if(wdw != NULL) wdw->def_fptr = fptr; + if(wdw != NULL) wdw->accept_fptr = accept; +} + +/** + * @fn void window_setCancel(const unsigned int wid, void(*cancel)(char*)) + * + * @brief Set the default cancel function of the window. + * + * This function is called whenever 'escape' is hit and the current widget + * does not catch it. NULL disables the cancel function. + * @param wid ID of the window to set cancel function. + * @param cancel Function to trigger when window is "cancelled". + * Parameter passed is the window name. + */ +void window_setCancel(const unsigned int wid, void(*cancel)(char*)) { + Window* wdw; + + wdw = window_wget(wid); + if(wdw != NULL) wdw->cancel_fptr = cancel; } /* Destroy a widget. */ @@ -1288,6 +1325,13 @@ static int toolkit_keyEvent(SDL_Event* event) { if(event->type == SDL_KEYDOWN) toolkit_triggerFocus(); return 1; + case SDLK_ESCAPE: + if(event->type == SDL_KEYDOWN) + if(wdw->cancel_fptr != NULL) { + (*wdw->cancel_fptr)(wdw->name); + return 1; + } + return 0; case SDLK_UP: if(event->type == SDL_KEYDOWN) { toolkit_regKey(SDLK_UP); @@ -1391,7 +1435,7 @@ static void toolkit_triggerFocus(void) { wgt->name, wdw->name); break; default: - if(wdw->def_fptr)(*wdw->def_fptr)(wgt->name); + if(wdw->accept_fptr)(*wdw->accept_fptr)(wgt->name); break; } } @@ -1598,6 +1642,7 @@ static void dialogue_YesNoClose(char* str) { /* Toolkit input boxes, return input. */ static unsigned int input_wid = 0; +static int input_cancelled = 0; char* dialogue_input(char* title, int min, int max, const char* fmt, ...) { char msg[512], *input; va_list ap; @@ -1613,12 +1658,16 @@ char* dialogue_input(char* title, int min, int max, const char* fmt, ...) { va_end(ap); } + /* Start out not cancelled. */ + input_cancelled = 0; + /* Get text height. */ h = gl_printHeight(&gl_smallFont, 200, msg); /* Create the window. */ input_wid = window_create(title, -1, -1, 240, h+140); - window_setFptr(input_wid, dialogue_inputClose); + window_setAccept(input_wid, dialogue_inputClose); + window_setCancel(input_wid, dialogue_inputCancel); /* Text. */ window_addText(input_wid, 30, -30, 200, h, 0, "txtInput", &gl_smallFont, &cDConsole, msg); @@ -1632,7 +1681,8 @@ char* dialogue_input(char* title, int min, int max, const char* fmt, ...) { /* Tricky secondary loop. */ input = NULL; - while(!input || ((int)strlen(input) < min)) { + while(!input_cancelled && (!input || + ((int)strlen(input) < min))) { /* Must be longer then min. */ /* Must be longer than min. */ if(input) { dialogue_alert("Input must be at least %d characters long!", min); @@ -1640,11 +1690,14 @@ char* dialogue_input(char* title, int min, int max, const char* fmt, ...) { input = NULL; } - if(toolkit_loop()) /* Error in loop -> quit. */ + if(toolkit_loop() != 0) /* Error in loop -> quit. */ return NULL; /* Save the input. */ - input = strdup(window_getInput(input_wid, "inpInput")); + if(input_cancelled != 0) + input = NULL; + else + input = strdup(window_getInput(input_wid, "inpInput")); } /* Cleanup. */ @@ -1661,6 +1714,11 @@ static void dialogue_inputClose(char* str) { loop_done = 1; } +static void dialogue_inputCancel(char* str) { + input_cancelled = 1; + dialogue_inputClose(str); +} + /* Init. */ int toolkit_init(void) { windows = malloc(sizeof(Window)*MIN_WINDOWS); diff --git a/src/toolkit.h b/src/toolkit.h index 09957b5..077186e 100644 --- a/src/toolkit.h +++ b/src/toolkit.h @@ -53,7 +53,8 @@ int dialogue_YesNo(char* caption, const char* fmt, ...); char* dialogue_input(char* title, int min, int max, const char* fmt, ...); /* Modification. */ -void window_setFptr(const unsigned int wid, void(*fptr)(char*)); +void window_setAccept(const unsigned int wid, void(*fptr)(char*)); +void window_setCancel(const unsigned int wid, void(*cancel)(char*)); /* Text. */ void window_modifyText(const unsigned int wid, char* name, char* newstring); /* Button. */