ref: 78bc9ea7f79f379634f822d5f95242900f5716b9
parent: 9aa7b7cdfb2bcd200f45941a58d6ae698882a2d4
author: Franklin Wei <franklin@rockbox.org>
date: Mon Jul 6 18:06:30 EDT 2020
Add method for frontends to query the backend's cursor location. The Rockbox frontend allows games to be displayed in a "zoomed-in" state targets with small displays. Currently we use a modal interface -- a "viewing" mode in which the cursor keys are used to pan around the rendered bitmap; and an "interaction" mode that actually sends keys to the game. This commit adds a midend_get_cursor_location() function to allow the frontend to retrieve the backend's cursor location or other "region of interest" -- such as the player location in Cube or Inertia. With this information, the Rockbox frontend can now intelligently follow the cursor around in the zoomed-in state, eliminating the need for a modal interface.
--- a/blackbox.c
+++ b/blackbox.c
@@ -1098,6 +1098,20 @@
return NULL;
}
+
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cur_visible) {
+ *x = TODRAW(ui->cur_x);
+ *y = TODRAW(ui->cur_y);
+ *w = *h = TILE_SIZE;
+ }
+}
+
/* ----------------------------------------------------------------------
* Drawing routines.
*/
@@ -1542,6 +1556,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
--- a/bridges.c
+++ b/bridges.c
@@ -2146,6 +2146,20 @@
bool started, dragging;
};
+
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cur_visible) {
+ *x = COORD(ui->cur_x);
+ *y = COORD(ui->cur_y);
+ *w = *h = TILE_SIZE;
+ }
+}
+
/*
* The contents of ds->grid are complicated, because of the circular
* islands which overlap their own grid square into neighbouring
@@ -3267,6 +3281,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/cube.c
+++ b/cube.c
@@ -1535,6 +1535,27 @@
sfree(ds);
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ struct bbox bb;
+
+ bb.l = 2.0F * (params->d1 + params->d2);
+ bb.r = -2.0F * (params->d1 + params->d2);
+ bb.u = 2.0F * (params->d1 + params->d2);
+ bb.d = -2.0F * (params->d1 + params->d2);
+
+ find_bbox_callback(&bb, state->grid->squares + state->current);
+
+ *x = ((int)(bb.l * GRID_SCALE) + ds->ox);
+ *y = ((int)(bb.u * GRID_SCALE) + ds->oy);
+ *w = (bb.r - bb.l) * GRID_SCALE;
+ *h = (bb.d - bb.u) * GRID_SCALE;
+}
+
static void game_redraw(drawing *dr, game_drawstate *ds,
const game_state *oldstate, const game_state *state,
int dir, const game_ui *ui,
@@ -1762,6 +1783,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
--- a/devel.but
+++ b/devel.but
@@ -1289,6 +1289,51 @@
to achieve this, its \cw{flash_length()} function has to store a
flag in the \c{game_ui} to indicate which flash type is required.)
+\S{backend-get-cursor-location} \cw{get_cursor_location()}
+
+\c void (*get_cursor_location)(const game_ui *ui,
+\c const game_drawstate *ds,
+\c const game_state *state,
+\c const game_params *params,
+\c int *x, int *y,
+\c int *w, int *h);
+
+This function queries the backend for the rectangular region
+containing the cursor (in games that have one), or other region of
+interest.
+
+This function is called by only
+\cw{midend_get_cursor_location()}(\k{midend-get-cursor-location}). Its
+purpose is to allow front ends to query the location of the backend's
+cursor. With knowledge of this location, a front end can, for example,
+ensure that the region of interest remains visible if the puzzle is
+too big to fit on the screen at once.
+
+On returning, \cw{*x}, \cw{*y} should be set to the X and Y
+coordinates of the upper-left corner of the rectangular region of
+interest, and \cw{*w} and \cw{*h} should be the width and height of
+that region, respectively. In the event that a cursor is not visible
+on screen, this function should return and leave the return parameters
+untouched \dash the midend will notice this. The backend need not
+bother checking that \cw{x}, \cw{y}, \cw{w} and \cw{h} are
+non-\cw{NULL} \dash the midend guarantees that they will not be.
+
+Defining what constitutes a \q{region of interest} is left up to the
+backend. If a game provides a conventional cursor \dash such as Mines,
+Solo, or any of the other grid-based games \dash the most logical
+choice is of course the location of the cursor itself. However, in
+other cases such as Cube or Inertia, there is no \q{cursor} in the
+conventional sense \dash the player instead controls an object moving
+around the screen. In these cases, it makes sense to define the region
+of interest as the bounding box of the player object or another
+sensible region \dash such as the grid square the player is sitting on
+in Cube.
+
+If a backend does not provide a cursor mechanism at all, the backend
+is free to provide an empty implementation of this function, or a
+\cw{NULL} pointer in the \cw{game} structure \dash the midend will
+notice either of these cases and behave appropriately.
+
\S{backend-status} \cw{status()}
\c int (*status)(const game_state *state);
@@ -3306,6 +3351,34 @@
\cw{activate_timer()} to be called from within a call to this
function. Some back ends require that \cw{midend_size()}
(\k{midend-size}) is called before \cw{midend_solve()}.
+
+\H{midend-get-cursor-location} \cw{midend_get_cursor_location()}
+
+\c bool midend_get_cursor_location(midend *me,
+\c int *x, int *y,
+\c int *w, int *h);
+
+This function requests the location of the back end's on-screen cursor
+or other region of interest.
+
+What exactly this region contains is up to the backend, but in general
+the region will be an area that the player is controlling with the
+cursor keys \dash such as the player location in Cube and Inertia, or
+the cursor in any of the conventional grid-based games. With knowledge
+of this location, a front end can, for example, ensure that the region
+of interest remains visible even if the entire puzzle is too big to
+fit on the screen.
+
+On success, this function returns \cw{true}, and the locations pointed
+to by \cw{x}, \cw{y}, \cw{w} and \cw{h} are updated to describe the
+cursor region, which has an upper-left corner located at \cw{(*x,*y)}
+and a size of \cw{*w} pixels wide by \cw{*h} pixels tall. The caller
+may pass \cw{NULL} for any number of these pointers, which will be
+ignored.
+
+On failure, this function returns \cw{false}. Failure can occur if
+there is currently no active cursor region, or if the back end lacks
+cursor support.
\H{midend-status} \cw{midend_status()}
--- a/dominosa.c
+++ b/dominosa.c
@@ -3328,6 +3328,20 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cur_visible)
+ {
+ *x = BORDER + ((2 * ui->cur_x + 1) * TILESIZE) / 4;
+ *y = BORDER + ((2 * ui->cur_y + 1) * TILESIZE) / 4;
+ *w = *h = TILESIZE / 2 + 2;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -3422,6 +3436,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/fifteen.c
+++ b/fifteen.c
@@ -1061,6 +1061,17 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ *x = COORD(X(state, state->gap_pos));
+ *y = COORD(Y(state, state->gap_pos));
+ *w = *h = TILE_SIZE;
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -1115,6 +1126,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
--- a/filling.c
+++ b/filling.c
@@ -2060,6 +2060,20 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cur_visible)
+ {
+ *x = BORDER + ui->cur_x * TILE_SIZE;
+ *y = BORDER + ui->cur_y * TILE_SIZE;
+ *w = *h = TILE_SIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -2165,6 +2179,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/flip.c
+++ b/flip.c
@@ -1290,6 +1290,20 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cdraw)
+ {
+ *x = COORD(ui->cx);
+ *y = COORD(ui->cy);
+ *w = *h = TILE_SIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -1344,6 +1358,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
--- a/flood.c
+++ b/flood.c
@@ -1277,6 +1277,20 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cursor_visible)
+ {
+ *x = COORD(ui->cx);
+ *y = COORD(ui->cy);
+ *w = *h = TILESIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
if (state->complete && state->moves <= state->movelimit) {
@@ -1359,6 +1373,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
--- a/galaxies.c
+++ b/galaxies.c
@@ -3469,6 +3469,37 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cur_visible) {
+ space *sp = &SPACE(state, ui->cur_x, ui->cur_y);
+
+ if(sp->flags & F_DOT) {
+ *x = SCOORD(ui->cur_x) - DOT_SIZE;
+ *y = SCOORD(ui->cur_y) - DOT_SIZE;
+ *w = *h = 2 * DOT_SIZE + 1;
+ } else if(sp->type != s_tile) {
+ int dx = (ui->cur_x % 2) ? CURSOR_SIZE : CURSOR_SIZE/3;
+ int dy = (ui->cur_y % 2) ? CURSOR_SIZE : CURSOR_SIZE/3;
+ int x1 = SCOORD(ui->cur_x)-dx, y1 = SCOORD(ui->cur_y)-dy;
+ int xs = dx*2+1, ys = dy*2+1;
+
+ *x = x1;
+ *y = y1;
+ *w = xs;
+ *h = ys;
+ } else {
+ *x = SCOORD(ui->cur_x) - CURSOR_SIZE;
+ *y = SCOORD(ui->cur_y) - CURSOR_SIZE;
+ *w = *h = 2 * CURSOR_SIZE + 1;
+ }
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -3695,6 +3726,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
#ifdef EDITOR
false, false, NULL, NULL,
--- a/guess.c
+++ b/guess.c
@@ -1448,6 +1448,20 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->display_cur && !state->solved) {
+ *x = GUESS_X(state->next_go, ui->peg_cur) - CGAP;
+ *y = GUESS_Y(state->next_go, ui->peg_cur) - CGAP;
+
+ *w = *h = 2 * (PEGRAD + CGAP) + 1;
+ }
+}
+
static int game_status(const game_state *state)
{
/*
@@ -1508,6 +1522,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/inertia.c
+++ b/inertia.c
@@ -2181,6 +2181,17 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ *x = ds->pbgx;
+ *y = ds->pbgy;
+ *w = *h = TILESIZE;
+}
+
static int game_status(const game_state *state)
{
/*
@@ -2240,6 +2251,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
--- a/keen.c
+++ b/keen.c
@@ -2198,6 +2198,20 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->hshow) {
+ *x = BORDER + ui->hx * TILESIZE + 1 + GRIDEXTRA;
+ *y = BORDER + ui->hy * TILESIZE + 1 + GRIDEXTRA;
+
+ *w = *h = TILESIZE-1-2*GRIDEXTRA;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -2480,6 +2494,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/lightup.c
+++ b/lightup.c
@@ -2217,6 +2217,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cur_visible) {
+ *x = COORD(ui->cur_x);
+ *y = COORD(ui->cur_y);
+ *w = *h = TILE_SIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -2325,6 +2338,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/loopy.c
+++ b/loopy.c
@@ -3537,6 +3537,14 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+}
+
static int game_status(const game_state *state)
{
return state->solved ? +1 : 0;
@@ -3675,6 +3683,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false /* wants_statusbar */,
--- a/magnets.c
+++ b/magnets.c
@@ -2291,6 +2291,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cur_visible) {
+ *x = COORD(ui->cur_x);
+ *y = COORD(ui->cur_y);
+ *w = *h = TILE_SIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -2432,6 +2445,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/map.c
+++ b/map.c
@@ -3061,6 +3061,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cur_visible) {
+ *x = COORD(ui->cur_x);
+ *y = COORD(ui->cur_y);
+ *w = *h = TILESIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -3260,6 +3273,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, true, game_print_size, game_print,
false, /* wants_statusbar */
--- a/midend.c
+++ b/midend.c
@@ -1464,6 +1464,35 @@
me->game_id_change_notify_ctx = ctx;
}
+bool midend_get_cursor_location(midend *me,
+ int *x_out, int *y_out,
+ int *w_out, int *h_out)
+{
+ int x, y, w, h;
+ x = y = -1;
+ w = h = 1;
+
+ if(me->ourgame->get_cursor_location)
+ me->ourgame->get_cursor_location(me->ui,
+ me->drawstate,
+ me->states[me->statepos-1].state,
+ me->params,
+ &x, &y, &w, &h);
+
+ if(x == -1 && y == -1)
+ return false;
+
+ if(x_out)
+ *x_out = x;
+ if(y_out)
+ *y_out = y;
+ if(w_out)
+ *w_out = w;
+ if(h_out)
+ *h_out = h;
+ return true;
+}
+
void midend_supersede_game_desc(midend *me, const char *desc,
const char *privdesc)
{
--- a/mines.c
+++ b/mines.c
@@ -3150,6 +3150,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cur_visible) {
+ *x = COORD(ui->cur_x);
+ *y = COORD(ui->cur_y);
+ *w = *h = TILE_SIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
/*
@@ -3211,6 +3224,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
--- a/net.c
+++ b/net.c
@@ -3087,6 +3087,20 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cur_visible) {
+ *x = WINDOW_OFFSET + TILE_SIZE * ui->cur_x;
+ *y = WINDOW_OFFSET + TILE_SIZE * ui->cur_y;
+
+ *w = *h = TILE_SIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -3268,6 +3282,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
true, /* wants_statusbar */
--- a/netslide.c
+++ b/netslide.c
@@ -1825,6 +1825,20 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cur_visible) {
+ *x = BORDER + WINDOW_OFFSET + TILE_SIZE * ui->cur_x;
+ *y = BORDER + WINDOW_OFFSET + TILE_SIZE * ui->cur_y;
+
+ *w = *h = TILE_SIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -1879,6 +1893,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
--- a/nullgame.c
+++ b/nullgame.c
@@ -242,6 +242,14 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+}
+
static int game_status(const game_state *state)
{
return 0;
@@ -296,6 +304,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/palisade.c
+++ b/palisade.c
@@ -1274,6 +1274,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->show) {
+ *x = MARGIN + TILESIZE * ui->x;
+ *y = MARGIN + TILESIZE * ui->y;
+ *w = *h = TILESIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -1387,6 +1400,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
true, /* wants_statusbar */
--- a/pattern.c
+++ b/pattern.c
@@ -1916,6 +1916,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cur_visible) {
+ *x = TOCOORD(ds->w, ui->cur_x);
+ *y = TOCOORD(ds->h, ui->cur_y);
+ *w = *h = TILE_SIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -2027,6 +2040,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/pearl.c
+++ b/pearl.c
@@ -2542,6 +2542,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cursor_active) {
+ *x = COORD(ui->curx);
+ *y = COORD(ui->cury);
+ *w = *h = TILE_SIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -2635,6 +2648,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/pegs.c
+++ b/pegs.c
@@ -1280,6 +1280,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cur_visible) {
+ *x = COORD(ui->cur_x);
+ *y = COORD(ui->cur_y);
+ *w = *h = TILESIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
/*
@@ -1338,6 +1351,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/puzzles.h
+++ b/puzzles.h
@@ -347,6 +347,8 @@
bool (*read)(void *ctx, void *buf, int len),
void *rctx);
void midend_request_id_changes(midend *me, void (*notify)(void *), void *ctx);
+bool midend_get_cursor_location(midend *me, int *x, int *y, int *w, int *h);
+
/* Printing functions supplied by the mid-end */
const char *midend_print_puzzle(midend *me, document *doc, bool with_soln);
int midend_tilesize(midend *me);
@@ -680,6 +682,11 @@
const game_state *newstate, int dir, game_ui *ui);
float (*flash_length)(const game_state *oldstate,
const game_state *newstate, int dir, game_ui *ui);
+ void (*get_cursor_location)(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h);
int (*status)(const game_state *state);
bool can_print, can_print_in_colour;
void (*print_size)(const game_params *params, float *x, float *y);
--- a/range.c
+++ b/range.c
@@ -1572,6 +1572,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cursor_show) {
+ *x = BORDER + TILESIZE * ui->c;
+ *y = BORDER + TILESIZE * ui->r;
+ *w = *h = TILESIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->was_solved ? +1 : 0;
@@ -1823,6 +1836,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/rect.c
+++ b/rect.c
@@ -2880,6 +2880,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cur_visible) {
+ *x = COORD(ui->cur_x);
+ *y = COORD(ui->cur_y);
+ *w = *h = TILE_SIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -2991,6 +3004,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
true, /* wants_statusbar */
--- a/samegame.c
+++ b/samegame.c
@@ -1615,6 +1615,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->displaysel) {
+ *x = COORD(ui->xsel);
+ *y = COORD(ui->ysel);
+ *w = *h = TILE_SIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
/*
@@ -1673,6 +1686,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
--- a/signpost.c
+++ b/signpost.c
@@ -2187,6 +2187,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cshow) {
+ *x = COORD(ui->cx);
+ *y = COORD(ui->cy);
+ *w = *h = TILE_SIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -2274,6 +2287,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/singles.c
+++ b/singles.c
@@ -1758,6 +1758,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cshow) {
+ *x = COORD(ui->cx);
+ *y = COORD(ui->cy);
+ *w = *h = TILE_SIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -1850,6 +1863,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/sixteen.c
+++ b/sixteen.c
@@ -1146,6 +1146,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cur_visible) {
+ *x = COORD(ui->cur_x);
+ *y = COORD(ui->cur_y);
+ *w = *h = TILE_SIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -1200,6 +1213,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
--- a/slant.c
+++ b/slant.c
@@ -2064,6 +2064,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cur_visible) {
+ *x = COORD(ui->cur_x);
+ *y = COORD(ui->cur_y);
+ *w = *h = TILESIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -2181,6 +2194,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/solo.c
+++ b/solo.c
@@ -5297,6 +5297,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->hshow) {
+ *x = BORDER + ui->hx * TILE_SIZE + 1 + GRIDEXTRA;
+ *y = BORDER + ui->hy * TILE_SIZE + 1 + GRIDEXTRA;
+ *w = *h = TILE_SIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -5622,6 +5635,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/tents.c
+++ b/tents.c
@@ -2554,6 +2554,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cdisp) {
+ *x = COORD(ui->cx);
+ *y = COORD(ui->cy);
+ *w = *h = TILESIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -2630,6 +2643,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/towers.c
+++ b/towers.c
@@ -1935,6 +1935,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->hshow) {
+ *x = COORD(ui->hx);
+ *y = COORD(ui->hy);
+ *w = *h = TILESIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -2060,6 +2073,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/tracks.c
+++ b/tracks.c
@@ -2854,6 +2854,37 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cursor_active) {
+ int off = HALFSZ / 4;
+ int cx = COORD(ui->curx / 2) + off;
+ int cy = COORD(ui->cury / 2) + off;
+ int cw, ch;
+ cw = ch = TILE_SIZE - (2*off) + 1;
+
+ if(ui->curx % 2 == 0) {
+ /* left border */
+ cx -= off;
+ cw = 2 * off + 1;
+ }
+ if(ui->cury % 2 == 0) {
+ /* upper border */
+ cy -= off;
+ ch = 2 * off + 1;
+ }
+
+ *x = cx;
+ *y = cy;
+ *w = cw;
+ *h = ch;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -2948,6 +2979,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/twiddle.c
+++ b/twiddle.c
@@ -1090,6 +1090,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cur_visible) {
+ *x = COORD(ui->cur_x);
+ *y = COORD(ui->cur_y);
+ *w = *h = state->n * TILE_SIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -1316,6 +1329,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
--- a/undead.c
+++ b/undead.c
@@ -2727,6 +2727,19 @@
!newstate->cheated) ? FLASH_TIME : 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->hshow) {
+ *x = BORDER + (ui->hx) * TILESIZE;
+ *y = BORDER + (ui->hy + 1) * TILESIZE;
+ *w = *h = TILESIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->solved;
@@ -2781,6 +2794,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/unequal.c
+++ b/unequal.c
@@ -2041,6 +2041,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->hshow) {
+ *x = COORD(ui->hx);
+ *y = COORD(ui->hy);
+ *w = *h = TILE_SIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -2135,6 +2148,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/unfinished/group.c
+++ b/unfinished/group.c
@@ -2196,6 +2196,14 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -2320,6 +2328,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/unfinished/separate.c
+++ b/unfinished/separate.c
@@ -799,6 +799,14 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+}
+
static int game_status(const game_state *state)
{
return 0;
@@ -853,6 +861,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/unfinished/slide.c
+++ b/unfinished/slide.c
@@ -2297,6 +2297,14 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -2351,6 +2359,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
--- a/unfinished/sokoban.c
+++ b/unfinished/sokoban.c
@@ -1415,6 +1415,14 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -1469,6 +1477,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/unruly.c
+++ b/unruly.c
@@ -1860,6 +1860,19 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+ if(ui->cursor) {
+ *x = COORD(ui->cx);
+ *y = COORD(ui->cy);
+ *w = *h = TILE_SIZE;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -1948,6 +1961,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
--- a/untangle.c
+++ b/untangle.c
@@ -1428,6 +1428,14 @@
return 0.0F;
}
+static void game_get_cursor_location(const game_ui *ui,
+ const game_drawstate *ds,
+ const game_state *state,
+ const game_params *params,
+ int *x, int *y, int *w, int *h)
+{
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -1482,6 +1490,7 @@
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
false, /* wants_statusbar */