Patch from Mark Wooding: one-pixel fix to the alignment of the
[sgt/puzzles] / tents.c
diff --git a/tents.c b/tents.c
index 973c770..eb9df8b 100644 (file)
--- a/tents.c
+++ b/tents.c
@@ -1369,6 +1369,11 @@ static char *solve_game(game_state *state, game_state *currstate,
     }
 }
 
+static int game_can_format_as_text_now(game_params *params)
+{
+    return TRUE;
+}
+
 static char *game_text_format(game_state *state)
 {
     int w = state->p.w, h = state->p.h;
@@ -1409,6 +1414,8 @@ struct game_ui {
     int dex, dey;                      /* coords of drag end */
     int drag_button;                   /* -1 for none, or a button code */
     int drag_ok;                       /* dragged off the window, to cancel */
+
+    int cx, cy, cdisp;                 /* cursor position, and ?display. */
 };
 
 static game_ui *new_ui(game_state *state)
@@ -1418,6 +1425,7 @@ static game_ui *new_ui(game_state *state)
     ui->dex = ui->dey = -1;
     ui->drag_button = -1;
     ui->drag_ok = FALSE;
+    ui->cx = ui->cy = ui->cdisp = 0;
     return ui;
 }
 
@@ -1445,6 +1453,7 @@ struct game_drawstate {
     int started;
     game_params p;
     char *drawn;
+    int cx, cy;         /* last-drawn cursor pos, or (-1,-1) if absent. */
 };
 
 #define PREFERRED_TILESIZE 32
@@ -1509,6 +1518,7 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
                            int x, int y, int button)
 {
     int w = state->p.w, h = state->p.h;
+    char tmpbuf[80];
 
     if (button == LEFT_BUTTON || button == RIGHT_BUTTON) {
         x = FROMCOORD(x);
@@ -1520,13 +1530,14 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
         ui->dsx = ui->dex = x;
         ui->dsy = ui->dey = y;
         ui->drag_ok = TRUE;
+        ui->cdisp = 0;
         return "";             /* ui updated */
     }
 
     if ((IS_MOUSE_DRAG(button) || IS_MOUSE_RELEASE(button)) &&
         ui->drag_button > 0) {
         int xmin, ymin, xmax, ymax;
-        char *buf, *sep, tmpbuf[80];
+        char *buf, *sep;
         int buflen, bufsize, tmplen;
 
         x = FROMCOORD(x);
@@ -1603,6 +1614,39 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
         }
     }
 
+    if (IS_CURSOR_MOVE(button)) {
+        move_cursor(button, &ui->cx, &ui->cy, w, h, 0);
+        ui->cdisp = 1;
+        return "";
+    }
+    if (ui->cdisp) {
+        char rep = 0;
+        int v = state->grid[ui->cy*w+ui->cx];
+
+        if (v != TREE) {
+#ifdef SINGLE_CURSOR_SELECT
+            if (button == CURSOR_SELECT)
+                /* SELECT cycles T, N, B */
+                rep = v == BLANK ? 'T' : v == TENT ? 'N' : 'B';
+#else
+            if (button == CURSOR_SELECT)
+                rep = v == BLANK ? 'T' : 'B';
+            else if (button == CURSOR_SELECT2)
+                rep = v == BLANK ? 'N' : 'B';
+            else if (button == 'T' || button == 'N' || button == 'B')
+                rep = (char)button;
+#endif
+        }
+
+        if (rep) {
+            sprintf(tmpbuf, "%c%d,%d", (int)rep, ui->cx, ui->cy);
+            return dupstr(tmpbuf);
+        }
+    } else if (IS_CURSOR_SELECT(button)) {
+        ui->cdisp = 1;
+        return "";
+    }
+
     return NULL;
 }
 
@@ -1798,7 +1842,8 @@ static void game_compute_size(game_params *params, int tilesize,
                              int *x, int *y)
 {
     /* fool the macros */
-    struct dummy { int tilesize; } dummy = { tilesize }, *ds = &dummy;
+    struct dummy { int tilesize; } dummy, *ds = &dummy;
+    dummy.tilesize = tilesize;
 
     *x = TLBORDER + BRBORDER + TILESIZE * params->w;
     *y = TLBORDER + BRBORDER + TILESIZE * params->h;
@@ -1850,6 +1895,7 @@ static game_drawstate *game_new_drawstate(drawing *dr, game_state *state)
     ds->p = state->p;                  /* structure copy */
     ds->drawn = snewn(w*h, char);
     memset(ds->drawn, MAGIC, w*h);
+    ds->cx = ds->cy = -1;
 
     return ds;
 }
