Patch from James H to centralise some generally useful cursor-

handling functionality into misc.c.

[originally from svn r8176]
This commit is contained in:
Simon Tatham
2008-09-13 18:26:53 +00:00
parent fe1b91ac49
commit 5ead207060
7 changed files with 112 additions and 12 deletions

6
flip.c
View File

@ -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; int w = state->w, h = state->h, wh = w * h;
char buf[80], *nullret = NULL; char buf[80], *nullret = NULL;
if (button == LEFT_BUTTON || button == CURSOR_SELECT || if (button == LEFT_BUTTON || IS_CURSOR_SELECT(button)) {
button == ' ' || button == '\r' || button == '\n') {
int tx, ty; int tx, ty;
if (button == LEFT_BUTTON) { if (button == LEFT_BUTTON) {
tx = FROMCOORD(x), ty = FROMCOORD(y); 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 || else if (IS_CURSOR_MOVE(button)) {
button == CURSOR_RIGHT || button == CURSOR_LEFT) {
int dx = 0, dy = 0; int dx = 0, dy = 0;
switch (button) { switch (button) {
case CURSOR_UP: dy = -1; break; case CURSOR_UP: dy = -1; break;

View File

@ -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) if (button == CURSOR_LEFT && ui->peg_cur > 0)
ui->peg_cur--; ui->peg_cur--;
ret = ""; ret = "";
} else if (button == CURSOR_SELECT || button == ' ' || button == '\r' || } else if (IS_CURSOR_SELECT(button)) {
button == '\n') {
ui->display_cur = 1; ui->display_cur = 1;
if (ui->peg_cur == from->params.npegs) { if (ui->peg_cur == from->params.npegs) {
ret = encode_move(from, ui); ret = encode_move(from, ui);

View File

@ -1580,7 +1580,8 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
dir = 1; dir = 1;
else if (button == (MOD_NUM_KEYPAD | '3')) else if (button == (MOD_NUM_KEYPAD | '3'))
dir = 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]; dir = state->soln->list[state->solnpos];
if (dir < 0) if (dir < 0)

View File

@ -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 * like a left click for the benefit of users of other
* implementations. So the last of the above points is modified * implementations. So the last of the above points is modified
* in the presence of an (optional) button priority order. * 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 (IS_MOUSE_DRAG(button) || IS_MOUSE_RELEASE(button)) {
if (me->pressed_mouse_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))); (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. * Now send on the event we originally received.
*/ */

73
misc.c
View File

@ -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); 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: */ /* vim: set shiftwidth=4 tabstop=8: */

View File

@ -46,6 +46,7 @@ enum {
CURSOR_LEFT, CURSOR_LEFT,
CURSOR_RIGHT, CURSOR_RIGHT,
CURSOR_SELECT, CURSOR_SELECT,
CURSOR_SELECT2,
/* made smaller because of 'limited range of datatype' errors. */ /* made smaller because of 'limited range of datatype' errors. */
MOD_CTRL = 0x1000, MOD_CTRL = 0x1000,
@ -60,6 +61,9 @@ enum {
(unsigned)(RIGHT_DRAG - LEFT_DRAG)) (unsigned)(RIGHT_DRAG - LEFT_DRAG))
#define IS_MOUSE_RELEASE(m) ( (unsigned)((m) - LEFT_RELEASE) <= \ #define IS_MOUSE_RELEASE(m) ( (unsigned)((m) - LEFT_RELEASE) <= \
(unsigned)(RIGHT_RELEASE - 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. * 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, void draw_rect_outline(drawing *dr, int x, int y, int w, int h,
int colour); 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 * dsf.c
*/ */

View File

@ -1277,8 +1277,7 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
if (button == RIGHT_BUTTON || button == LEFT_BUTTON) { if (button == RIGHT_BUTTON || button == LEFT_BUTTON) {
tx = FROMCOORD(x); ty= FROMCOORD(y); tx = FROMCOORD(x); ty= FROMCOORD(y);
} else if (button == CURSOR_UP || button == CURSOR_DOWN || } else if (IS_CURSOR_MOVE(button)) {
button == CURSOR_LEFT || button == CURSOR_RIGHT) {
int dx = 0, dy = 0; int dx = 0, dy = 0;
ui->displaysel = 1; ui->displaysel = 1;
dx = (button == CURSOR_LEFT) ? -1 : ((button == CURSOR_RIGHT) ? +1 : 0); 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->xsel = (ui->xsel + state->params.w + dx) % state->params.w;
ui->ysel = (ui->ysel + state->params.h + dy) % state->params.h; ui->ysel = (ui->ysel + state->params.h + dy) % state->params.h;
return ret; return ret;
} else if (button == CURSOR_SELECT || button == ' ' || button == '\r' || } else if (IS_CURSOR_SELECT(button)) {
button == '\n') {
ui->displaysel = 1; ui->displaysel = 1;
tx = ui->xsel; tx = ui->xsel;
ty = ui->ysel; 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 (COL(state, tx, ty) == 0) return NULL;
if (ISSEL(ui,tx,ty)) { if (ISSEL(ui,tx,ty)) {
if (button == RIGHT_BUTTON) if (button == RIGHT_BUTTON || button == CURSOR_SELECT2)
sel_clear(ui, state); sel_clear(ui, state);
else else
ret = sel_movedesc(ui, state); ret = sel_movedesc(ui, state);