chiark / gitweb /
Miscellaneous fixes from James Harvey's PalmOS porting work:
authorSimon Tatham <anakin@pobox.com>
Wed, 1 Jun 2005 17:47:56 +0000 (17:47 +0000)
committerSimon Tatham <anakin@pobox.com>
Wed, 1 Jun 2005 17:47:56 +0000 (17:47 +0000)
 - fixed numerous memory leaks (not Palm-specific)
 - corrected a couple of 32-bit-int assumptions (vital for Palm but
   generally a good thing anyway)
 - lifted a few function pointer types into explicit typedefs
   (neutral for me but convenient for the source-munging Perl
   scripts he uses to deal with Palm code segment rules)
 - lifted a few function-level static arrays into global static
   arrays (neutral for me but apparently works round a Palm tools
   bug)
 - a couple more presets in Rectangles (so that Palm, or any other
   slow platform which can't handle the larger sizes easily, can
   still have some variety available)
 - in Solo, arranged a means of sharing scratch space between calls
   to nsolve to prevent a lot of redundant malloc/frees (gives a 10%
   speed increase even on existing platforms)

[originally from svn r5897]

15 files changed:
cube.c
fifteen.c
malloc.c
midend.c
mines.c
net.c
netslide.c
pattern.c
puzzles.h
random.c
rect.c
sixteen.c
solo.c
twiddle.c
windows.c

diff --git a/cube.c b/cube.c
index cb6a1f970c02cc61e26ef6712fd66ea4245f88e6..0ff952fc97b3a6f76d9acce5ddb98f1b4f24a47f 100644 (file)
--- a/cube.c
+++ b/cube.c
@@ -300,10 +300,9 @@ static char *encode_params(game_params *params, int full)
 
     return dupstr(data);
 }
+typedef void (*egc_callback)(void *, struct grid_square *);
 
