int nstates, statesize, statepos;
struct midend_state_entry *states;
- void *newgame_undo;
- int newgame_undo_avail, newgame_undo_used;
+ void *newgame_undo_buf;
+ int newgame_undo_len, newgame_undo_size;
game_params *params, *curparams;
game_drawstate *drawstate;
me->random = random_new(randseed, randseedsize);
me->nstates = me->statesize = me->statepos = 0;
me->states = NULL;
- me->newgame_undo = 0;
- me->newgame_undo_avail = me->newgame_undo_used = 0;
+ me->newgame_undo_buf = NULL;
+ me->newgame_undo_size = me->newgame_undo_len = 0;
me->params = ourgame->default_params();
me->game_id_change_notify_function = NULL;
me->game_id_change_notify_ctx = NULL;
if (me->drawing)
drawing_free(me->drawing);
random_free(me->random);
+ sfree(me->newgame_undo_buf);
sfree(me->states);
sfree(me->desc);
sfree(me->privdesc);
static void newgame_serialise_write(void *ctx, void *buf, int len)
{
midend *const me = ctx;
- int new_used;
-
- assert(len < INT_MAX - me->newgame_undo_used);
- new_used = me->newgame_undo_used + len;
- if (new_used > me-> newgame_undo_avail) {
- me->newgame_undo_avail = max(me->newgame_undo_avail, new_used);
- me->newgame_undo_avail *= 2;
- me->newgame_undo = sresize(me->newgame_undo,
- me->newgame_undo_avail, char);
+ int new_len;
+
+ assert(len < INT_MAX - me->newgame_undo_len);
+ new_len = me->newgame_undo_len + len;
+ if (new_len > me->newgame_undo_size) {
+ me->newgame_undo_size = new_len + new_len / 4 + 1024;
+ me->newgame_undo_buf = sresize(me->newgame_undo_buf,
+ me->newgame_undo_size, char);
}
- memcpy(me->newgame_undo + me->newgame_undo_used, buf, len);
- me->newgame_undo_used = new_used;
+ memcpy(me->newgame_undo_buf + me->newgame_undo_len, buf, len);
+ me->newgame_undo_len = new_len;
}
void midend_new_game(midend *me)
{
- me->newgame_undo_used = 0;
+ me->newgame_undo_len = 0;
midend_serialise(me, newgame_serialise_write, me);
midend_stop_anim(me);
int midend_can_undo(midend *me)
{
- return (me->statepos > 1 || me->newgame_undo_used);
+ return (me->statepos > 1 || me->newgame_undo_len);
}
int midend_can_redo(midend *me)
struct newgame_undo_deserialise_read_ctx {
midend *me;
- int size, pos;
+ int len, pos;
};
-int newgame_undo_deserialise_read(void *ctx, void *buf, int len)
+static int newgame_undo_deserialise_read(void *ctx, void *buf, int len)
{
struct newgame_undo_deserialise_read_ctx *const rctx = ctx;
midend *const me = rctx->me;
- int use = min(len, rctx->size - rctx->pos);
- memcpy(buf, me->newgame_undo + rctx->pos, use);
+ int use = min(len, rctx->len - rctx->pos);
+ memcpy(buf, me->newgame_undo_buf + rctx->pos, use);
rctx->pos += use;
return use;
}
me->statepos--;
me->dir = -1;
return 1;
- } else if (me->newgame_undo_used) {
+ } else if (me->newgame_undo_len) {
/* This undo cannot be undone with redo */
struct newgame_undo_deserialise_read_ctx rctx;
rctx.me = me;
- rctx.size = me->newgame_undo_used; /* copy for reentrancy safety */
+ rctx.len = me->newgame_undo_len; /* copy for reentrancy safety */
rctx.pos = 0;
deserialise_error =
midend_deserialise(me, newgame_undo_deserialise_read, &rctx);
- if (deserialise_error)
- /* umm, better to carry on than to crash ? */
- return 0;
+ assert(!deserialise_error);
return 1;
} else
return 0;
* more sophisticated way to decide when to discard the previous
* game state.
*/
- me->newgame_undo_used = 0;
+ me->newgame_undo_len = 0;
{
game_params *tmp;