chiark / gitweb /
Patch from James H to centralise some generally useful cursor-
authorSimon Tatham <anakin@pobox.com>
Sat, 13 Sep 2008 18:26:53 +0000 (18:26 +0000)
committerSimon Tatham <anakin@pobox.com>
Sat, 13 Sep 2008 18:26:53 +0000 (18:26 +0000)
handling functionality into misc.c.

[originally from svn r8176]

flip.c
guess.c
inertia.c
midend.c
misc.c
puzzles.h
samegame.c

diff --git a/flip.c b/flip.c
index 10c48250a06e240bfdc74d32296cbca062cafc72..d430217c30d1e35500e22a3ee3afab43f6aadf41 100644 (file)
--- 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 9117e8ef905b1b40785483769be273d02b666b96..e09a066490f625d1bc5f2d662b6b2a98bbc649ae 100644 (file)
--- 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);
index 965f5338a9d35f9164373de15ec1a80f3df0a6cd..aebd3145553a9576a0598ccc5be2ce5fe3acc1cf 100644 (file)
--- 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)
index 215482deba45f02c03e1c4403c93da00352d8a8b..a316bcd3062f92c69fbf5716e7d6931b5c3d2016 100644 (file)
--- 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 d3ab815a6416b7c7d5e5ffdaa983bcad53953884..81aa011a2fa153892520544faae1065b65037ad9 100644 (file)
--- 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: */
index 1b1f013c6a9909ea17d8a772f1c06c7842249537..f2ef978d99d0419fffd4807a4f0cbe9142875a9e 100644 (file)
--- 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
  */
index 8976ad44b50b8d84b0672849c81bf84a7f5a9b5b..2b77c26ed07b052e0a56360800ee8420297907ac 100644 (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) {
        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);