@@ -1861,7 +1907,7 @@ static void game_free_drawstate(drawing *dr, game_drawstate *ds)
 }
 
 static void draw_tile(drawing *dr, game_drawstate *ds,
-                      int x, int y, int v, int printing)
+                      int x, int y, int v, int cur, int printing)
 {
     int tx = COORD(x), ty = COORD(y);
     int cx = tx + TILESIZE/2, cy = ty + TILESIZE/2;
@@ -1905,6 +1951,13 @@ static void draw_tile(drawing *dr, game_drawstate *ds,
         draw_polygon(dr, coords, 3, (printing ? -1 : COL_TENT), COL_TENT);
     }
 
+    if (cur) {
+      int coff = TILESIZE/8;
+      draw_rect_outline(dr, tx + coff, ty + coff,
+                        TILESIZE - coff*2 + 1, TILESIZE - coff*2 + 1,
+                       COL_GRID);
+    }
+
     unclip(dr);
     draw_update(dr, tx+1, ty+1, TILESIZE-1, TILESIZE-1);
 }
@@ -1918,6 +1971,13 @@ static void int_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
 {
     int w = state->p.w, h = state->p.h;
     int x, y, flashing;
+    int cx = -1, cy = -1;
+    int cmoved = 0;
+
+    if (ui) {
+      if (ui->cdisp) { cx = ui->cx; cy = ui->cy; }
+      if (cx != ds->cx || cy != ds->cy) cmoved = 1;
+    }
 
     if (printing || !ds->started) {
        if (!printing) {
@@ -1969,6 +2029,7 @@ static void int_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
     for (y = 0; y < h; y++)
         for (x = 0; x < w; x++) {
             int v = state->grid[y*w+x];
+            int credraw = 0;
 
             /*
              * We deliberately do not take drag_ok into account
@@ -1976,18 +2037,24 @@ static void int_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
              * marginally nicer not to have the drag effects
              * flickering on and off disconcertingly.
              */
-            if (ui->drag_button >= 0)
+            if (ui && ui->drag_button >= 0)
                 v = drag_xform(ui, x, y, v);
 
             if (flashing && (v == TREE || v == TENT))
                 v = NONTENT;
 
-            if (printing || ds->drawn[y*w+x] != v) {
-                draw_tile(dr, ds, x, y, v, printing);
+            if (cmoved) {
+              if ((x == cx && y == cy) ||
+                  (x == ds->cx && y == ds->cy)) credraw = 1;
+            }
+
+            if (printing || ds->drawn[y*w+x] != v || credraw) {
+                draw_tile(dr, ds, x, y, v, (x == cx && y == cy), printing);
                 if (!printing)
                    ds->drawn[y*w+x] = v;
             }
         }
+    if (cmoved) { ds->cx = cx; ds->cy = cy; }
 }
 
 static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
@@ -2026,8 +2093,8 @@ static void game_print_size(game_params *params, float *x, float *y)
      * I'll use 6mm squares by default.
      */
     game_compute_size(params, 600, &pw, &ph);
-    *x = pw / 100.0;
-    *y = ph / 100.0;
+    *x = pw / 100.0F;
+    *y = ph / 100.0F;
 }
 
 static void game_print(drawing *dr, game_state *state, int tilesize)
@@ -2053,7 +2120,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize)
 #endif
 
 const struct game thegame = {
-    "Tents", "games.tents",
+    "Tents", "games.tents", "tents",
     default_params,
     game_fetch_preset,
     decode_params,
@@ -2068,7 +2135,7 @@ const struct game thegame = {
     dup_game,
     free_game,
     TRUE, solve_game,
-    FALSE, game_text_format,
+    FALSE, game_can_format_as_text_now, game_text_format,
     new_ui,
     free_ui,
     encode_ui,
@@ -2086,7 +2153,7 @@ const struct game thegame = {
     TRUE, FALSE, game_print_size, game_print,
     FALSE,                            /* wants_statusbar */
     FALSE, game_timing_state,
-    0,                                /* flags */
+    REQUIRE_RBUTTON,                  /* flags */
 };
 
 #ifdef STANDALONE_SOLVER
@@ -2179,3 +2246,5 @@ int main(int argc, char **argv)
 }
 
 #endif
+
+/* vim: set shiftwidth=4 tabstop=8: */