summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorFranklin Wei <franklin@rockbox.org>2020-07-06 22:59:58 -0400
committerFranklin Wei <franklin@rockbox.org>2020-07-06 23:00:13 -0400
commit5094aaa4d49573c0491399e987c2c866c00796a5 (patch)
tree7d625f9982e3263e6c242babe26be7ad5474b357 /apps
parent443ad25e75a29d114bc6c7d34387e6ad1f873a81 (diff)
downloadrockbox-5094aaa4d49573c0491399e987c2c866c00796a5.tar.gz
rockbox-5094aaa4d49573c0491399e987c2c866c00796a5.tar.bz2
rockbox-5094aaa4d49573c0491399e987c2c866c00796a5.zip
puzzles: Follow cursor in zoom mode and general code cleanup.
Frontends now have a way to retrieve the backend cursor position with some changes I've submitted upstream. With this information, we can now follow the cursor around in "interaction mode" while zoomed in, eliminating (most) need for mode switching. Also does some cleanup of the frontend code. Change-Id: I1ba118f67564a3baed95435f5619b73cfa3ae87a
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/puzzles/rockbox.c102
-rw-r--r--apps/plugins/puzzles/src/blackbox.c15
-rw-r--r--apps/plugins/puzzles/src/bridges.c15
-rw-r--r--apps/plugins/puzzles/src/cube.c22
-rw-r--r--apps/plugins/puzzles/src/devel.but76
-rw-r--r--apps/plugins/puzzles/src/dominosa.c15
-rw-r--r--apps/plugins/puzzles/src/fifteen.c12
-rw-r--r--apps/plugins/puzzles/src/filling.c15
-rw-r--r--apps/plugins/puzzles/src/flip.c15
-rw-r--r--apps/plugins/puzzles/src/flood.c15
-rw-r--r--apps/plugins/puzzles/src/galaxies.c45
-rw-r--r--apps/plugins/puzzles/src/guess.c15
-rw-r--r--apps/plugins/puzzles/src/inertia.c12
-rw-r--r--apps/plugins/puzzles/src/keen.c15
-rw-r--r--apps/plugins/puzzles/src/lightup.c14
-rw-r--r--apps/plugins/puzzles/src/loopy.c9
-rw-r--r--apps/plugins/puzzles/src/magnets.c14
-rw-r--r--apps/plugins/puzzles/src/map.c14
-rw-r--r--apps/plugins/puzzles/src/midend.c19
-rw-r--r--apps/plugins/puzzles/src/mines.c14
-rw-r--r--apps/plugins/puzzles/src/net.c15
-rw-r--r--apps/plugins/puzzles/src/netslide.c15
-rw-r--r--apps/plugins/puzzles/src/nullgame.c9
-rw-r--r--apps/plugins/puzzles/src/palisade.c14
-rw-r--r--apps/plugins/puzzles/src/pattern.c14
-rw-r--r--apps/plugins/puzzles/src/pearl.c14
-rw-r--r--apps/plugins/puzzles/src/pegs.c14
-rw-r--r--apps/plugins/puzzles/src/puzzles.h7
-rw-r--r--apps/plugins/puzzles/src/range.c14
-rw-r--r--apps/plugins/puzzles/src/rect.c14
-rw-r--r--apps/plugins/puzzles/src/samegame.c14
-rw-r--r--apps/plugins/puzzles/src/signpost.c14
-rw-r--r--apps/plugins/puzzles/src/singles.c14
-rw-r--r--apps/plugins/puzzles/src/sixteen.c14
-rw-r--r--apps/plugins/puzzles/src/slant.c14
-rw-r--r--apps/plugins/puzzles/src/solo.c14
-rw-r--r--apps/plugins/puzzles/src/tents.c14
-rw-r--r--apps/plugins/puzzles/src/towers.c14
-rw-r--r--apps/plugins/puzzles/src/tracks.c32
-rw-r--r--apps/plugins/puzzles/src/twiddle.c14
-rw-r--r--apps/plugins/puzzles/src/undead.c14
-rw-r--r--apps/plugins/puzzles/src/unequal.c14
-rw-r--r--apps/plugins/puzzles/src/unfinished/group.c9
-rw-r--r--apps/plugins/puzzles/src/unfinished/separate.c9
-rw-r--r--apps/plugins/puzzles/src/unfinished/slide.c9
-rw-r--r--apps/plugins/puzzles/src/unfinished/sokoban.c9
-rw-r--r--apps/plugins/puzzles/src/unruly.c14
-rw-r--r--apps/plugins/puzzles/src/untangle.c20
48 files changed, 834 insertions, 25 deletions
diff --git a/apps/plugins/puzzles/rockbox.c b/apps/plugins/puzzles/rockbox.c
index 04d7e6d6e4..51b5e0890b 100644
--- a/apps/plugins/puzzles/rockbox.c
+++ b/apps/plugins/puzzles/rockbox.c
@@ -37,6 +37,7 @@
#include "src/puzzles.h"
+#include "lib/helper.h"
#include "lib/keymaps.h"
#include "lib/playback_control.h"
#include "lib/simple_viewer.h"
@@ -139,6 +140,7 @@ extern bool audiobuf_available; /* defined in rbmalloc.c */
static fb_data *zoom_fb; /* dynamically allocated */
static int zoom_x = -1, zoom_y = -1, zoom_w, zoom_h, zoom_clipu, zoom_clipd, zoom_clipl, zoom_clipr;
+static bool zoom_force_center;
static int cur_font = FONT_UI;
static bool need_draw_update = false;
@@ -171,7 +173,7 @@ static bool load_success;
/* ...did I mention there's a secret debug menu? */
static struct {
int slowmo_factor;
- bool timerflash, clipoff, shortcuts, no_aa, polyanim;
+ bool timerflash, clipoff, shortcuts, no_aa, polyanim, highlight_cursor;
} debug_settings;
// used in menu titles - make sure to initialize!
@@ -337,7 +339,7 @@ static void zoom_mono_bitmap(const unsigned char *bits, int x, int y, int w, int
static void zoom_alpha_bitmap(const unsigned char *bits, int x, int y, int w, int h)
{
const unsigned char *ptr = bits;
- unsigned char buf;
+ unsigned char buf = 0;
int n_read = 0; /* how many 4-bit nibbles we've read (read new when even) */
unsigned int pix = rb->lcd_get_foreground();
@@ -751,7 +753,7 @@ static void draw_antialiased_line(fb_data *fb, int w, int h, int x0, int y0, int
dx = x1 - x0;
dy = y1 - y0;
- if(!(dx << FRACBITS))
+ if((dx << FRACBITS) == 0)
return; /* bail out */
long gradient = fp_div(dy << FRACBITS, dx << FRACBITS, FRACBITS);
@@ -1349,6 +1351,16 @@ static void rb_start_draw(void *handle)
static void rb_end_draw(void *handle)
{
(void) handle;
+
+ if(debug_settings.highlight_cursor)
+ {
+ rb->lcd_set_foreground(LCD_RGBPACK(255,0,255));
+ int x, y, w, h;
+ midend_get_cursor_location(me, &x, &y, &w, &h);
+ if(x >= 0)
+ rb->lcd_drawrect(x, y, w, h);
+ }
+
/* we ignore the backend's redraw requests and just
* unconditionally update everything */
#if 0
@@ -1991,6 +2003,47 @@ static void zoom_clamp_panning(void) {
zoom_x = zoom_w - LCD_WIDTH;
}
+static bool point_in_rect(int px, int py,
+ int rx, int ry,
+ int rw, int rh) {
+ return (rx <= px && px < rx + rw) && (ry <= py && py < ry + rh);
+}
+
+
+static void zoom_center_on_cursor(void) {
+ /* get cursor bounding rectangle */
+ int x, y, w, h;
+
+ midend_get_cursor_location(me, &x, &y, &w, &h);
+
+ /* no cursor */
+ if(x < 0)
+ return;
+
+ /* check if either of the top-left and bottom-right corners are
+ * off-screen */
+ bool off_screen = (!point_in_rect(x, y, zoom_x, zoom_y, LCD_WIDTH, LCD_HEIGHT) ||
+ !point_in_rect(x + w, y + h, zoom_x, zoom_y, LCD_WIDTH, LCD_HEIGHT));
+
+ if(off_screen || zoom_force_center)
+ {
+ /* if so, recenter */
+ int cx, cy;
+ cx = x + w / 2;
+ cy = y + h / 2;
+
+ bool x_pan = x < zoom_x || zoom_x + LCD_WIDTH <= x + w;
+ if(x_pan || zoom_force_center)
+ zoom_x = cx - LCD_WIDTH / 2;
+
+ bool y_pan = y < zoom_y || zoom_y + LCD_HEIGHT <= y + h;
+ if(y_pan || zoom_force_center)
+ zoom_y = cy - LCD_HEIGHT / 2;
+
+ zoom_clamp_panning();
+ }
+}
+
/* This function handles zoom mode, where the user can either pan
* around a zoomed-in image or play a zoomed-in version of the game. */
static void zoom(void)
@@ -2137,6 +2190,8 @@ static void zoom(void)
if(timer_on)
timer_cb();
+ zoom_center_on_cursor();
+
midend_redraw(me);
/* blit */
@@ -2624,6 +2679,7 @@ static void init_default_settings(void)
debug_settings.shortcuts = false;
debug_settings.no_aa = false;
debug_settings.polyanim = false;
+ debug_settings.highlight_cursor = false;
}
#ifdef DEBUG_MENU
@@ -2672,6 +2728,8 @@ static void debug_menu(void)
"Toggle send keys on release",
"Toggle ignore repeats",
"Toggle right-click on hold vs. dragging",
+ "Toggle highlight cursor region",
+ "Toggle force zoom on center",
"Back");
bool quit = false;
int sel = 0;
@@ -2693,37 +2751,43 @@ static void debug_menu(void)
break;
}
case 2:
- debug_settings.timerflash = !debug_settings.timerflash;
+ debug_settings.timerflash ^= true;
break;
case 3:
- debug_settings.clipoff = !debug_settings.clipoff;
+ debug_settings.clipoff ^= true;
break;
case 4:
- debug_settings.shortcuts = !debug_settings.shortcuts;
+ debug_settings.shortcuts ^= true;
break;
case 5:
- debug_settings.no_aa = !debug_settings.no_aa;
+ debug_settings.no_aa ^= true;
break;
case 6:
bench_aa();
break;
case 7:
- debug_settings.polyanim = !debug_settings.polyanim;
+ debug_settings.polyanim ^= true;
break;
case 8:
- mouse_mode = !mouse_mode;
+ mouse_mode ^= true;
break;
case 9:
- input_settings.want_spacebar = !input_settings.want_spacebar;
+ input_settings.want_spacebar ^= true;
break;
case 10:
- input_settings.falling_edge = !input_settings.falling_edge;
+ input_settings.falling_edge ^= true;
break;
case 11:
- input_settings.ignore_repeats = !input_settings.ignore_repeats;
+ input_settings.ignore_repeats ^= true;
break;
case 12:
- input_settings.rclick_on_hold = !input_settings.rclick_on_hold;
+ input_settings.rclick_on_hold ^= true;
+ break;
+ case 13:
+ debug_settings.highlight_cursor ^= true;
+ break;
+ case 14:
+ zoom_force_center ^= true;
break;
default:
quit = true;
@@ -2952,10 +3016,10 @@ static void init_tlsf(void)
init_memory_pool(giant_buffer_len, giant_buffer);
}
-static int read_wrapper(void *ptr, void *buf, int len)
+static bool read_wrapper(void *ptr, void *buf, int len)
{
int fd = (int) ptr;
- return rb->read(fd, buf, len);
+ return rb->read(fd, buf, len) == len;
}
static void write_wrapper(void *ptr, const void *buf, int len)
@@ -3067,6 +3131,12 @@ static void tune_input(const char *name)
};
input_settings.numerical_chooser = string_in_list(name, number_chooser_games);
+
+ static const char *force_center_games[] = {
+ "Inertia",
+ NULL
+ };
+ zoom_force_center = string_in_list(name, force_center_games);
}
static const char *init_for_game(const game *gm, int load_fd)
@@ -3241,7 +3311,7 @@ static void save_fonts(void)
final |= oldmask;
uint32_t left = final >> 31;
uint32_t right = final & 0x7fffffff;
- rb->fdprintf(outfd, "%s:%lu:%lu\n", midend_which_game(me)->name, left, right);
+ rb->fdprintf(outfd, "%s:%u:%u\n", midend_which_game(me)->name, (unsigned)left, (unsigned)right);
rb->close(outfd);
rb->rename(FONT_TABLE ".tmp", FONT_TABLE);
}
diff --git a/apps/plugins/puzzles/src/blackbox.c b/apps/plugins/puzzles/src/blackbox.c
index c52c50812d..a9c1f88261 100644
--- a/apps/plugins/puzzles/src/blackbox.c
+++ b/apps/plugins/puzzles/src/blackbox.c
@@ -1100,6 +1100,20 @@ badmove:
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.
*/
@@ -1544,6 +1558,7 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/bridges.c b/apps/plugins/puzzles/src/bridges.c
index d12aa0bb6c..83086c9761 100644
--- a/apps/plugins/puzzles/src/bridges.c
+++ b/apps/plugins/puzzles/src/bridges.c
@@ -2146,6 +2146,20 @@ struct game_drawstate {
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/cube.c b/apps/plugins/puzzles/src/cube.c
index bda7623f97..8c8c46faed 100644
--- a/apps/plugins/puzzles/src/cube.c
+++ b/apps/plugins/puzzles/src/cube.c
@@ -1535,6 +1535,27 @@ static void game_free_drawstate(drawing *dr, game_drawstate *ds)
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/devel.but b/apps/plugins/puzzles/src/devel.but
index 9f95ad7dd4..741a7944ac 100644
--- a/apps/plugins/puzzles/src/devel.but
+++ b/apps/plugins/puzzles/src/devel.but
@@ -1289,6 +1289,50 @@ a mine from the colour it uses when you complete the game. In order
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, 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 frontends to query the location of the backend's
+cursor. With knowledge of this location, a frontend 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. All return values are in units of pixels in
+screenspace coordinates. In the event that a cursor is not visible on
+screen, this function should return and leave the return parameters
+untouched \dash the mid-end 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 mid-end 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 cursor location. However, in other cases such as Cube
+or Inertia, there is no \q{cursor} in the conventional sense \dash the
+player 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 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 mid-end will
+notice either of these cases and behave appropriately.
+
\S{backend-status} \cw{status()}
\c int (*status)(const game_state *state);
@@ -1586,10 +1630,10 @@ to the midend when the frontend deems appropriate.
The backend should set \cw{*nkeys} to the number of elements in the
returned array.
-The field for this function point in the \cw{game} structure might be
-set to \cw{NULL} (and indeed it is for the majority of the games) to
-indicate that no additional buttons (apart from the cursor keys) are
-required to play the game.
+The field for this function pointer in the \cw{game} structure might
+be set to \cw{NULL} (and indeed it is for the majority of the games)
+to indicate that no additional buttons (apart from the cursor keys)
+are required to play the game.
This function should not be called directly by frontends. Instead,
frontends should use \cw{midend_request_keys()}
@@ -3307,6 +3351,30 @@ The front end can expect its drawing API and/or
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 void midend_get_cursor_location(midend *me,
+\c int *x, int *y, int *w, int *h);
+
+This function returns the location of the backend's on-screen cursor
+or other region of interest in the parameters \cw{*x}, \cw{*y},
+\cw{*w} and \cw{*h}, which describe a rectangle with an upper-left
+corner at \cw{(*x,*y)} and a size of \cw{*w} pixels wide by \cw{*h}
+pixels tall. The mid-end will ignore any return parameters that may be
+equal to \cw{NULL}.
+
+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 frontend can, for example, ensure that the region
+of interest remains visible even if the entire puzzle is too big to
+fit on the screen.
+
+If there is no such region (if either the cursor is not visible, or if
+the game does not have cursor support), both \cw{*x} and \cw{*y} will
+be set to \cw{-1}.
+
\H{midend-status} \cw{midend_status()}
\c int midend_status(midend *me);
diff --git a/apps/plugins/puzzles/src/dominosa.c b/apps/plugins/puzzles/src/dominosa.c
index 67a1d69c91..758db4f506 100644
--- a/apps/plugins/puzzles/src/dominosa.c
+++ b/apps/plugins/puzzles/src/dominosa.c
@@ -3328,6 +3328,20 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/fifteen.c b/apps/plugins/puzzles/src/fifteen.c
index ba991e711a..4b877dc098 100644
--- a/apps/plugins/puzzles/src/fifteen.c
+++ b/apps/plugins/puzzles/src/fifteen.c
@@ -1061,6 +1061,17 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/filling.c b/apps/plugins/puzzles/src/filling.c
index f67d9fadba..6d9beb5c28 100644
--- a/apps/plugins/puzzles/src/filling.c
+++ b/apps/plugins/puzzles/src/filling.c
@@ -2060,6 +2060,20 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/flip.c b/apps/plugins/puzzles/src/flip.c
index 29c888edf2..5d4f2250aa 100644
--- a/apps/plugins/puzzles/src/flip.c
+++ b/apps/plugins/puzzles/src/flip.c
@@ -1290,6 +1290,20 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/flood.c b/apps/plugins/puzzles/src/flood.c
index 67c3225be4..74214a50b6 100644
--- a/apps/plugins/puzzles/src/flood.c
+++ b/apps/plugins/puzzles/src/flood.c
@@ -1279,6 +1279,20 @@ static float game_anim_length(const game_state *oldstate,
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) {
@@ -1361,6 +1375,7 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/galaxies.c b/apps/plugins/puzzles/src/galaxies.c
index fe7cd24ecf..9172b90e12 100644
--- a/apps/plugins/puzzles/src/galaxies.c
+++ b/apps/plugins/puzzles/src/galaxies.c
@@ -382,12 +382,15 @@ static bool ok_to_add_assoc_with_opposite(
static void add_assoc_with_opposite(game_state *state, space *tile, space *dot) {
space *opposite = space_opposite_dot(state, tile, dot);
- assert(ok_to_add_assoc_with_opposite_internal(state, tile, opposite));
+ if(opposite)
+ {
+ assert(ok_to_add_assoc_with_opposite_internal(state, tile, opposite));
- remove_assoc_with_opposite(state, tile);
- add_assoc(state, tile, dot);
- remove_assoc_with_opposite(state, opposite);
- add_assoc(state, opposite, dot);
+ remove_assoc_with_opposite(state, tile);
+ add_assoc(state, tile, dot);
+ remove_assoc_with_opposite(state, opposite);
+ add_assoc(state, opposite, dot);
+ }
}
static space *sp2dot(const game_state *state, int x, int y)
@@ -3469,6 +3472,37 @@ static float game_flash_length(const game_state *oldstate,
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 +3729,7 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
#ifdef EDITOR
false, false, NULL, NULL,
diff --git a/apps/plugins/puzzles/src/guess.c b/apps/plugins/puzzles/src/guess.c
index e5ebd5509b..a501579442 100644
--- a/apps/plugins/puzzles/src/guess.c
+++ b/apps/plugins/puzzles/src/guess.c
@@ -1448,6 +1448,20 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/inertia.c b/apps/plugins/puzzles/src/inertia.c
index 838f8dee96..726c89c7dd 100644
--- a/apps/plugins/puzzles/src/inertia.c
+++ b/apps/plugins/puzzles/src/inertia.c
@@ -2186,6 +2186,17 @@ static float game_flash_length(const game_state *oldstate,
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)
{
/*
@@ -2245,6 +2256,7 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/keen.c b/apps/plugins/puzzles/src/keen.c
index 70e3e5432c..6b9610dbcd 100644
--- a/apps/plugins/puzzles/src/keen.c
+++ b/apps/plugins/puzzles/src/keen.c
@@ -2198,6 +2198,20 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/lightup.c b/apps/plugins/puzzles/src/lightup.c
index 90811d5475..ab4be9ec87 100644
--- a/apps/plugins/puzzles/src/lightup.c
+++ b/apps/plugins/puzzles/src/lightup.c
@@ -2217,6 +2217,19 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/loopy.c b/apps/plugins/puzzles/src/loopy.c
index f2875a2e93..176b56285c 100644
--- a/apps/plugins/puzzles/src/loopy.c
+++ b/apps/plugins/puzzles/src/loopy.c
@@ -3537,6 +3537,14 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false /* wants_statusbar */,
diff --git a/apps/plugins/puzzles/src/magnets.c b/apps/plugins/puzzles/src/magnets.c
index 1a5f37f1fd..edbb8490ad 100644
--- a/apps/plugins/puzzles/src/magnets.c
+++ b/apps/plugins/puzzles/src/magnets.c
@@ -2291,6 +2291,19 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/map.c b/apps/plugins/puzzles/src/map.c
index 4e65aa91a6..9df2d22b52 100644
--- a/apps/plugins/puzzles/src/map.c
+++ b/apps/plugins/puzzles/src/map.c
@@ -3061,6 +3061,19 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, true, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/midend.c b/apps/plugins/puzzles/src/midend.c
index a8dd179690..87605a9da8 100644
--- a/apps/plugins/puzzles/src/midend.c
+++ b/apps/plugins/puzzles/src/midend.c
@@ -1464,6 +1464,25 @@ void midend_request_id_changes(midend *me, void (*notify)(void *), void *ctx)
me->game_id_change_notify_ctx = ctx;
}
+void 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_out)
+ *x_out = x;
+ if(y_out)
+ *y_out = y;
+ if(w_out)
+ *w_out = w;
+ if(h_out)
+ *h_out = h;
+}
+
void midend_supersede_game_desc(midend *me, const char *desc,
const char *privdesc)
{
diff --git a/apps/plugins/puzzles/src/mines.c b/apps/plugins/puzzles/src/mines.c
index ae717d3f37..706777c4f1 100644
--- a/apps/plugins/puzzles/src/mines.c
+++ b/apps/plugins/puzzles/src/mines.c
@@ -3152,6 +3152,19 @@ static float game_flash_length(const game_state *oldstate,
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)
{
/*
@@ -3213,6 +3226,7 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/net.c b/apps/plugins/puzzles/src/net.c
index 36f8aca483..d3032b6fe2 100644
--- a/apps/plugins/puzzles/src/net.c
+++ b/apps/plugins/puzzles/src/net.c
@@ -3090,6 +3090,20 @@ static float game_flash_length(const game_state *oldstate,
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;
@@ -3271,6 +3285,7 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
true, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/netslide.c b/apps/plugins/puzzles/src/netslide.c
index 727ff0a910..14af2a689d 100644
--- a/apps/plugins/puzzles/src/netslide.c
+++ b/apps/plugins/puzzles/src/netslide.c
@@ -1830,6 +1830,20 @@ static float game_flash_length(const game_state *oldstate,
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;
@@ -1884,6 +1898,7 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/nullgame.c b/apps/plugins/puzzles/src/nullgame.c
index 2fa4da6ffd..d923bc8710 100644
--- a/apps/plugins/puzzles/src/nullgame.c
+++ b/apps/plugins/puzzles/src/nullgame.c
@@ -242,6 +242,14 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/palisade.c b/apps/plugins/puzzles/src/palisade.c
index 759fcaa75d..e941661a0e 100644
--- a/apps/plugins/puzzles/src/palisade.c
+++ b/apps/plugins/puzzles/src/palisade.c
@@ -1288,6 +1288,19 @@ static float game_flash_length(const game_state *oldstate,
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;
@@ -1401,6 +1414,7 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
true, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/pattern.c b/apps/plugins/puzzles/src/pattern.c
index a43982f452..df720b7d82 100644
--- a/apps/plugins/puzzles/src/pattern.c
+++ b/apps/plugins/puzzles/src/pattern.c
@@ -1918,6 +1918,19 @@ static float game_flash_length(const game_state *oldstate,
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;
@@ -2029,6 +2042,7 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/pearl.c b/apps/plugins/puzzles/src/pearl.c
index ccbba51897..2657d45a67 100644
--- a/apps/plugins/puzzles/src/pearl.c
+++ b/apps/plugins/puzzles/src/pearl.c
@@ -2542,6 +2542,19 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/pegs.c b/apps/plugins/puzzles/src/pegs.c
index db9caf298f..ec12aa9552 100644
--- a/apps/plugins/puzzles/src/pegs.c
+++ b/apps/plugins/puzzles/src/pegs.c
@@ -1280,6 +1280,19 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/puzzles.h b/apps/plugins/puzzles/src/puzzles.h
index 45ae321cc6..5560aabe03 100644
--- a/apps/plugins/puzzles/src/puzzles.h
+++ b/apps/plugins/puzzles/src/puzzles.h
@@ -347,6 +347,8 @@ const char *identify_game(char **name,
bool (*read)(void *ctx, void *buf, int len),
void *rctx);
void midend_request_id_changes(midend *me, void (*notify)(void *), void *ctx);
+void 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);
@@ -684,6 +686,11 @@ struct game {
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);
diff --git a/apps/plugins/puzzles/src/range.c b/apps/plugins/puzzles/src/range.c
index 64bd17da56..fc0a5405f1 100644
--- a/apps/plugins/puzzles/src/range.c
+++ b/apps/plugins/puzzles/src/range.c
@@ -1572,6 +1572,19 @@ static float game_flash_length(const game_state *from,
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 @@ struct game const thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/rect.c b/apps/plugins/puzzles/src/rect.c
index 2cb01bfa5d..b13de75fd4 100644
--- a/apps/plugins/puzzles/src/rect.c
+++ b/apps/plugins/puzzles/src/rect.c
@@ -2883,6 +2883,19 @@ static float game_flash_length(const game_state *oldstate,
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;
@@ -2994,6 +3007,7 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
true, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/samegame.c b/apps/plugins/puzzles/src/samegame.c
index 272c7b457d..615c60e0a5 100644
--- a/apps/plugins/puzzles/src/samegame.c
+++ b/apps/plugins/puzzles/src/samegame.c
@@ -1615,6 +1615,19 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/signpost.c b/apps/plugins/puzzles/src/signpost.c
index abf4c6a79c..9aee255ebe 100644
--- a/apps/plugins/puzzles/src/signpost.c
+++ b/apps/plugins/puzzles/src/signpost.c
@@ -2188,6 +2188,19 @@ static float game_flash_length(const game_state *oldstate,
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;
@@ -2275,6 +2288,7 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/singles.c b/apps/plugins/puzzles/src/singles.c
index 3dde8c2b87..202ce08b20 100644
--- a/apps/plugins/puzzles/src/singles.c
+++ b/apps/plugins/puzzles/src/singles.c
@@ -1758,6 +1758,19 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/sixteen.c b/apps/plugins/puzzles/src/sixteen.c
index e47147a8a5..0b02038c43 100644
--- a/apps/plugins/puzzles/src/sixteen.c
+++ b/apps/plugins/puzzles/src/sixteen.c
@@ -1147,6 +1147,19 @@ static float game_flash_length(const game_state *oldstate,
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;
@@ -1201,6 +1214,7 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/slant.c b/apps/plugins/puzzles/src/slant.c
index 70b2585b81..ed290fe57d 100644
--- a/apps/plugins/puzzles/src/slant.c
+++ b/apps/plugins/puzzles/src/slant.c
@@ -2064,6 +2064,19 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/solo.c b/apps/plugins/puzzles/src/solo.c
index cfe38c5bd9..49753f41dc 100644
--- a/apps/plugins/puzzles/src/solo.c
+++ b/apps/plugins/puzzles/src/solo.c
@@ -5297,6 +5297,19 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/tents.c b/apps/plugins/puzzles/src/tents.c
index 1e601f5836..ee06172baf 100644
--- a/apps/plugins/puzzles/src/tents.c
+++ b/apps/plugins/puzzles/src/tents.c
@@ -2554,6 +2554,19 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/towers.c b/apps/plugins/puzzles/src/towers.c
index aee088fb54..13c652b819 100644
--- a/apps/plugins/puzzles/src/towers.c
+++ b/apps/plugins/puzzles/src/towers.c
@@ -1935,6 +1935,19 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/tracks.c b/apps/plugins/puzzles/src/tracks.c
index 924836afa9..3cf5df70a1 100644
--- a/apps/plugins/puzzles/src/tracks.c
+++ b/apps/plugins/puzzles/src/tracks.c
@@ -2854,6 +2854,37 @@ static float game_flash_length(const game_state *oldstate, const game_state *new
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/twiddle.c b/apps/plugins/puzzles/src/twiddle.c
index 5f2ea02e6f..a107925aee 100644
--- a/apps/plugins/puzzles/src/twiddle.c
+++ b/apps/plugins/puzzles/src/twiddle.c
@@ -1092,6 +1092,19 @@ static float game_flash_length(const game_state *oldstate,
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;
@@ -1318,6 +1331,7 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/undead.c b/apps/plugins/puzzles/src/undead.c
index 781c15d791..4dba828d48 100644
--- a/apps/plugins/puzzles/src/undead.c
+++ b/apps/plugins/puzzles/src/undead.c
@@ -2727,6 +2727,19 @@ static float game_flash_length(const game_state *oldstate,
!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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/unequal.c b/apps/plugins/puzzles/src/unequal.c
index 556cf01c45..153954e510 100644
--- a/apps/plugins/puzzles/src/unequal.c
+++ b/apps/plugins/puzzles/src/unequal.c
@@ -2041,6 +2041,19 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/unfinished/group.c b/apps/plugins/puzzles/src/unfinished/group.c
index 006a9e0ee6..8e0185741e 100644
--- a/apps/plugins/puzzles/src/unfinished/group.c
+++ b/apps/plugins/puzzles/src/unfinished/group.c
@@ -2196,6 +2196,14 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/unfinished/separate.c b/apps/plugins/puzzles/src/unfinished/separate.c
index 88dc8ed060..39243afb92 100644
--- a/apps/plugins/puzzles/src/unfinished/separate.c
+++ b/apps/plugins/puzzles/src/unfinished/separate.c
@@ -799,6 +799,14 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/unfinished/slide.c b/apps/plugins/puzzles/src/unfinished/slide.c
index 5ad1237d58..c7a3dcecf7 100644
--- a/apps/plugins/puzzles/src/unfinished/slide.c
+++ b/apps/plugins/puzzles/src/unfinished/slide.c
@@ -2297,6 +2297,14 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
true, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/unfinished/sokoban.c b/apps/plugins/puzzles/src/unfinished/sokoban.c
index 7d42a12c5d..ecc222c906 100644
--- a/apps/plugins/puzzles/src/unfinished/sokoban.c
+++ b/apps/plugins/puzzles/src/unfinished/sokoban.c
@@ -1415,6 +1415,14 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/unruly.c b/apps/plugins/puzzles/src/unruly.c
index e69c31b6b9..a1f06332e0 100644
--- a/apps/plugins/puzzles/src/unruly.c
+++ b/apps/plugins/puzzles/src/unruly.c
@@ -1860,6 +1860,19 @@ static float game_flash_length(const game_state *oldstate,
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 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
true, false, game_print_size, game_print,
false, /* wants_statusbar */
diff --git a/apps/plugins/puzzles/src/untangle.c b/apps/plugins/puzzles/src/untangle.c
index eff93382cd..0d3e0e6135 100644
--- a/apps/plugins/puzzles/src/untangle.c
+++ b/apps/plugins/puzzles/src/untangle.c
@@ -1581,6 +1581,25 @@ static float game_flash_length(const game_state *oldstate,
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->dragpoint >= 0 || ui->cursorpoint >= 0) {
+ int idx = (ui->dragpoint >= 0) ? ui->dragpoint : ui->cursorpoint;
+
+ int cx, cy;
+ cx = ds->x[idx];
+ cy = ds->y[idx];
+
+ *x = cx - CIRCLE_RADIUS;
+ *y = cy - CIRCLE_RADIUS;
+ *w = *h = 2 * CIRCLE_RADIUS + 1;
+ }
+}
+
static int game_status(const game_state *state)
{
return state->completed ? +1 : 0;
@@ -1635,6 +1654,7 @@ const struct game thegame = {
game_redraw,
game_anim_length,
game_flash_length,
+ game_get_cursor_location,
game_status,
false, false, game_print_size, game_print,
false, /* wants_statusbar */