diff --git a/blackbox.c b/blackbox.c index 2025d1d..43323f9 100644 --- a/blackbox.c +++ b/blackbox.c @@ -930,7 +930,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (IS_CURSOR_MOVE(button)) { int cx = ui->cur_x, cy = ui->cur_y; - move_cursor(button, &cx, &cy, state->w+2, state->h+2, false); + move_cursor(button, &cx, &cy, state->w+2, state->h+2, false, NULL); if ((cx == 0 && cy == 0 && !CAN_REVEAL(state)) || (cx == 0 && cy == state->h+1) || (cx == state->w+1 && cy == 0) || diff --git a/bridges.c b/bridges.c index 0cbe779..6de61f1 100644 --- a/bridges.c +++ b/bridges.c @@ -2446,7 +2446,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (ui->dragging) { int nx = ui->cur_x, ny = ui->cur_y; - move_cursor(button, &nx, &ny, state->w, state->h, false); + move_cursor(button, &nx, &ny, state->w, state->h, false, NULL); if (nx == ui->cur_x && ny == ui->cur_y) return MOVE_NO_EFFECT; update_drag_dst(state, ui, ds, diff --git a/devel.but b/devel.but index 65c1571..4d205ac 100644 --- a/devel.but +++ b/devel.but @@ -5239,8 +5239,8 @@ The returned string is dynamically allocated and should be \S{utils-move-cursor} \cw{move_cursor()} -\c void move_cursor(int button, int *x, int *y, int w, int h, -\c bool wrap); +\c char *move_cursor(int button, int *x, int *y, int w, int h, +\c bool wrap, bool *visible); This function can be called by \cw{interpret_move()} to implement the default keyboard API for moving a cursor around a grid. @@ -5263,6 +5263,15 @@ of the grid will result in it wrapping round to the corresponding square on the opposite edge. If \c{wrap} is \cw{false}, such a move will have no effect. +If \c{visible} is not \cw{NULL}, it points to a flag indicating +whether the cursor is visible. This will be set to \cw{true} if +\c{button} represents a cursor-movement key. + +The function returns one of the special constants that can be returned +by \cw{interpret_move()}. The return value is \cw{MOVE_UNUSED} if +\c{button} is unrecognised, \cw{MOVE_UI_UPDATE} if \c{x}, \c{y}, or +\c{visible} was updated, and \cw{MOVE_NO EFFECT} otherwise. + \S{utils-divvy-rectangle} \cw{divvy_rectangle()} \c int *divvy_rectangle(int w, int h, int k, random_state *rs); diff --git a/dominosa.c b/dominosa.c index 3ff0c97..d649e05 100644 --- a/dominosa.c +++ b/dominosa.c @@ -2832,7 +2832,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, } else if (IS_CURSOR_MOVE(button)) { ui->cur_visible = true; - move_cursor(button, &ui->cur_x, &ui->cur_y, 2*w-1, 2*h-1, false); + move_cursor(button, &ui->cur_x, &ui->cur_y, 2*w-1, 2*h-1, false, NULL); return MOVE_UI_UPDATE; } else if (IS_CURSOR_SELECT(button)) { diff --git a/fifteen.c b/fifteen.c index 2f10122..6651d43 100644 --- a/fifteen.c +++ b/fifteen.c @@ -766,7 +766,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, button = flip_cursor(button); /* the default */ if (ui->invert_cursor) button = flip_cursor(button); /* undoes the first flip */ - move_cursor(button, &nx, &ny, state->w, state->h, false); + move_cursor(button, &nx, &ny, state->w, state->h, false, NULL); } else if ((button == 'h' || button == 'H') && !state->completed) { if (!compute_hint(state, &nx, &ny)) return MOVE_NO_EFFECT;/* shouldn't happen, since ^^we^^checked^^ */ diff --git a/filling.c b/filling.c index 0ab4f08..80a06dd 100644 --- a/filling.c +++ b/filling.c @@ -1498,7 +1498,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (IS_CURSOR_MOVE(button)) { ui->cur_visible = true; - move_cursor(button, &ui->cur_x, &ui->cur_y, w, h, false); + move_cursor(button, &ui->cur_x, &ui->cur_y, w, h, false, NULL); if (ui->keydragging) goto select_square; return MOVE_UI_UPDATE; } diff --git a/galaxies.c b/galaxies.c index 7f1d605..c56b07a 100644 --- a/galaxies.c +++ b/galaxies.c @@ -3021,7 +3021,8 @@ static char *interpret_move(const game_state *state, game_ui *ui, else return MOVE_UI_UPDATE; } else if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cur_x, &ui->cur_y, state->sx-1, state->sy-1, false); + move_cursor(button, &ui->cur_x, &ui->cur_y, state->sx-1, state->sy-1, + false, NULL); if (ui->cur_x < 1) ui->cur_x = 1; if (ui->cur_y < 1) ui->cur_y = 1; ui->cur_visible = true; diff --git a/keen.c b/keen.c index 1446740..7022611 100644 --- a/keen.c +++ b/keen.c @@ -1748,7 +1748,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, } } if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->hx, &ui->hy, w, w, false); + move_cursor(button, &ui->hx, &ui->hy, w, w, false, NULL); ui->hshow = true; ui->hcursor = true; return MOVE_UI_UPDATE; diff --git a/lightup.c b/lightup.c index 15e0a67..64c41f7 100644 --- a/lightup.c +++ b/lightup.c @@ -1975,7 +1975,8 @@ static char *interpret_move(const game_state *state, game_ui *ui, } ui->cur_visible = true; } else if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cur_x, &ui->cur_y, state->w, state->h, false); + move_cursor(button, &ui->cur_x, &ui->cur_y, state->w, state->h, false, + NULL); ui->cur_visible = true; nullret = empty; } else diff --git a/magnets.c b/magnets.c index a437b59..6d7eb00 100644 --- a/magnets.c +++ b/magnets.c @@ -1844,7 +1844,8 @@ static char *interpret_move(const game_state *state, game_ui *ui, enum { CYCLE_MAGNET, CYCLE_NEUTRAL } action; if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cur_x, &ui->cur_y, state->w, state->h, false); + move_cursor(button, &ui->cur_x, &ui->cur_y, state->w, state->h, false, + NULL); ui->cur_visible = true; return MOVE_UI_UPDATE; } else if (IS_CURSOR_SELECT(button)) { diff --git a/map.c b/map.c index e7681a0..c7dbd29 100644 --- a/map.c +++ b/map.c @@ -2486,7 +2486,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (IS_CURSOR_MOVE(button)) { move_cursor(button, &ui->cur_x, &ui->cur_y, state->p.w, state->p.h, - false); + false, NULL); ui->cur_visible = true; ui->cur_moved = true; ui->cur_lastmove = button; diff --git a/mines.c b/mines.c index d1787f5..91fe6e2 100644 --- a/mines.c +++ b/mines.c @@ -2423,7 +2423,8 @@ static char *interpret_move(const game_state *from, game_ui *ui, cy = FROMCOORD(y); if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cur_x, &ui->cur_y, from->w, from->h, false); + move_cursor(button, &ui->cur_x, &ui->cur_y, from->w, from->h, false, + NULL); ui->cur_visible = true; return MOVE_UI_UPDATE; } diff --git a/misc.c b/misc.c index 334e08d..6b5f3f8 100644 --- a/misc.c +++ b/misc.c @@ -351,15 +351,16 @@ void draw_rect_corners(drawing *dr, int cx, int cy, int r, int col) draw_line(dr, cx + r, cy + r, cx + r/2, cy + r, col); } -void move_cursor(int button, int *x, int *y, int maxw, int maxh, bool wrap) +char *move_cursor(int button, int *x, int *y, int maxw, int maxh, bool wrap, + bool *visible) { - int dx = 0, dy = 0; + int dx = 0, dy = 0, ox = *x, oy = *y; 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; + default: return MOVE_UNUSED; } if (wrap) { *x = (*x + dx + maxw) % maxw; @@ -368,6 +369,13 @@ void move_cursor(int button, int *x, int *y, int maxw, int maxh, bool wrap) *x = min(max(*x+dx, 0), maxw - 1); *y = min(max(*y+dy, 0), maxh - 1); } + if (visible != NULL && !*visible) { + *visible = true; + return MOVE_UI_UPDATE; + } + if (*x != ox || *y != oy) + return MOVE_UI_UPDATE; + return MOVE_NO_EFFECT; } /* Used in netslide.c and sixteen.c for cursor movement around edge. */ diff --git a/mosaic.c b/mosaic.c index b2cb0a5..8cca7b9 100644 --- a/mosaic.c +++ b/mosaic.c @@ -1190,7 +1190,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->prev_cur_x = ui->cur_x; ui->prev_cur_y = ui->cur_y; move_cursor(button, &ui->cur_x, &ui->cur_y, state->width, - state->height, false); + state->height, false, NULL); ui->cur_visible = true; return MOVE_UI_UPDATE; } else if (IS_CURSOR_SELECT(button)) { diff --git a/palisade.c b/palisade.c index 83b5983..028633b 100644 --- a/palisade.c +++ b/palisade.c @@ -969,7 +969,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, int dir, i = ui->y * w + ui->x; x = ui->x; y = ui->y; - move_cursor(button, &x, &y, w, h, false); + move_cursor(button, &x, &y, w, h, false, NULL); if (OUT_OF_BOUNDS(x, y, w, h)) return NULL; for (dir = 0; dir < 4; ++dir) @@ -989,7 +989,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, return string(80, "F%d,%d,%dF%d,%d,%d", ui->x, ui->y, flag, x, y, newflag); } else { - move_cursor(button, &ui->x, &ui->y, w, h, false); + move_cursor(button, &ui->x, &ui->y, w, h, false, NULL); return MOVE_UI_UPDATE; } } diff --git a/pattern.c b/pattern.c index 1eafaff..734b70b 100644 --- a/pattern.c +++ b/pattern.c @@ -1395,7 +1395,8 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (IS_CURSOR_MOVE(button)) { int x = ui->cur_x, y = ui->cur_y, newstate; char buf[80]; - move_cursor(button, &ui->cur_x, &ui->cur_y, state->common->w, state->common->h, false); + move_cursor(button, &ui->cur_x, &ui->cur_y, + state->common->w, state->common->h, false, NULL); ui->cur_visible = true; if (!control && !shift) return MOVE_UI_UPDATE; diff --git a/pearl.c b/pearl.c index 6c64ee9..51897b0 100644 --- a/pearl.c +++ b/pearl.c @@ -2201,10 +2201,10 @@ static char *interpret_move(const game_state *state, game_ui *ui, move = mark_in_direction(state, ui->curx, ui->cury, KEY_DIRECTION(button), control, tmpbuf); if (control && !shift && *move) - move_cursor(button, &ui->curx, &ui->cury, w, h, false); + move_cursor(button, &ui->curx, &ui->cury, w, h, false, NULL); return move; } else { - move_cursor(button, &ui->curx, &ui->cury, w, h, false); + move_cursor(button, &ui->curx, &ui->cury, w, h, false, NULL); if (ui->ndragcoords >= 0) update_ui_drag(state, ui, ui->curx, ui->cury); } diff --git a/pegs.c b/pegs.c index 1a2b9cd..c770bf3 100644 --- a/pegs.c +++ b/pegs.c @@ -947,7 +947,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, /* Not jumping; move cursor as usual, making sure we don't * leave the gameboard (which may be an irregular shape) */ int cx = ui->cur_x, cy = ui->cur_y; - move_cursor(button, &cx, &cy, w, h, false); + move_cursor(button, &cx, &cy, w, h, false, NULL); ui->cur_visible = true; if (state->grid[cy*w+cx] == GRID_HOLE || state->grid[cy*w+cx] == GRID_PEG) { diff --git a/puzzles.h b/puzzles.h index b4d33de..f545653 100644 --- a/puzzles.h +++ b/puzzles.h @@ -424,7 +424,8 @@ void draw_rect_outline(drawing *dr, int x, int y, int w, int h, /* Draw a set of rectangle corners (e.g. for a cursor display). */ void draw_rect_corners(drawing *dr, int cx, int cy, int r, int col); -void move_cursor(int button, int *x, int *y, int maxw, int maxh, bool wrap); +char *move_cursor(int button, int *x, int *y, int maxw, int maxh, bool wrap, + bool *visible); /* Used in netslide.c and sixteen.c for cursor movement around edge. */ int c2pos(int w, int h, int cx, int cy); diff --git a/rect.c b/rect.c index a20cf18..7228837 100644 --- a/rect.c +++ b/rect.c @@ -2415,7 +2415,8 @@ static char *interpret_move(const game_state *from, game_ui *ui, enddrag = true; erasing = (button == RIGHT_RELEASE); } else if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cur_x, &ui->cur_y, from->w, from->h, false); + move_cursor(button, &ui->cur_x, &ui->cur_y, from->w, from->h, false, + NULL); ui->cur_visible = true; active = true; if (!ui->cur_dragging) return MOVE_UI_UPDATE; diff --git a/signpost.c b/signpost.c index 4f7eaf3..38c4795 100644 --- a/signpost.c +++ b/signpost.c @@ -1511,7 +1511,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, char buf[80]; if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cx, &ui->cy, state->w, state->h, false); + move_cursor(button, &ui->cx, &ui->cy, state->w, state->h, false, NULL); ui->cshow = true; if (ui->dragging) { ui->dx = COORD(ui->cx) + TILE_SIZE/2; diff --git a/singles.c b/singles.c index 0270331..23b8a4c 100644 --- a/singles.c +++ b/singles.c @@ -1505,7 +1505,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, enum { NONE, TOGGLE_BLACK, TOGGLE_CIRCLE, UI } action = NONE; if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cx, &ui->cy, state->w, state->h, true); + move_cursor(button, &ui->cx, &ui->cy, state->w, state->h, true, NULL); ui->cshow = true; action = UI; } else if (IS_CURSOR_SELECT(button)) { diff --git a/sixteen.c b/sixteen.c index 1f4c7e1..f8763ff 100644 --- a/sixteen.c +++ b/sixteen.c @@ -634,9 +634,9 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (x < 0 || x >= state->w || y < 0 || y >= state->h) return NULL; move_cursor(button | pad, &x, &y, - state->w, state->h, false); + state->w, state->h, false, NULL); move_cursor(button | pad, &xwrap, &ywrap, - state->w, state->h, true); + state->w, state->h, true, NULL); if (x != xwrap) { sprintf(buf, "R%d,%c1", y, x ? '+' : '-'); @@ -657,7 +657,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, int x = ui->cur_x + 1, y = ui->cur_y + 1; move_cursor(button | pad, &x, &y, - state->w + 2, state->h + 2, false); + state->w + 2, state->h + 2, false, NULL); if (x == 0 && y == 0) { int t = ui->cur_x; diff --git a/slant.c b/slant.c index 134d49e..6ce0a49 100644 --- a/slant.c +++ b/slant.c @@ -1739,7 +1739,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, action = (button == CURSOR_SELECT2) ? ANTICLOCKWISE : CLOCKWISE; } else if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cur_x, &ui->cur_y, w, h, false); + move_cursor(button, &ui->cur_x, &ui->cur_y, w, h, false, NULL); ui->cur_visible = true; return MOVE_UI_UPDATE; } else if (button == '\\' || button == '\b' || button == '/') { diff --git a/solo.c b/solo.c index d934110..29ae1dd 100644 --- a/solo.c +++ b/solo.c @@ -4661,7 +4661,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, } } if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->hx, &ui->hy, cr, cr, false); + move_cursor(button, &ui->hx, &ui->hy, cr, cr, false, NULL); ui->hshow = true; ui->hcursor = true; return MOVE_UI_UPDATE; diff --git a/tents.c b/tents.c index ff4af33..607b6ab 100644 --- a/tents.c +++ b/tents.c @@ -1678,7 +1678,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (shift || control) { int len = 0, i, indices[2]; indices[0] = ui->cx + w * ui->cy; - move_cursor(button, &ui->cx, &ui->cy, w, h, false); + move_cursor(button, &ui->cx, &ui->cy, w, h, false, NULL); indices[1] = ui->cx + w * ui->cy; /* NONTENTify all unique traversed eligible squares */ @@ -1693,7 +1693,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, tmpbuf[len] = '\0'; if (len) return dupstr(tmpbuf); } else - move_cursor(button, &ui->cx, &ui->cy, w, h, false); + move_cursor(button, &ui->cx, &ui->cy, w, h, false, NULL); return MOVE_UI_UPDATE; } if (ui->cdisp) { diff --git a/towers.c b/towers.c index 718f9f6..297ada8 100644 --- a/towers.c +++ b/towers.c @@ -1501,7 +1501,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, } return NULL; } - move_cursor(button, &ui->hx, &ui->hy, w, w, false); + move_cursor(button, &ui->hx, &ui->hy, w, w, false, NULL); ui->hshow = true; ui->hcursor = true; return MOVE_UI_UPDATE; diff --git a/unequal.c b/unequal.c index 4b2bc42..0adee9d 100644 --- a/unequal.c +++ b/unequal.c @@ -1553,7 +1553,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (shift_or_control) { int nx = ui->hx, ny = ui->hy, i; bool self; - move_cursor(button, &nx, &ny, ds->order, ds->order, false); + move_cursor(button, &nx, &ny, ds->order, ds->order, false, NULL); ui->hshow = true; ui->hcursor = true; @@ -1582,7 +1582,8 @@ static char *interpret_move(const game_state *state, game_ui *ui, return dupstr(buf); } else { - move_cursor(button, &ui->hx, &ui->hy, ds->order, ds->order, false); + move_cursor(button, &ui->hx, &ui->hy, ds->order, ds->order, false, + NULL); ui->hshow = true; ui->hcursor = true; return MOVE_UI_UPDATE; diff --git a/unfinished/group.c b/unfinished/group.c index b008e82..8eac96a 100644 --- a/unfinished/group.c +++ b/unfinished/group.c @@ -1615,7 +1615,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, if (IS_CURSOR_MOVE(button)) { int cx = find_in_sequence(state->sequence, w, ui->hx); int cy = find_in_sequence(state->sequence, w, ui->hy); - move_cursor(button, &cx, &cy, w, w, false); + move_cursor(button, &cx, &cy, w, w, false, NULL); ui->hx = state->sequence[cx]; ui->hy = state->sequence[cy]; ui->hshow = true; diff --git a/unruly.c b/unruly.c index 18c411f..eddd641 100644 --- a/unruly.c +++ b/unruly.c @@ -1628,7 +1628,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, /* Keyboard move */ if (IS_CURSOR_MOVE(button)) { - move_cursor(button, &ui->cx, &ui->cy, w2, h2, false); + move_cursor(button, &ui->cx, &ui->cy, w2, h2, false, NULL); ui->cursor = true; return MOVE_UI_UPDATE; }