Patch from Chris Emerson to add a status bar to Rectangles. Apart
[sgt/puzzles] / rect.c
diff --git a/rect.c b/rect.c
index c040efa..95d1d8c 100644 (file)
--- a/rect.c
+++ b/rect.c
@@ -60,8 +60,9 @@ struct game_params {
 #define HRANGE(state,x,y) CRANGE(state,x,y,0,1)
 #define VRANGE(state,x,y) CRANGE(state,x,y,1,0)
 
-#define TILE_SIZE 24
-#define BORDER 18
+#define PREFERRED_TILE_SIZE 24
+#define TILE_SIZE (ds->tilesize)
+#define BORDER (TILE_SIZE * 3 / 4)
 
 #define CORNER_TOLERANCE 0.15F
 #define CENTRE_TOLERANCE 0.15F
@@ -2034,6 +2035,14 @@ struct game_ui {
      * treated as a small drag rather than a click.
      */
     int dragged;
+    /*
+     * These are the co-ordinates of the top-left and bottom-right squares
+     * in the drag box, respectively, or -1 otherwise.
+     */
+    int x1;
+    int y1;
+    int x2;
+    int y2;
 };
 
 static game_ui *new_ui(game_state *state)
@@ -2044,6 +2053,10 @@ static game_ui *new_ui(game_state *state)
     ui->drag_end_x = -1;
     ui->drag_end_y = -1;
     ui->dragged = FALSE;
+    ui->x1 = -1;
+    ui->y1 = -1;
+    ui->x2 = -1;
+    ui->y2 = -1;
     return ui;
 }
 
@@ -2139,20 +2152,11 @@ static void coord_round(float x, float y, int *xr, int *yr)
 static void ui_draw_rect(game_state *state, game_ui *ui,
                          unsigned char *hedge, unsigned char *vedge, int c)
 {
-    int x1, x2, y1, y2, x, y, t;
-
-    x1 = ui->drag_start_x;
-    x2 = ui->drag_end_x;
-    if (x2 < x1) { t = x1; x1 = x2; x2 = t; }
-
-    y1 = ui->drag_start_y;
-    y2 = ui->drag_end_y;
-    if (y2 < y1) { t = y1; y1 = y2; y2 = t; }
-
-    x1 = x1 / 2;               /* rounds down */
-    x2 = (x2+1) / 2;           /* rounds up */
-    y1 = y1 / 2;               /* rounds down */
-    y2 = (y2+1) / 2;           /* rounds up */
+    int x, y;
+    int x1 = ui->x1;
+    int y1 = ui->y1;
+    int x2 = ui->x2;
+    int y2 = ui->y2;
 
     /*
      * Draw horizontal edges of rectangles.
@@ -2188,6 +2192,12 @@ static void game_changed_state(game_ui *ui, game_state *oldstate,
 {
 }
 
+struct game_drawstate {
+    int started;
+    int w, h, tilesize;
+    unsigned long *visible;
+};
+
 static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
                              int x, int y, int button) {
     int xc, yc;
@@ -2216,10 +2226,26 @@ static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
     }
 
     if (xc != ui->drag_end_x || yc != ui->drag_end_y) {
+       int t;
+
         ui->drag_end_x = xc;
         ui->drag_end_y = yc;
         ui->dragged = TRUE;
         active = TRUE;
+
+       ui->x1 = ui->drag_start_x;
+       ui->x2 = ui->drag_end_x;
+       if (ui->x2 < ui->x1) { t = ui->x1; ui->x1 = ui->x2; ui->x2 = t; }
+
+       ui->y1 = ui->drag_start_y;
+       ui->y2 = ui->drag_end_y;
+       if (ui->y2 < ui->y1) { t = ui->y1; ui->y1 = ui->y2; ui->y2 = t; }
+
+       ui->x1 = ui->x1 / 2;               /* rounds down */
+       ui->x2 = (ui->x2+1) / 2;           /* rounds up */
+       ui->y1 = ui->y1 / 2;               /* rounds down */
+       ui->y2 = (ui->y2+1) / 2;           /* rounds up */
+
     }
 
     ret = NULL;
