New backend function: current_key_label()

This provides a way for the front end to ask how a particular key should
be labelled right now (specifically, for a given game_state and
game_ui).  This is useful on feature phones where it's conventional to
put a small caption above each soft key indicating what it currently
does.

The function currently provides labels only for CURSOR_SELECT and
CURSOR_SELECT2.  This is because these are the only keys that need
labelling on KaiOS.

The concept of labelling keys also turns up in the request_keys() call,
but there are quite a few differences.  The labels returned by
current_key_label() are dynamic and likely to vary with each move, while
the labels provided by request_keys() are constant for a given
game_params.  Also, the keys returned by request_keys() don't generally
include CURSOR_SELECT and CURSOR_SELECT2, because those aren't necessary
on platforms with pointing devices.  It might be possible to provide a
unified API covering both of this, but I think it would be quite
difficult to work with.

Where a key is to be unlabelled, current_key_label() is expected to
return an empty string.  This leaves open the possibility of NULL
indicating a fallback to button2label or the label specified by
request_keys() in the future.

It's tempting to try to implement current_key_label() by calling
interpret_move() and parsing its output.  This doesn't work for two
reasons.  One is that interpret_move() is entitled to modify the
game_ui, and there isn't really a practical way to back those changes
out.  The other is that the information returned by interpret_move()
isn't sufficient to generate a label.  For instance, in many puzzles it
generates moves that toggle the state of a square, but we want the label
to reflect which state the square will be toggled to.  The result is
that I've generally ended up pulling bits of code from interpret_move()
and execute_move() together to implement current_key_label().

Alongside the back-end function, there's a midend_current_key_label()
that's a thin wrapper around the back-end function.  It just adds an
assertion about which key's being requested and a default null
implementation so that back-ends can avoid defining the function if it
will do nothing useful.
This commit is contained in:
Ben Harris
2022-12-05 01:13:26 +00:00
parent 1d91522bab
commit a3310ab857
48 changed files with 717 additions and 0 deletions

View File

@ -1692,6 +1692,43 @@ This function should not be called directly by frontends. Instead,
frontends should use \cw{midend_request_keys()}
(\k{midend-request-keys}).
\S{backend-current-key-label} \cw{current_key_label()}
\c const char *(*current_key_label)(const game_ui *ui,
\c const game_state *state, int button);
This function is called to ask the back-end how certain keys should be
labelled on platforms (such a feature phones) where this is
conventional.
These labels are expected to reflect what the keys will do right now,
so they can change depending on the game and UI state.
The \c{ui} and \c{state} arguments describe the state of the game for
which key labels are required.
The \c{button} argument is the same as the one passed to
\cw{interpret_move()}.
At present, the only values of \c{button} that can be passed to
\cw{current_key_label()} are \cw{CURSOR_SELECT} and \cw{CURSOR_SELECT2}.
The return value is a short string describing what the requested key
will do if pressed.
Usually the string should be a static string constant.
If it's really necessary to use a dynamically-allocated string, it
should remain valid until the next call to \cw{current_key_label()} or
\cw{free_ui()} with the same \cw{game_ui} (so it can be referenced from
the \cw{game_ui} and freed at the next one of those calls).
There's no fixed upper limit on the length of string that this
function can return, but more than about 12 characters is likely to
cause problems for front-ends. If two buttons have the same effect,
their labels should be identical so that the front end can detect
this. Similarly, keys that do different things should have different
labels. The label should be an empty string (\cw{""}) if the key does
nothing.
Like \cw{request_keys()}, the \cw{current_key_label} pointer in the
\c{game} structure is allowed to be \cw{NULL}, in which case the
mid-end will treat it as though it always returned \cw{""}.
\S{backend-flags} \c{flags}
\c int flags;
@ -3232,6 +3269,20 @@ labels (i.e. the \cw{key_label} items that have their \cw{label}
fields set to \cw{NULL}) by using \cw{button2label()}
(\k{utils-button2label}).
\H{midend-current-key-label} \cw{midend_current_key_label()}
\c const char *midend_current_key_label(midend *me, int button);
This is a thin wrapper around the backend's \cw{current_key_label()}
function (\k{backend-current-key-label}). Front ends that need to
label \cw{CURSOR_SELECT} or \cw{CURSOR_SELECT2} should call this
function after each move (at least after each call to
\cw{midend_process_key()}) to get the current labels. The front end
should arrange to copy the returned string somewhere before the next
call to the mid-end, just in case it's dynamically allocated. If the
button supplied does nothing, the label returned will be an empty
string.
\H{midend-colours} \cw{midend_colours()}
\c float *midend_colours(midend *me, int *ncolours);