From 5ead207060a3e1f74ad6200fdf02934457394bc2 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 13 Sep 2008 18:26:53 +0000 Subject: [PATCH] Patch from James H to centralise some generally useful cursor- handling functionality into misc.c. [originally from svn r8176] --- flip.c | 6 ++--- guess.c | 3 +-- inertia.c | 3 ++- midend.c | 16 ++++++++++++ misc.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ puzzles.h | 15 +++++++++++ samegame.c | 8 +++--- 7 files changed, 112 insertions(+), 12 deletions(-) diff --git a/flip.c b/flip.c index 10c4825..d430217 100644 --- a/flip.c +++ b/flip.c @@ -905,8 +905,7 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, int w = state->w, h = state->h, wh = w * h; char buf[80], *nullret = NULL; - if (button == LEFT_BUTTON || button == CURSOR_SELECT || - button == ' ' || button == '\r' || button == '\n') { + if (button == LEFT_BUTTON || IS_CURSOR_SELECT(button)) { int tx, ty; if (button == LEFT_BUTTON) { tx = FROMCOORD(x), ty = FROMCOORD(y); @@ -936,8 +935,7 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, } } } - else if (button == CURSOR_UP || button == CURSOR_DOWN || - button == CURSOR_RIGHT || button == CURSOR_LEFT) { + else if (IS_CURSOR_MOVE(button)) { int dx = 0, dy = 0; switch (button) { case CURSOR_UP: dy = -1; break; diff --git a/guess.c b/guess.c index 9117e8e..e09a066 100644 --- a/guess.c +++ b/guess.c @@ -758,8 +758,7 @@ static char *interpret_move(game_state *from, game_ui *ui, game_drawstate *ds, if (button == CURSOR_LEFT && ui->peg_cur > 0) ui->peg_cur--; ret = ""; - } else if (button == CURSOR_SELECT || button == ' ' || button == '\r' || - button == '\n') { + } else if (IS_CURSOR_SELECT(button)) { ui->display_cur = 1; if (ui->peg_cur == from->params.npegs) { ret = encode_move(from, ui); diff --git a/inertia.c b/inertia.c index 965f533..aebd314 100644 --- a/inertia.c +++ b/inertia.c @@ -1580,7 +1580,8 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, dir = 1; else if (button == (MOD_NUM_KEYPAD | '3')) dir = 3; - else if (button == ' ' && state->soln && state->solnpos < state->soln->len) + else if (IS_CURSOR_SELECT(button) && + state->soln && state->solnpos < state->soln->len) dir = state->soln->list[state->solnpos]; if (dir < 0) diff --git a/midend.c b/midend.c index 215482d..a316bcd 100644 --- a/midend.c +++ b/midend.c @@ -683,6 +683,14 @@ int midend_process_key(midend *me, int x, int y, int button) * like a left click for the benefit of users of other * implementations. So the last of the above points is modified * in the presence of an (optional) button priority order. + * + * A further addition: we translate certain keyboard presses to + * cursor key 'select' buttons, so that a) frontends don't have + * to translate these themselves (like they do for CURSOR_UP etc), + * and b) individual games don't have to hard-code button presses + * of '\n' etc for keyboard-based cursors. The choice of buttons + * here could eventually be controlled by a runtime configuration + * option. */ if (IS_MOUSE_DRAG(button) || IS_MOUSE_RELEASE(button)) { if (me->pressed_mouse_button) { @@ -712,6 +720,14 @@ int midend_process_key(midend *me, int x, int y, int button) (LEFT_RELEASE - LEFT_BUTTON))); } + /* + * Translate keyboard presses to cursor selection. + */ + if (button == '\n' || button == '\r') + button = CURSOR_SELECT; + if (button == ' ') + button = CURSOR_SELECT2; + /* * Now send on the event we originally received. */ diff --git a/misc.c b/misc.c index d3ab815..81aa011 100644 --- a/misc.c +++ b/misc.c @@ -244,4 +244,77 @@ void draw_rect_outline(drawing *dr, int x, int y, int w, int h, int colour) draw_polygon(dr, coords, 4, -1, colour); } +void move_cursor(int button, int *x, int *y, int maxw, int maxh, int wrap) +{ + int dx = 0, dy = 0; + switch (button) { + case CURSOR_UP: dy = -1; break; + case CURSOR_DOWN: dy = 1; break; + case CURSOR_RIGHT: dx = 1; break; + case CURSOR_LEFT: dx = -1; break; + default: return; + } + if (wrap) { + *x = (*x + dx + maxw) % maxw; + *y = (*y + dy + maxh) % maxh; + } else { + *x = min(max(*x+dx, 0), maxw - 1); + *y = min(max(*y+dy, 0), maxh - 1); + } +} + +/* Used in netslide.c and sixteen.c for cursor movement around edge. */ + +int c2pos(int w, int h, int cx, int cy) +{ + if (cy == -1) + return cx; /* top row, 0 .. w-1 (->) */ + else if (cx == w) + return w + cy; /* R col, w .. w+h -1 (v) */ + else if (cy == h) + return w + h + (w-cx-1); /* bottom row, w+h .. w+h+w-1 (<-) */ + else if (cx == -1) + return w + h + w + (h-cy-1); /* L col, w+h+w .. w+h+w+h-1 (^) */ + + assert(!"invalid cursor pos!"); + return -1; /* not reached */ +} + +void pos2c(int w, int h, int pos, int *cx, int *cy) +{ + int max = w+h+w+h; + + pos = (pos + max) % max; + + if (pos < w) { + *cx = pos; *cy = -1; return; + } + pos -= w; + if (pos < h) { + *cx = w; *cy = pos; return; + } + pos -= h; + if (pos < w) { + *cx = w-pos-1; *cy = h; return; + } + pos -= w; + if (pos < h) { + *cx = -1; *cy = h-pos-1; return; + } + assert(!"invalid pos, huh?"); /* limited by % above! */ +} + +void draw_text_outline(drawing *dr, int x, int y, int fonttype, + int fontsize, int align, + int text_colour, int outline_colour, char *text) +{ + if (outline_colour > -1) { + draw_text(dr, x-1, y, fonttype, fontsize, align, outline_colour, text); + draw_text(dr, x+1, y, fonttype, fontsize, align, outline_colour, text); + draw_text(dr, x, y-1, fonttype, fontsize, align, outline_colour, text); + draw_text(dr, x, y+1, fonttype, fontsize, align, outline_colour, text); + } + draw_text(dr, x, y, fonttype, fontsize, align, text_colour, text); +} + /* vim: set shiftwidth=4 tabstop=8: */ diff --git a/puzzles.h b/puzzles.h index 1b1f013..f2ef978 100644 --- a/puzzles.h +++ b/puzzles.h @@ -46,6 +46,7 @@ enum { CURSOR_LEFT, CURSOR_RIGHT, CURSOR_SELECT, + CURSOR_SELECT2, /* made smaller because of 'limited range of datatype' errors. */ MOD_CTRL = 0x1000, @@ -60,6 +61,9 @@ enum { (unsigned)(RIGHT_DRAG - LEFT_DRAG)) #define IS_MOUSE_RELEASE(m) ( (unsigned)((m) - LEFT_RELEASE) <= \ (unsigned)(RIGHT_RELEASE - LEFT_RELEASE)) +#define IS_CURSOR_MOVE(m) ( (m) == CURSOR_UP || (m) == CURSOR_DOWN || \ + (m) == CURSOR_RIGHT || (m) == CURSOR_LEFT ) +#define IS_CURSOR_SELECT(m) ( (m) == CURSOR_SELECT || (m) == CURSOR_SELECT2) /* * Flags in the back end's `flags' word. @@ -297,6 +301,17 @@ void shuffle(void *array, int nelts, int eltsize, random_state *rs); void draw_rect_outline(drawing *dr, int x, int y, int w, int h, int colour); +void move_cursor(int button, int *x, int *y, int maxw, int maxh, int wrap); + +/* Used in netslide.c and sixteen.c for cursor movement around edge. */ +int c2pos(int w, int h, int cx, int cy); +void pos2c(int w, int h, int pos, int *cx, int *cy); + +/* Draws text with an 'outline' formed by offsetting the text + * by one pixel; useful for highlighting. Outline is omitted if -1. */ +void draw_text_outline(drawing *dr, int x, int y, int fonttype, + int fontsize, int align, + int text_colour, int outline_colour, char *text); /* * dsf.c */ diff --git a/samegame.c b/samegame.c index 8976ad4..2b77c26 100644 --- a/samegame.c +++ b/samegame.c @@ -1277,8 +1277,7 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, if (button == RIGHT_BUTTON || button == LEFT_BUTTON) { tx = FROMCOORD(x); ty= FROMCOORD(y); - } else if (button == CURSOR_UP || button == CURSOR_DOWN || - button == CURSOR_LEFT || button == CURSOR_RIGHT) { + } else if (IS_CURSOR_MOVE(button)) { int dx = 0, dy = 0; ui->displaysel = 1; dx = (button == CURSOR_LEFT) ? -1 : ((button == CURSOR_RIGHT) ? +1 : 0); @@ -1286,8 +1285,7 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, ui->xsel = (ui->xsel + state->params.w + dx) % state->params.w; ui->ysel = (ui->ysel + state->params.h + dy) % state->params.h; return ret; - } else if (button == CURSOR_SELECT || button == ' ' || button == '\r' || - button == '\n') { + } else if (IS_CURSOR_SELECT(button)) { ui->displaysel = 1; tx = ui->xsel; ty = ui->ysel; @@ -1299,7 +1297,7 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, if (COL(state, tx, ty) == 0) return NULL; if (ISSEL(ui,tx,ty)) { - if (button == RIGHT_BUTTON) + if (button == RIGHT_BUTTON || button == CURSOR_SELECT2) sel_clear(ui, state); else ret = sel_movedesc(ui, state); -- 2.30.2