ref: 28acb0ebdc2814d94fd11c899afc84a5823432c3
parent: fa23fc3943506b256c08730a9f717642912ced9b
author: Simon Tatham <anakin@pobox.com>
date: Fri Jan 16 13:50:22 EST 2009
Keyboard cursor support for Tents, from James H. [originally from svn r8416]
--- a/puzzles.but
+++ b/puzzles.but
@@ -2006,6 +2006,11 @@
other squares will be affected. (This is useful for clearing the
remainder of a row once you have placed all its tents.)
+You can also use the cursor keys to move around the grid. Pressing the
+return key over an empty square will place a tent, and pressing the
+space bar over an empty square will colour it green; either key will
+clear an occupied square.
+
(All the actions described in \k{common-actions} are also available.)
\H{tents-parameters} \I{parameters, for Tents}Tents parameters
--- a/tents.c
+++ b/tents.c
@@ -1414,6 +1414,8 @@
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)
@@ -1423,6 +1425,7 @@
ui->dex = ui->dey = -1;
ui->drag_button = -1;
ui->drag_ok = FALSE;
+ ui->cx = ui->cy = ui->cdisp = 0;
return ui;
}
@@ -1450,6 +1453,7 @@
int started;
game_params p;
char *drawn;
+ int cx, cy; /* last-drawn cursor pos, or (-1,-1) if absent. */
};
#define PREFERRED_TILESIZE 32
@@ -1514,6 +1518,7 @@
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);
@@ -1525,6 +1530,7 @@
ui->dsx = ui->dex = x;
ui->dsy = ui->dey = y;
ui->drag_ok = TRUE;
+ ui->cdisp = 0;
return ""; /* ui updated */
}
@@ -1531,7 +1537,7 @@
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);
@@ -1608,6 +1614,39 @@
}
}
+ 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;
}
@@ -1856,6 +1895,7 @@
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;
}
@@ -1867,7 +1907,7 @@
}
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;
@@ -1911,6 +1951,12 @@
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, TILESIZE - coff*2, COL_GRID);
+ }
+
unclip(dr);
draw_update(dr, tx+1, ty+1, TILESIZE-1, TILESIZE-1);
}
@@ -1924,7 +1970,14 @@
{
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) {
int ww, wh;
@@ -1975,6 +2028,7 @@
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
@@ -1988,12 +2042,18 @@
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,
@@ -2032,8 +2092,8 @@
* 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)
@@ -2185,3 +2245,5 @@
}
#endif
+
+/* vim: set shiftwidth=4 tabstop=8: */