ref: 5ead207060a3e1f74ad6200fdf02934457394bc2
parent: fe1b91ac49cc2f4cd07801535dc19103a8ebeb70
author: Simon Tatham <[email protected]>
date: Sat Sep 13 14:26:53 EDT 2008
Patch from James H to centralise some generally useful cursor- handling functionality into misc.c. [originally from svn r8176]
--- a/flip.c
+++ b/flip.c
@@ -905,8 +905,7 @@
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 @@
}
}
}
- 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;
--- a/guess.c
+++ b/guess.c
@@ -758,8 +758,7 @@
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);
--- a/inertia.c
+++ b/inertia.c
@@ -1580,7 +1580,8 @@
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)
--- a/midend.c
+++ b/midend.c
@@ -683,6 +683,14 @@
* 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) {
@@ -711,6 +719,14 @@
(me, x, y, (me->pressed_mouse_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.
--- a/misc.c
+++ b/misc.c
@@ -244,4 +244,77 @@
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: */
--- a/puzzles.h
+++ b/puzzles.h
@@ -46,6 +46,7 @@
CURSOR_LEFT,
CURSOR_RIGHT,
CURSOR_SELECT,
+ CURSOR_SELECT2,
/* made smaller because of 'limited range of datatype' errors. */
MOD_CTRL = 0x1000,
@@ -60,6 +61,9 @@
(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 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
*/
--- a/samegame.c
+++ b/samegame.c
@@ -1277,8 +1277,7 @@
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 @@
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 @@
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);