diff options
| author | Ben Harris <bjh21@bjh21.me.uk> | 2023-08-09 09:43:04 +0100 |
|---|---|---|
| committer | Ben Harris <bjh21@bjh21.me.uk> | 2023-08-09 11:44:25 +0100 |
| commit | 5ec86c03a8bc911bb3dbd77fb7c827eeca975594 (patch) | |
| tree | 13814a3493ff9c813b6bbd28c28dc90d55524549 | |
| parent | 7ada9a5742dd4766cc42909ac01bbb2505f74e47 (diff) | |
| download | puzzles-5ec86c03a8bc911bb3dbd77fb7c827eeca975594.zip puzzles-5ec86c03a8bc911bb3dbd77fb7c827eeca975594.tar.gz puzzles-5ec86c03a8bc911bb3dbd77fb7c827eeca975594.tar.bz2 puzzles-5ec86c03a8bc911bb3dbd77fb7c827eeca975594.tar.xz | |
move_cursor(): handle visible flag; return useful value
This adds an extra parameter to move_cursor() that's an optional pointer
to a bool indicating whether the cursor is visible. This allows for
centralising the common idiom of having the keyboard cursor become
visible when a cursor key is pressed. Consistently with the vast
majority of existing puzzles, the cursor moves even if it was invisible
before, and becomes visible even if it can't move.
The function now also returns one of the special constants that can be
returned by interpret_move(), so that the caller can correctly return
MOVE_UI_UPDATE or MOVE_NO_EFFECT without needing to carefully check for
changes itself.
Callers are updated only to the extent that they all pass NULL as the
new argument. Most of them could now be substantially simplified.
| -rw-r--r-- | blackbox.c | 2 | ||||
| -rw-r--r-- | bridges.c | 2 | ||||
| -rw-r--r-- | devel.but | 13 | ||||
| -rw-r--r-- | dominosa.c | 2 | ||||
| -rw-r--r-- | fifteen.c | 2 | ||||
| -rw-r--r-- | filling.c | 2 | ||||
| -rw-r--r-- | galaxies.c | 3 | ||||
| -rw-r--r-- | keen.c | 2 | ||||
| -rw-r--r-- | lightup.c | 3 | ||||
| -rw-r--r-- | magnets.c | 3 | ||||
| -rw-r--r-- | map.c | 2 | ||||
| -rw-r--r-- | mines.c | 3 | ||||
| -rw-r--r-- | misc.c | 14 | ||||
| -rw-r--r-- | mosaic.c | 2 | ||||
| -rw-r--r-- | palisade.c | 4 | ||||
| -rw-r--r-- | pattern.c | 3 | ||||
| -rw-r--r-- | pearl.c | 4 | ||||
| -rw-r--r-- | pegs.c | 2 | ||||
| -rw-r--r-- | puzzles.h | 3 | ||||
| -rw-r--r-- | rect.c | 3 | ||||
| -rw-r--r-- | signpost.c | 2 | ||||
| -rw-r--r-- | singles.c | 2 | ||||
| -rw-r--r-- | sixteen.c | 6 | ||||
| -rw-r--r-- | slant.c | 2 | ||||
| -rw-r--r-- | solo.c | 2 | ||||
| -rw-r--r-- | tents.c | 4 | ||||
| -rw-r--r-- | towers.c | 2 | ||||
| -rw-r--r-- | unequal.c | 5 | ||||
| -rw-r--r-- | unfinished/group.c | 2 | ||||
| -rw-r--r-- | unruly.c | 2 |
30 files changed, 64 insertions, 39 deletions
@@ -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) || @@ -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, @@ -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); @@ -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)) { @@ -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^^ */ @@ -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; } @@ -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; @@ -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; @@ -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 @@ -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)) { @@ -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; @@ -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; } @@ -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. */ @@ -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)) { @@ -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; } } @@ -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; @@ -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); } @@ -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) { @@ -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); @@ -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; @@ -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; @@ -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)) { @@ -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; @@ -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 == '/') { @@ -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; @@ -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) { @@ -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; @@ -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; @@ -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; } |