X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/cb64d2dd666eb5d02c6bfd8dcb151fd0a16196d6..fad9cc36230d773950fb068f2089232101477820:/midend.c diff --git a/midend.c b/midend.c index a764c77..df661b5 100644 --- a/midend.c +++ b/midend.c @@ -387,37 +387,38 @@ static int midend_really_process_key(midend_data *me, int x, int y, int button) me->ourgame->dup_game(me->states[me->statepos - 1].state); int special = FALSE, gotspecial = FALSE, ret = 1; float anim_time; + game_state *s; + char *movestr; + + movestr = + me->ourgame->interpret_move(me->states[me->statepos-1].state, + me->ui, me->drawstate, x, y, button); - if (button == 'n' || button == 'N' || button == '\x0E') { - midend_stop_anim(me); - midend_new_game(me); - midend_redraw(me); - goto done; /* never animate */ - } else if (button == 'u' || button == 'u' || - button == '\x1A' || button == '\x1F') { - midend_stop_anim(me); - special = special(me->states[me->statepos-1].movetype); - gotspecial = TRUE; - if (!midend_undo(me)) + if (!movestr) { + if (button == 'n' || button == 'N' || button == '\x0E') { + midend_stop_anim(me); + midend_new_game(me); + midend_redraw(me); + goto done; /* never animate */ + } else if (button == 'u' || button == 'u' || + button == '\x1A' || button == '\x1F') { + midend_stop_anim(me); + special = special(me->states[me->statepos-1].movetype); + gotspecial = TRUE; + if (!midend_undo(me)) + goto done; + } else if (button == 'r' || button == 'R' || + button == '\x12' || button == '\x19') { + midend_stop_anim(me); + if (!midend_redo(me)) + goto done; + } else if (button == 'q' || button == 'Q' || button == '\x11') { + ret = 0; + goto done; + } else goto done; - } else if (button == 'r' || button == 'R' || - button == '\x12' || button == '\x19') { - midend_stop_anim(me); - if (!midend_redo(me)) - goto done; - } else if (button == 'q' || button == 'Q' || button == '\x11') { - ret = 0; - goto done; } else { - game_state *s; - char *movestr; - - movestr = - me->ourgame->interpret_move(me->states[me->statepos-1].state, - me->ui, me->drawstate, x, y, button); - if (!movestr) - s = NULL; - else if (!*movestr) + if (!*movestr) s = me->states[me->statepos-1].state; else { s = me->ourgame->execute_move(me->states[me->statepos-1].state, @@ -855,6 +856,8 @@ config_item *midend_get_config(midend_data *me, int which, char **wintitle) static char *midend_game_id_int(midend_data *me, char *id, int defmode) { char *error, *par, *desc, *seed; + game_params *newcurparams, *newparams, *oldparams1, *oldparams2; + int free_params; seed = strchr(id, '#'); desc = strchr(id, ':'); @@ -894,18 +897,24 @@ static char *midend_game_id_int(midend_data *me, char *id, int defmode) } } + /* + * We must be reasonably careful here not to modify anything in + * `me' until we have finished validating things. This function + * must either return an error and do nothing to the midend, or + * return success and do everything; nothing in between is + * acceptable. + */ + newcurparams = newparams = oldparams1 = oldparams2 = NULL; + if (par) { - game_params *tmpparams; - tmpparams = me->ourgame->dup_params(me->params); - me->ourgame->decode_params(tmpparams, par); - error = me->ourgame->validate_params(tmpparams); + newcurparams = me->ourgame->dup_params(me->params); + me->ourgame->decode_params(newcurparams, par); + error = me->ourgame->validate_params(newcurparams); if (error) { - me->ourgame->free_params(tmpparams); + me->ourgame->free_params(newcurparams); return error; } - if (me->curparams) - me->ourgame->free_params(me->curparams); - me->curparams = tmpparams; + oldparams1 = me->curparams; /* * Now filter only the persistent parts of this state into @@ -913,16 +922,50 @@ static char *midend_game_id_int(midend_data *me, char *id, int defmode) * received a params string in which case the whole lot is * persistent. */ + oldparams2 = me->params; if (seed || desc) { - char *tmpstr = me->ourgame->encode_params(tmpparams, FALSE); - me->ourgame->decode_params(me->params, tmpstr); + char *tmpstr; + + newparams = me->ourgame->dup_params(me->params); + + tmpstr = me->ourgame->encode_params(newcurparams, FALSE); + me->ourgame->decode_params(newparams, tmpstr); + sfree(tmpstr); } else { - me->ourgame->free_params(me->params); - me->params = me->ourgame->dup_params(tmpparams); + newparams = me->ourgame->dup_params(newcurparams); } + free_params = TRUE; + } else { + newcurparams = me->curparams; + newparams = me->params; + free_params = FALSE; } + if (desc) { + error = me->ourgame->validate_desc(newparams, desc); + if (error) { + if (free_params) { + if (newcurparams) + me->ourgame->free_params(newcurparams); + if (newparams) + me->ourgame->free_params(newparams); + } + return error; + } + } + + /* + * Now we've got past all possible error points. Update the + * midend itself. + */ + me->params = newparams; + me->curparams = newcurparams; + if (oldparams1) + me->ourgame->free_params(oldparams1); + if (oldparams2) + me->ourgame->free_params(oldparams2); + sfree(me->desc); sfree(me->privdesc); me->desc = me->privdesc = NULL; @@ -930,10 +973,6 @@ static char *midend_game_id_int(midend_data *me, char *id, int defmode) me->seedstr = NULL; if (desc) { - error = me->ourgame->validate_desc(me->params, desc); - if (error) - return error; - me->desc = dupstr(desc); me->genmode = GOT_DESC; sfree(me->aux_info);