-static void enum_grid_squares(game_params *params,
-                              void (*callback)(void *, struct grid_square *),
-                              void *ctx)
+static void enum_grid_squares(game_params *params, egc_callback callback, void *ctx)
 {
     const struct solid *solid = solids[params->solid];
 
@@ -979,6 +978,8 @@ static game_state *dup_game(game_state *state)
 
 static void free_game(game_state *state)
 {
+    sfree(state->squares);
+    sfree(state->facecolours);
     sfree(state);
 }
 
@@ -1233,6 +1234,7 @@ static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
         success = align_poly(poly, &from->squares[ret->current], all_pkey);
 
         if (!success) {
+            sfree(poly);
             angle = -angle;
             poly = transform_poly(from->solid,
                                   from->squares[from->current].flip,
@@ -1572,8 +1574,8 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
     }
     sfree(poly);
 
-    draw_update(fe, 0, 0, (int)((bb.r-bb.l+2.0F) * GRID_SCALE),
-                (int)((bb.d-bb.u+2.0F) * GRID_SCALE));
+    game_size(&state->params, &i, &j);
+    draw_update(fe, 0, 0, i, j);
 
     /*
      * Update the status bar.
index 4b37dd71e19da8af45c54014884d49f9e144d696..bf2cdf1ad279aacc9b1bb0628a0448a2843a6ec1 100644 (file)
--- a/fifteen.c
+++ b/fifteen.c
@@ -130,7 +130,7 @@ static game_params *custom_params(config_item *cfg)
 
 static char *validate_params(game_params *params)
 {
-    if (params->w < 2 && params->h < 2)
+    if (params->w < 2 || params->h < 2)
        return "Width and height must both be at least two";
 
     return NULL;
@@ -374,6 +374,7 @@ static game_state *dup_game(game_state *state)
 
 static void free_game(game_state *state)
 {
+    sfree(state->tiles);
     sfree(state);
 }
 
index fd0ddf97c6ca58f278d8a7bca09b0e17f5852ea6..a7fa7c5adc862fb73fd35bea36be457025609c0d 100644 (file)
--- a/malloc.c
+++ b/malloc.c
@@ -10,7 +10,7 @@
  * smalloc should guarantee to return a useful pointer - Halibut
  * can do nothing except die when it's out of memory anyway.
  */
-void *smalloc(int size) {
+void *smalloc(size_t size) {
     void *p;
     p = malloc(size);
     if (!p)
@@ -30,7 +30,7 @@ void sfree(void *p) {
 /*
  * srealloc should guaranteeably be able to realloc NULL
  */
-void *srealloc(void *p, int size) {
+void *srealloc(void *p, size_t size) {
     void *q;
     if (p) {
        q = realloc(p, size);
index cde2729bf959d93bda162e582cdf80633de038ec..b6b17207fcc4d487ce5a7ed3fc96e1e8c6c3351b 100644 (file)
--- a/midend.c
+++ b/midend.c
@@ -96,15 +96,38 @@ midend_data *midend_new(frontend *fe, const game *ourgame)
     return me;
 }
 
+static void midend_free_game(midend_data *me)
+{
+    while (me->nstates > 0)
+       me->ourgame->free_game(me->states[--me->nstates].state);
+
+    if (me->drawstate)
+        me->ourgame->free_drawstate(me->drawstate);
+}
+
 void midend_free(midend_data *me)
 {
+    int i;
+
+    midend_free_game(me);
+
+    random_free(me->random);
     sfree(me->states);
     sfree(me->desc);
     sfree(me->seedstr);
-    random_free(me->random);
     if (me->aux_info)
        me->ourgame->free_aux_info(me->aux_info);
     me->ourgame->free_params(me->params);
+    if (me->npresets) {
+       for (i = 0; i < me->npresets; i++) {
+           sfree(me->presets[i]);
+           sfree(me->preset_names[i]);
+       }
+       sfree(me->presets);
+       sfree(me->preset_names);
+    }
+    if (me->ui)
+        me->ourgame->free_ui(me->ui);
     if (me->curparams)
         me->ourgame->free_params(me->curparams);
     sfree(me->laststatus);
@@ -142,11 +165,7 @@ void midend_force_redraw(midend_data *me)
 
 void midend_new_game(midend_data *me)
 {
-    while (me->nstates > 0)
-       me->ourgame->free_game(me->states[--me->nstates].state);
-
-    if (me->drawstate)
-        me->ourgame->free_drawstate(me->drawstate);
+    midend_free_game(me);
 
     assert(me->nstates == 0);
 
@@ -259,7 +278,7 @@ static void midend_finish_move(midend_data *me)
     midend_set_timer(me);
 }
 
-static void midend_stop_anim(midend_data *me)
+void midend_stop_anim(midend_data *me)
 {
     if (me->oldstate || me->anim_time) {
        midend_finish_move(me);
@@ -299,29 +318,29 @@ static int midend_really_process_key(midend_data *me, int x, int y, int button)
 {
     game_state *oldstate =
         me->ourgame->dup_game(me->states[me->statepos - 1].state);
-    int special = FALSE, gotspecial = FALSE;
+    int special = FALSE, gotspecial = FALSE, ret = 1;
     float anim_time;
 
     if (button == 'n' || button == 'N' || button == '\x0E') {
        midend_stop_anim(me);
        midend_new_game(me);
         midend_redraw(me);
-        return 1;                      /* never animate */
+       goto done;                     /* never animate */
     } else if (button == 'u' || button == 'u' ||
                button == '\x1A' || button == '\x1F') {
        midend_stop_anim(me);
         special = me->states[me->statepos-1].special;
         gotspecial = TRUE;
        if (!midend_undo(me))
-            return 1;
+           goto done;
     } else if (button == 'r' || button == 'R' ||
                button == '\x12' || button == '\x19') {
        midend_stop_anim(me);
        if (!midend_redo(me))
-            return 1;
+            goto done;
     } else if (button == 'q' || button == 'Q' || button == '\x11') {
-       me->ourgame->free_game(oldstate);
-        return 0;
+       ret = 0;
+       goto done;
     } else {
         game_state *s =
             me->ourgame->make_move(me->states[me->statepos-1].state,
@@ -334,7 +353,7 @@ static int midend_really_process_key(midend_data *me, int x, int y, int button)
              * state has been updated and a redraw is called for.
              */
             midend_redraw(me);
-            return 1;
+            goto done;
         } else if (s) {
            midend_stop_anim(me);
             while (me->nstates > me->statepos)
@@ -345,8 +364,7 @@ static int midend_really_process_key(midend_data *me, int x, int y, int button)
             me->statepos = ++me->nstates;
             me->dir = +1;
         } else {
-            me->ourgame->free_game(oldstate);
-            return 1;
+          goto done;
         }
     }
 
@@ -364,7 +382,7 @@ static int midend_really_process_key(midend_data *me, int x, int y, int button)
                                              me->dir, me->ui);
     }
 
-    me->oldstate = oldstate;
+    me->oldstate = oldstate; oldstate = NULL;
     if (anim_time > 0) {
         me->anim_time = anim_time;
     } else {
@@ -377,7 +395,9 @@ static int midend_really_process_key(midend_data *me, int x, int y, int button)
 
     midend_set_timer(me);
 
-    return 1;
+    done:
+    if (oldstate) me->ourgame->free_game(oldstate);
+    return ret;
 }
 
 int midend_process_key(midend_data *me, int x, int y, int button)
@@ -687,21 +707,27 @@ void midend_supersede_game_desc(midend_data *me, char *desc)
 
 config_item *midend_get_config(midend_data *me, int which, char **wintitle)
 {
-    char *titlebuf, *parstr;
+    char *titlebuf, *parstr, *rest;
     config_item *ret;
+    char sep;
 
+    assert(wintitle);
     titlebuf = snewn(40 + strlen(me->ourgame->name), char);
 
     switch (which) {
       case CFG_SETTINGS:
        sprintf(titlebuf, "%s configuration", me->ourgame->name);
-       *wintitle = dupstr(titlebuf);
+       *wintitle = titlebuf;
        return me->ourgame->configure(me->params);
       case CFG_SEED:
       case CFG_DESC:
-       sprintf(titlebuf, "%s %s selection", me->ourgame->name,
+        if (!me->curparams) {
+          sfree(titlebuf);
+          return NULL;
+        }
+        sprintf(titlebuf, "%s %s selection", me->ourgame->name,
                 which == CFG_SEED ? "random" : "game");
-       *wintitle = dupstr(titlebuf);
+        *wintitle = titlebuf;
 
        ret = snewn(2, config_item);
 
@@ -721,21 +747,16 @@ config_item *midend_get_config(midend_data *me, int which, char **wintitle)
          * changes).
          */
         parstr = me->ourgame->encode_params(me->curparams, which == CFG_SEED);
+        assert(parstr);
         if (which == CFG_DESC) {
-            ret[0].sval = snewn(strlen(parstr) + strlen(me->desc) + 2, char);
-            sprintf(ret[0].sval, "%s:%s", parstr, me->desc);
-        } else if (me->seedstr) {
-            ret[0].sval = snewn(strlen(parstr) + strlen(me->seedstr) + 2, char);
-            sprintf(ret[0].sval, "%s#%s", parstr, me->seedstr);
+            rest = me->desc ? me->desc : "";
+            sep = ':';
         } else {
-            /*
-             * If the current game was not randomly generated, the
-             * best we can do is to give a template for typing a
-             * new seed in.
-             */
-            ret[0].sval = snewn(strlen(parstr) + 2, char);
-            sprintf(ret[0].sval, "%s#", parstr);
+            rest = me->seedstr ? me->seedstr : "";
+            sep = '#';
         }
+        ret[0].sval = snewn(strlen(parstr) + strlen(rest) + 2, char);
+        sprintf(ret[0].sval, "%s%c%s", parstr, sep, rest);
         sfree(parstr);
 
        ret[1].type = C_END;
diff --git a/mines.c b/mines.c
index 5afefe682299b760edad1ca9d359687426d572db..50ba8f030f4076e95b3a562d2ed2c674760c2dda 100644 (file)
--- a/mines.c
+++ b/mines.c
@@ -95,24 +95,22 @@ static game_params *default_params(void)
     return ret;
 }
 
+static const struct game_params mines_presets[] = {
+  {9, 9, 10, TRUE},
+  {16, 16, 40, TRUE},
+  {30, 16, 99, TRUE},
+};
+
 static int game_fetch_preset(int i, char **name, game_params **params)
 {
     game_params *ret;
     char str[80];
-    static const struct { int w, h, n; } values[] = {
-        {9, 9, 10},
-        {16, 16, 40},
-        {30, 16, 99},
-    };
 
-    if (i < 0 || i >= lenof(values))
+    if (i < 0 || i >= lenof(mines_presets))
         return FALSE;
 
     ret = snew(game_params);
-    ret->w = values[i].w;
-    ret->h = values[i].h;
-    ret->n = values[i].n;
-    ret->unique = TRUE;
+    *ret = mines_presets[i];
 
     sprintf(str, "%dx%d, %d mines", ret->w, ret->h, ret->n);
 
@@ -558,9 +556,11 @@ static void std_add(struct squaretodo *std, int i)
     std->next[i] = -1;
 }
 
+typedef int (*open_cb)(void *, int, int);
+
 static void known_squares(int w, int h, struct squaretodo *std,
-                         signed char *grid,
-                         int (*open)(void *ctx, int x, int y), void *openctx,
+                          signed char *grid,
+                         open_cb open, void *openctx,
                          int x, int y, int mask, int mine)
 {
     int xx, yy, bit;
@@ -626,11 +626,12 @@ struct perturbations {
  *    steps were required; the exact return value is the number of
  *    perturb calls.
  */
+
+typedef struct perturbations *(*perturb_cb) (void *, signed char *, int, int, int);
+
 static int minesolve(int w, int h, int n, signed char *grid,
-                    int (*open)(void *ctx, int x, int y),
-                    struct perturbations *(*perturb)(void *ctx,
-                                                     signed char *grid,
-                                                     int x, int y, int mask),
+                    open_cb open,
+                     perturb_cb perturb,
                     void *ctx, random_state *rs)
 {
     struct setstore *ss = ss_new();
@@ -2071,7 +2072,7 @@ static char *new_game_desc(game_params *params, random_state *rs,
 
        rsdesc = random_state_encode(rs);
        desc = snewn(strlen(rsdesc) + 100, char);
-       sprintf(desc, "r%d,%c,%s", params->n, params->unique ? 'u' : 'a', rsdesc);
+       sprintf(desc, "r%d,%c,%s", params->n, (char)(params->unique ? 'u' : 'a'), rsdesc);
        sfree(rsdesc);
        return desc;
     }
@@ -2258,6 +2259,7 @@ static game_state *new_game(midend_data *me, game_params *params, char *desc)
     wh = state->w * state->h;
 
     state->layout = snew(struct mine_layout);
+    memset(state->layout, 0, sizeof(struct mine_layout));
     state->layout->refcount = 1;
 
     state->grid = snewn(wh, char);
@@ -2334,6 +2336,7 @@ static game_state *new_game(midend_data *me, game_params *params, char *desc)
        }
 
        ret = open_square(state, x, y);
+        sfree(bmp);
     }
 
     return state;
diff --git a/net.c b/net.c
index 5ef1ba77d97b2bed0f9c5b74f9541e61586f1365..38a025c6a6130fdb640182261222eda465528a14 100644 (file)
--- a/net.c
+++ b/net.c
@@ -149,32 +149,29 @@ static game_params *default_params(void)
     return ret;
 }
 
+static const struct game_params net_presets[] = {
+    {5, 5, FALSE, TRUE, 0.0},
+    {7, 7, FALSE, TRUE, 0.0},
+    {9, 9, FALSE, TRUE, 0.0},
+    {11, 11, FALSE, TRUE, 0.0},
+    {13, 11, FALSE, TRUE, 0.0},
+    {5, 5, TRUE, TRUE, 0.0},
+    {7, 7, TRUE, TRUE, 0.0},
+    {9, 9, TRUE, TRUE, 0.0},
+    {11, 11, TRUE, TRUE, 0.0},
+    {13, 11, TRUE, TRUE, 0.0},
+};
+
 static int game_fetch_preset(int i, char **name, game_params **params)
 {
     game_params *ret;
     char str[80];
-    static const struct { int x, y, wrap; } values[] = {
-        {5, 5, FALSE},
-        {7, 7, FALSE},
-        {9, 9, FALSE},
-        {11, 11, FALSE},
-        {13, 11, FALSE},
-        {5, 5, TRUE},
-        {7, 7, TRUE},
-        {9, 9, TRUE},
-        {11, 11, TRUE},
-        {13, 11, TRUE},
-    };
-
-    if (i < 0 || i >= lenof(values))
+
+    if (i < 0 || i >= lenof(net_presets))
         return FALSE;
 
     ret = snew(game_params);
-    ret->width = values[i].x;
-    ret->height = values[i].y;
-    ret->wrapping = values[i].wrap;
-    ret->unique = TRUE;
-    ret->barrier_probability = 0.0;
+    *ret = net_presets[i];
 
     sprintf(str, "%dx%d%s", ret->width, ret->height,
             ret->wrapping ? " wrapping" : "");
@@ -302,12 +299,8 @@ static game_params *custom_params(config_item *cfg)
 
 static char *validate_params(game_params *params)
 {
-    if (params->width <= 0 && params->height <= 0)
+    if (params->width <= 0 || params->height <= 0)
        return "Width and height must both be greater than zero";
-    if (params->width <= 0)
-       return "Width must be greater than zero";
-    if (params->height <= 0)
-       return "Height must be greater than zero";
     if (params->width <= 1 && params->height <= 1)
        return "At least one of width and height must be greater than one";
     if (params->barrier_probability < 0)
@@ -968,6 +961,7 @@ static void perturb(int w, int h, unsigned char *tiles, int wrapping,
 
        break;
     }
+    sfree(perim2);
 
     if (i == nperim)
        return;                        /* nothing we can do! */
@@ -1944,7 +1938,10 @@ static game_state *make_move(game_state *state, game_ui *ui,
         ret->last_rotate_dir = 0; /* suppress animation */
         ret->last_rotate_x = ret->last_rotate_y = 0;
 
-    } else assert(0);
+    } else {
+       ret = NULL;  /* placate optimisers which don't understand assert(0) */
+       assert(0);
+    }
 
     /*
      * Check whether the game has been completed.
index 5697b2ffaa9dcd0429799d0300ee188bc4a91803..f6282eb9b62d7e4c23ee8dc86d27b52f94326edb 100644 (file)
@@ -161,34 +161,35 @@ static game_params *default_params(void)
     return ret;
 }
 
+static const struct { int x, y, wrap, bprob; const char* desc; }
+netslide_presets[] = {
+    {3, 3, FALSE, 1.0, " easy"},
+    {3, 3, FALSE, 0.0, " medium"},
+    {3, 3, TRUE,  0.0, " hard"},
+    {4, 4, FALSE, 1.0, " easy"},
+    {4, 4, FALSE, 0.0, " medium"},
+    {4, 4, TRUE,  0.0, " hard"},
+    {5, 5, FALSE, 1.0, " easy"},
+    {5, 5, FALSE, 0.0, " medium"},
+    {5, 5, TRUE,  0.0, " hard"},
+};
+
 static int game_fetch_preset(int i, char **name, game_params **params)
 {
     game_params *ret;
     char str[80];
-    static const struct { int x, y, wrap, bprob; const char* desc; } values[] = {
-        {3, 3, FALSE, 1.0, " easy"},
-        {3, 3, FALSE, 0.0, " medium"},
-        {3, 3, TRUE,  0.0, " hard"},
-        {4, 4, FALSE, 1.0, " easy"},
-        {4, 4, FALSE, 0.0, " medium"},
-        {4, 4, TRUE,  0.0, " hard"},
-        {5, 5, FALSE, 1.0, " easy"},
-        {5, 5, FALSE, 0.0, " medium"},
-        {5, 5, TRUE,  0.0, " hard"},
-    };
-
-    if (i < 0 || i >= lenof(values))
+
+    if (i < 0 || i >= lenof(netslide_presets))
         return FALSE;
 
     ret = snew(game_params);
-    ret->width = values[i].x;
-    ret->height = values[i].y;
-    ret->wrapping = values[i].wrap;
-    ret->barrier_probability = values[i].bprob;
+    ret->width = netslide_presets[i].x;
+    ret->height = netslide_presets[i].y;
+    ret->wrapping = netslide_presets[i].wrap;
+    ret->barrier_probability = netslide_presets[i].bprob;
     ret->movetarget = 0;
 
-    sprintf(str, "%dx%d%s", ret->width, ret->height,
-            values[i].desc);
+    sprintf(str, "%dx%d%s", ret->width, ret->height, netslide_presets[i].desc);
 
     *name = dupstr(str);
     *params = ret;
@@ -314,12 +315,8 @@ static game_params *custom_params(config_item *cfg)
 
 static char *validate_params(game_params *params)
 {
-    if (params->width <= 1 && params->height <= 1)
+    if (params->width <= 1 || params->height <= 1)
        return "Width and height must both be greater than one";
-    if (params->width <= 1)
-       return "Width must be greater than one";
-    if (params->height <= 1)
-       return "Height must be greater than one";
     if (params->barrier_probability < 0)
        return "Barrier probability may not be negative";
     if (params->barrier_probability > 1)
index 26201e874b5a92de04583a0e3d82b8e36aa0e743..f8e8fc54b40d5b4349833ba0f38a11bdab06a916 100644 (file)
--- a/pattern.c
+++ b/pattern.c
@@ -11,9 +11,6 @@
 
 #include "puzzles.h"
 
-#define max(x,y) ( (x)>(y) ? (x):(y) )
-#define min(x,y) ( (x)<(y) ? (x):(y) )
-
 enum {
     COL_BACKGROUND,
     COL_EMPTY,
@@ -62,24 +59,26 @@ static game_params *default_params(void)
     return ret;
 }
 
+static const struct game_params pattern_presets[] = {
+    {10, 10},
+    {15, 15},
+    {20, 20},
+#ifndef SLOW_SYSTEM
+    {25, 25},
+    {30, 30},
+#endif
+};
+
 static int game_fetch_preset(int i, char **name, game_params **params)
 {
     game_params *ret;
     char str[80];
-    static const struct { int x, y; } values[] = {
-        {10, 10},
-        {15, 15},
-        {20, 20},
-        {25, 25},
-        {30, 30},
-    };
-
-    if (i < 0 || i >= lenof(values))
+
+    if (i < 0 || i >= lenof(pattern_presets))
         return FALSE;
 
     ret = snew(game_params);
-    ret->w = values[i].x;
-    ret->h = values[i].y;
+    *ret = pattern_presets[i];
 
     sprintf(str, "%dx%d", ret->w, ret->h);
 
@@ -166,12 +165,8 @@ static game_params *custom_params(config_item *cfg)
 
 static char *validate_params(game_params *params)
 {
-    if (params->w <= 0 && params->h <= 0)
+    if (params->w <= 0 || params->h <= 0)
        return "Width and height must both be greater than zero";
-    if (params->w <= 0)
-       return "Width must be greater than zero";
-    if (params->h <= 0)
-       return "Height must be greater than zero";
     return NULL;
 }
 
@@ -494,8 +489,7 @@ static char *new_game_desc(game_params *params, random_state *rs,
 
        ai->w = params->w;
        ai->h = params->h;
-       ai->grid = snewn(ai->w * ai->h, unsigned char);
-       memcpy(ai->grid, grid, ai->w * ai->h);
+        ai->grid = grid;
 
        *aux = ai;
     }
index b8317ee8da5654067426d2ce8c300caad64a2876..8be90095fc19fb3b72ca2b47920200c30af53f69 100644 (file)
--- a/puzzles.h
+++ b/puzzles.h
@@ -5,6 +5,8 @@
 #ifndef PUZZLES_PUZZLES_H
 #define PUZZLES_PUZZLES_H
 
+#include <stdlib.h> /* for size_t */
+
 #ifndef TRUE
 #define TRUE 1
 #endif
 #define STR_INT(x) #x
 #define STR(x) STR_INT(x)
 
+/* NB not perfect because they evaluate arguments multiple times. */
+#define max(x,y) ( (x)>(y) ? (x) : (y) )
+#define min(x,y) ( (x)<(y) ? (x) : (y) )
+
 enum {
-    LEFT_BUTTON = 0x1000,
+    LEFT_BUTTON = 0x0200,
     MIDDLE_BUTTON,
     RIGHT_BUTTON,
     LEFT_DRAG,
@@ -34,10 +40,11 @@ enum {
     CURSOR_LEFT,
     CURSOR_RIGHT,
     
-    MOD_CTRL       = 0x10000000,
-    MOD_SHFT       = 0x20000000,
-    MOD_NUM_KEYPAD = 0x40000000,
-    MOD_MASK       = 0x70000000 /* mask for all modifiers */
+    /* made smaller because of 'limited range of datatype' errors. */
+    MOD_CTRL       = 0x1000,
+    MOD_SHFT       = 0x2000,
+    MOD_NUM_KEYPAD = 0x4000,
+    MOD_MASK       = 0x7000 /* mask for all modifiers */
 };
 
 #define IS_MOUSE_DOWN(m) ( (unsigned)((m) - LEFT_BUTTON) <= \
@@ -108,6 +115,14 @@ struct config_item {
 /*
  * Platform routines
  */
+
+#ifdef DEBUG
+#define debug(x) (debug_printf x)
+void debug_printf(char *fmt, ...);
+#else
+#define debug(x)
+#endif
+
 void fatal(char *fmt, ...);
 void frontend_default_colour(frontend *fe, float *output);
 void draw_text(frontend *fe, int x, int y, int fonttype, int fontsize,
@@ -135,6 +150,7 @@ void midend_set_params(midend_data *me, game_params *params);
 void midend_size(midend_data *me, int *x, int *y);
 void midend_new_game(midend_data *me);
 void midend_restart_game(midend_data *me);
+void midend_stop_anim(midend_data *me);
 int midend_process_key(midend_data *me, int x, int y, int button);
 void midend_force_redraw(midend_data *me);
 void midend_redraw(midend_data *me);
@@ -156,8 +172,8 @@ char *midend_rewrite_statusbar(midend_data *me, char *text);
 /*
  * malloc.c
  */
-void *smalloc(int size);
-void *srealloc(void *p, int size);
+void *smalloc(size_t size);
+void *srealloc(void *p, size_t size);
 void sfree(void *p);
 char *dupstr(const char *s);
 #define snew(type) \
index 08bc6089f65629a2aadb1d4f360ed89dd262f093..107649c733b2cb3e90ce21b90632467fe8bfa488 100644 (file)
--- a/random.c
+++ b/random.c
@@ -264,7 +264,7 @@ unsigned long random_upto(random_state *state, unsigned long limit)
     bits += 3;
     assert(bits < 32);
 
-    max = 1 << bits;
+    max = 1L << bits;
     divisor = max / limit;
     max = limit * divisor;
 
diff --git a/rect.c b/rect.c
index 0eeb704502963252cd147d3e8821875458a95ff1..0448958925f80da18ebd2b65993708ecc5e7a794 100644 (file)
--- a/rect.c
+++ b/rect.c
@@ -98,9 +98,14 @@ static int game_fetch_preset(int i, char **name, game_params **params)
 
     switch (i) {
       case 0: w = 7, h = 7; break;
-      case 1: w = 11, h = 11; break;
-      case 2: w = 15, h = 15; break;
-      case 3: w = 19, h = 19; break;
+      case 1: w = 9, h = 9; break;
+      case 2: w = 11, h = 11; break;
+      case 3: w = 13, h = 13; break;
+      case 4: w = 15, h = 15; break;
+#ifndef SLOW_SYSTEM
+      case 5: w = 17, h = 17; break;
+      case 6: w = 19, h = 19; break;
+#endif
       default: return FALSE;
     }
 
@@ -212,9 +217,9 @@ static game_params *custom_params(config_item *cfg)
 
 static char *validate_params(game_params *params)
 {
-    if (params->w <= 0 && params->h <= 0)
+    if (params->w <= 0 || params->h <= 0)
        return "Width and height must both be greater than zero";
-    if (params->w < 2 && params->h < 2)
+    if (params->w*params->h < 2)
        return "Grid area must be greater than one";
     if (params->expandfactor < 0.0F)
        return "Expansion factor may not be negative";
@@ -2277,16 +2282,15 @@ static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
  * Drawing routines.
  */
 
-#define CORRECT 65536
+#define CORRECT (1L<<16)
 
 #define COLOUR(k) ( (k)==1 ? COL_LINE : COL_DRAG )
-#define MAX(x,y) ( (x)>(y) ? (x) : (y) )
-#define MAX4(x,y,z,w) ( MAX(MAX(x,y),MAX(z,w)) )
+#define MAX4(x,y,z,w) ( max(max(x,y),max(z,w)) )
 
 struct game_drawstate {
     int started;
     int w, h;
-    unsigned int *visible;
+    unsigned long *visible;
 };
 
 static void game_size(game_params *params, int *x, int *y)
@@ -2333,7 +2337,7 @@ static game_drawstate *game_new_drawstate(game_state *state)
     ds->started = FALSE;
     ds->w = state->w;
     ds->h = state->h;
-    ds->visible = snewn(ds->w * ds->h, unsigned int);
+    ds->visible = snewn(ds->w * ds->h, unsigned long);
     for (i = 0; i < ds->w * ds->h; i++)
         ds->visible[i] = 0xFFFF;
 
@@ -2459,7 +2463,7 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
 
     for (x = 0; x < state->w; x++)
        for (y = 0; y < state->h; y++) {
-           unsigned int c = 0;
+           unsigned long c = 0;
 
            if (HRANGE(state,x,y))
                 c |= index(state,hedge,x,y);
@@ -2475,12 +2479,14 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
            if (y+1 < state->h)
                c |= index(state,corners,x,y+1) << 12;
            if (x+1 < state->w && y+1 < state->h)
-               c |= index(state,corners,x+1,y+1) << 14;
+               /* cast to prevent 2<<14 sign-extending on promotion to long */
+               c |= (unsigned long)index(state,corners,x+1,y+1) << 14;
            if (index(state, correct, x, y) && !flashtime)
                c |= CORRECT;
 
            if (index(ds,ds->visible,x,y) != c) {
-               draw_tile(fe, state, x, y, hedge, vedge, corners, c & CORRECT);
+               draw_tile(fe, state, x, y, hedge, vedge, corners,
+                          (c & CORRECT) ? 1 : 0);
                index(ds,ds->visible,x,y) = c;
            }
        }
index 744e01d08b5c85303b492a75d2f464a4a6337db4..feab05dcd3357f66ae4eb7ede3039d49852f6435 100644 (file)
--- a/sixteen.c
+++ b/sixteen.c
@@ -173,7 +173,7 @@ static game_params *custom_params(config_item *cfg)
 
 static char *validate_params(game_params *params)
 {
-    if (params->w < 2 && params->h < 2)
+    if (params->w < 2 || params->h < 2)
        return "Width and height must both be at least two";
 
     return NULL;
@@ -505,6 +505,7 @@ static game_state *dup_game(game_state *state)
 
 static void free_game(game_state *state)
 {
+    sfree(state->tiles);
     sfree(state);
 }
 
diff --git a/solo.c b/solo.c
index 2cd406a04f1ebc8220158f22d7499ded6cb0ae88..c8fac6e513d77ba024e3641d1689f28094aac700 100644 (file)
--- a/solo.c
+++ b/solo.c
@@ -96,8 +96,6 @@ int solver_show_working;
 
 #include "puzzles.h"
 
-#define max(x,y) ((x)>(y)?(x):(y))
-
 /*
  * To save space, I store digits internally as unsigned char. This
  * imposes a hard limit of 255 on the order of the puzzle. Since
@@ -177,8 +175,10 @@ static int game_fetch_preset(int i, char **name, game_params **params)
         { "3x3 Intermediate", { 3, 3, SYMM_ROT2, DIFF_INTERSECT } },
         { "3x3 Advanced", { 3, 3, SYMM_ROT2, DIFF_SET } },
         { "3x3 Unreasonable", { 3, 3, SYMM_ROT2, DIFF_RECURSIVE } },
+#ifndef SLOW_SYSTEM
         { "3x4 Basic", { 3, 4, SYMM_ROT2, DIFF_SIMPLE } },
         { "4x4 Basic", { 4, 4, SYMM_ROT2, DIFF_SIMPLE } },
+#endif
     };
 
     if (i < 0 || i >= lenof(presets))
@@ -844,7 +844,12 @@ static int nsolve_intersect(struct nsolve_usage *usage,
     return ret;
 }
 
+struct nsolve_scratch {
+    unsigned char *grid, *rowidx, *colidx, *set;
+};
+
 static int nsolve_set(struct nsolve_usage *usage,
+                      struct nsolve_scratch *scratch,
                       int start, int step1, int step2
 #ifdef STANDALONE_SOLVER
                       , char *fmt, ...
@@ -853,10 +858,10 @@ static int nsolve_set(struct nsolve_usage *usage,
 {
     int c = usage->c, r = usage->r, cr = c*r;
     int i, j, n, count;
-    unsigned char *grid = snewn(cr*cr, unsigned char);
-    unsigned char *rowidx = snewn(cr, unsigned char);
-    unsigned char *colidx = snewn(cr, unsigned char);
-    unsigned char *set = snewn(cr, unsigned char);
+    unsigned char *grid = scratch->grid;
+    unsigned char *rowidx = scratch->rowidx;
+    unsigned char *colidx = scratch->colidx;
+    unsigned char *set = scratch->set;
 
     /*
      * We are passed a cr-by-cr matrix of booleans. Our first job
@@ -999,10 +1004,6 @@ static int nsolve_set(struct nsolve_usage *usage,
                 }
 
                 if (progress) {
-                    sfree(set);
-                    sfree(colidx);
-                    sfree(rowidx);
-                    sfree(grid);
                     return TRUE;
                 }
             }
@@ -1021,17 +1022,33 @@ static int nsolve_set(struct nsolve_usage *usage,
             break;                     /* done */
     }
 
-    sfree(set);
-    sfree(colidx);
-    sfree(rowidx);
-    sfree(grid);
-
     return FALSE;
 }
 
+static struct nsolve_scratch *nsolve_new_scratch(struct nsolve_usage *usage)
+{
+    struct nsolve_scratch *scratch = snew(struct nsolve_scratch);
+    int cr = usage->cr;
+    scratch->grid = snewn(cr*cr, unsigned char);
+    scratch->rowidx = snewn(cr, unsigned char);
+    scratch->colidx = snewn(cr, unsigned char);
+    scratch->set = snewn(cr, unsigned char);
+    return scratch;
+}
+
+static void nsolve_free_scratch(struct nsolve_scratch *scratch)
+{
+    sfree(scratch->set);
+    sfree(scratch->colidx);
+    sfree(scratch->rowidx);
+    sfree(scratch->grid);
+    sfree(scratch);
+}
+
 static int nsolve(int c, int r, digit *grid)
 {
     struct nsolve_usage *usage;
+    struct nsolve_scratch *scratch;
     int cr = c*r;
     int x, y, n;
     int diff = DIFF_BLOCK;
@@ -1055,6 +1072,8 @@ static int nsolve(int c, int r, digit *grid)
     memset(usage->col, FALSE, cr * cr);
     memset(usage->blk, FALSE, cr * cr);
 
+    scratch = nsolve_new_scratch(usage);
+
     /*
      * Place all the clue numbers we are given.
      */
@@ -1204,7 +1223,7 @@ static int nsolve(int c, int r, digit *grid)
         */
        for (x = 0; x < cr; x += r)
            for (y = 0; y < r; y++)
-                if (nsolve_set(usage, cubepos(x,y,1), r*cr, 1
+                if (nsolve_set(usage, scratch, cubepos(x,y,1), r*cr, 1
 #ifdef STANDALONE_SOLVER
                                , "set elimination, block (%d,%d)", 1+x/r, 1+y
 #endif
@@ -1217,7 +1236,7 @@ static int nsolve(int c, int r, digit *grid)
         * Row-wise set elimination.
         */
        for (y = 0; y < cr; y++)
-            if (nsolve_set(usage, cubepos(0,y,1), cr*cr, 1
+            if (nsolve_set(usage, scratch, cubepos(0,y,1), cr*cr, 1
 #ifdef STANDALONE_SOLVER
                            , "set elimination, row %d", 1+YUNTRANS(y)
 #endif
@@ -1230,7 +1249,7 @@ static int nsolve(int c, int r, digit *grid)
         * Column-wise set elimination.
         */
        for (x = 0; x < cr; x++)
-            if (nsolve_set(usage, cubepos(x,0,1), cr, 1
+            if (nsolve_set(usage, scratch, cubepos(x,0,1), cr, 1
 #ifdef STANDALONE_SOLVER
                            , "set elimination, column %d", 1+x
 #endif
@@ -1246,6 +1265,8 @@ static int nsolve(int c, int r, digit *grid)
        break;
     }
 
+    nsolve_free_scratch(scratch);
+
     sfree(usage->cube);
     sfree(usage->row);
     sfree(usage->col);
@@ -1448,6 +1469,16 @@ static char *new_game_desc(game_params *params, random_state *rs,
            ai->r = r;
            ai->grid = snewn(cr * cr, digit);
            memcpy(ai->grid, grid, cr * cr * sizeof(digit));
+           /*
+            * We might already have written *aux the last time we
+            * went round this loop, in which case we should free
+            * the old aux_info before overwriting it with the new
+            * one.
+            */
+            if (*aux) {
+               sfree((*aux)->grid);
+               sfree(*aux);
+            }
            *aux = ai;
        }
 
index e66bdb0554fbd68367289440d2036c135ed83991..7beedc40ea6256b5e0b435c3ac49e0880cab3f51 100644 (file)
--- a/twiddle.c
+++ b/twiddle.c
@@ -409,7 +409,7 @@ static char *new_game_desc(game_params *params, random_state *rs,
         int k;
 
         k = sprintf(buf, "%d%c", grid[i] / 4,
-                   params->orientable ? "uldr"[grid[i] & 3] : ',');
+                   (char)(params->orientable ? "uldr"[grid[i] & 3] : ','));
 
         ret = sresize(ret, retlen + k + 1, char);
         strcpy(ret + retlen, buf);
@@ -764,6 +764,7 @@ static game_drawstate *game_new_drawstate(game_state *state)
 
 static void game_free_drawstate(game_drawstate *ds)
 {
+    sfree(ds->grid);
     sfree(ds);
 }
 
index 0a61f3c5b2ef68af15ddd7abe34c6511f60bfb53..430fff045ba2c6a3f1244e8129930f943f01fc79 100644 (file)
--- a/windows.c
+++ b/windows.c
@@ -77,13 +77,6 @@ void debug_printf(char *fmt, ...)
     dputs(buf);
     va_end(ap);
 }
-
-#define debug(x) (debug_printf x)
-
-#else
-
-#define debug(x)
-
 #endif
 
 struct font {