From 505ea4e519a86e04130db10195e913068c9b7284 Mon Sep 17 00:00:00 2001 From: simon Date: Fri, 16 Jan 2009 18:50:22 +0000 Subject: [PATCH] Keyboard cursor support for Tents, from James H. git-svn-id: svn://svn.tartarus.org/sgt/puzzles@8416 cda61777-01e9-0310-a592-d414129be87e --- puzzles.but | 5 +++++ tents.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/puzzles.but b/puzzles.but index cdb978f..60b675c 100644 --- a/puzzles.but +++ b/puzzles.but @@ -2006,6 +2006,11 @@ blank square in the region you cover will be turned green, and no 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 diff --git a/tents.c b/tents.c index bab0de7..6f6e343 100644 --- a/tents.c +++ b/tents.c @@ -1414,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) @@ -1423,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; } @@ -1450,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 @@ -1514,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); @@ -1525,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); @@ -1608,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; } @@ -1856,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; } @@ -1867,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; @@ -1911,6 +1951,12 @@ 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, TILESIZE - coff*2, COL_GRID); + } + unclip(dr); draw_update(dr, tx+1, ty+1, TILESIZE-1, TILESIZE-1); } @@ -1924,6 +1970,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) { @@ -1975,6 +2028,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 @@ -1988,12 +2042,18 @@ static void int_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate, 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 @@ 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) @@ -2185,3 +2245,5 @@ int main(int argc, char **argv) } #endif + +/* vim: set shiftwidth=4 tabstop=8: */ -- 2.11.0