@@ -2271,6 +2297,10 @@ static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
        ui->drag_start_y = -1;
        ui->drag_end_x = -1;
        ui->drag_end_y = -1;
+       ui->x1 = -1;
+       ui->y1 = -1;
+       ui->x2 = -1;
+       ui->y2 = -1;
        ui->dragged = FALSE;
        active = TRUE;
     }
@@ -2292,14 +2322,26 @@ static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
 #define COLOUR(k) ( (k)==1 ? COL_LINE : COL_DRAG )
 #define MAX4(x,y,z,w) ( max(max(x,y),max(z,w)) )
 
-struct game_drawstate {
-    int started;
-    int w, h;
-    unsigned long *visible;
-};
-
-static void game_size(game_params *params, int *x, int *y)
+static void game_size(game_params *params, game_drawstate *ds,
+                      int *x, int *y, int expand)
 {
+    int tsx, tsy, ts;
+    /*
+     * Each window dimension equals the tile size times 1.5 more
+     * than the grid dimension (the border is 3/4 the width of the
+     * tiles).
+     * 
+     * We must cast to unsigned before multiplying by two, because
+     * *x might be INT_MAX.
+     */
+    tsx = 2 * (unsigned)*x / (2 * params->w + 3);
+    tsy = 2 * (unsigned)*y / (2 * params->h + 3);
+    ts = min(tsx, tsy);
+    if (expand)
+        ds->tilesize = ts;
+    else
+        ds->tilesize = min(ts, PREFERRED_TILE_SIZE);
+
     *x = params->w * TILE_SIZE + 2*BORDER + 1;
     *y = params->h * TILE_SIZE + 2*BORDER + 1;
 }
@@ -2343,6 +2385,7 @@ static game_drawstate *game_new_drawstate(game_state *state)
     ds->w = state->w;
     ds->h = state->h;
     ds->visible = snewn(ds->w * ds->h, unsigned long);
+    ds->tilesize = 0;                  /* not decided yet */
     for (i = 0; i < ds->w * ds->h; i++)
         ds->visible[i] = 0xFFFF;
 
@@ -2355,9 +2398,9 @@ static void game_free_drawstate(game_drawstate *ds)
     sfree(ds);
 }
 
-static void draw_tile(frontend *fe, game_state *state, int x, int y,
-               unsigned char *hedge, unsigned char *vedge,
-              unsigned char *corners, int correct)
+static void draw_tile(frontend *fe, game_drawstate *ds, game_state *state,
+                      int x, int y, unsigned char *hedge, unsigned char *vedge,
+                      unsigned char *corners, int correct)
 {
     int cx = COORD(x), cy = COORD(y);
     char str[80];
@@ -2490,16 +2533,36 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
                c |= CORRECT;
 
            if (index(ds,ds->visible,x,y) != c) {
-               draw_tile(fe, state, x, y, hedge, vedge, corners,
+               draw_tile(fe, ds, state, x, y, hedge, vedge, corners,
                           (c & CORRECT) ? 1 : 0);
                index(ds,ds->visible,x,y) = c;
            }
        }
 
+    {
+       char buf[256];
+
+       if (ui->x1 >= 0 && ui->y1 >= 0 &&
+           ui->x2 >= 0 && ui->y2 >= 0) {
+           sprintf(buf, "%dx%d ",
+                   ui->x2-ui->x1,
+                   ui->y2-ui->y1);
+       } else {
+           buf[0] = '\0';
+       }
+
+        if (state->cheated)
+            strcat(buf, "Auto-solved.");
+        else if (state->completed)
+            strcat(buf, "COMPLETED!");
+
+        status_bar(fe, buf);
+    }
+
     if (hedge != state->hedge) {
         sfree(hedge);
         sfree(vedge);
-   }
+    }
 
     sfree(corners);
     sfree(correct);
@@ -2522,7 +2585,7 @@ static float game_flash_length(game_state *oldstate,
 
 static int game_wants_statusbar(void)
 {
-    return FALSE;
+    return TRUE;
 }
 
 static int game_timing_state(game_state *state)