X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=puzzles.h;h=47c164c163b6fc6220a6a5f0fbf8eb06de7b05ed;hb=db313b3948d27244dd7c34c2609c66d6204d8931;hp=a40201686e6e98274c62dba28b3bf7283b3910f1;hpb=251b21c41813055d9c416378508b1ee038bc3dac;p=sgt-puzzles.git diff --git a/puzzles.h b/puzzles.h index a402016..47c164c 100644 --- a/puzzles.h +++ b/puzzles.h @@ -47,6 +47,15 @@ enum { CURSOR_RIGHT, CURSOR_SELECT, CURSOR_SELECT2, + /* UI_* are special keystrokes generated by front ends in response + * to menu actions, never passed to back ends */ + UI_LOWER_BOUND, + UI_QUIT, + UI_NEWGAME, + UI_SOLVE, + UI_UNDO, + UI_REDO, + UI_UPPER_BOUND, /* made smaller because of 'limited range of datatype' errors. */ MOD_CTRL = 0x1000, @@ -64,6 +73,7 @@ enum { #define IS_CURSOR_MOVE(m) ( (m) == CURSOR_UP || (m) == CURSOR_DOWN || \ (m) == CURSOR_RIGHT || (m) == CURSOR_LEFT ) #define IS_CURSOR_SELECT(m) ( (m) == CURSOR_SELECT || (m) == CURSOR_SELECT2) +#define IS_UI_FAKE_KEY(m) ( (m) > UI_LOWER_BOUND && (m) < UI_UPPER_BOUND ) /* * Flags in the back end's `flags' word. @@ -153,6 +163,54 @@ struct config_item { int ival; }; +/* + * Structure used to communicate the presets menu from midend to + * frontend. In principle, it's also used to pass the same information + * from game to midend, though games that don't specify a menu + * hierarchy (i.e. most of them) will use the simpler fetch_preset() + * function to return an unstructured list. + * + * A tree of these structures always belongs to the midend, and only + * the midend should ever need to free it. The front end should treat + * them as read-only. + */ +struct preset_menu_entry { + char *title; + /* Exactly one of the next two fields is NULL, depending on + * whether this entry is a submenu title or an actual preset */ + game_params *params; + struct preset_menu *submenu; + /* Every preset menu entry has a number allocated by the mid-end, + * so that midend_which_preset() can return a value that + * identifies an entry anywhere in the menu hierarchy. The values + * will be allocated reasonably densely from 1 upwards (so it's + * reasonable for the front end to use them as array indices if it + * needs to store GUI state per menu entry), but no other + * guarantee is given about their ordering. + * + * Entries containing submenus have ids too - not only the actual + * presets are numbered. */ + int id; +}; +struct preset_menu { + int n_entries; /* number of entries actually in use */ + int entries_size; /* space currently allocated in this array */ + struct preset_menu_entry *entries; +}; +/* For games which do want to directly return a tree of these, here + * are convenience routines (in midend.c) for constructing one. These + * assume that 'title' and 'encoded_params' are already dynamically + * allocated by the caller; the resulting preset_menu tree takes + * ownership of them. */ +struct preset_menu *preset_menu_new(void); +struct preset_menu *preset_menu_add_submenu(struct preset_menu *parent, + char *title); +void preset_menu_add_preset(struct preset_menu *menu, + char *title, game_params *params); +/* Helper routine front ends can use for one of the ways they might + * want to organise their preset menu usage */ +game_params *preset_menu_lookup_by_id(struct preset_menu *menu, int id); + /* * Platform routines */ @@ -242,9 +300,7 @@ void midend_redraw(midend *me); float *midend_colours(midend *me, int *ncolours); void midend_freeze_timer(midend *me, float tprop); void midend_timer(midend *me, float tplus); -int midend_num_presets(midend *me); -void midend_fetch_preset(midend *me, int n, - char **name, game_params **params); +struct preset_menu *midend_get_presets(midend *me, int *id_limit); int midend_which_preset(midend *me); int midend_wants_statusbar(midend *me); enum { CFG_SETTINGS, CFG_SEED, CFG_DESC, CFG_FRONTEND_SPECIFIC }; @@ -330,6 +386,11 @@ void pos2c(int w, int h, int pos, int *cx, int *cy); void draw_text_outline(drawing *dr, int x, int y, int fonttype, int fontsize, int align, int text_colour, int outline_colour, char *text); + +/* Copies text left-justified with spaces. Length of string must be + * less than buffer size. */ +void copy_left_justified(char *buf, size_t sz, const char *str); + /* * dsf.c */ @@ -467,6 +528,41 @@ void free_combi(combi_ctx *combi); /* divides w*h rectangle into pieces of size k. Returns w*h dsf. */ int *divvy_rectangle(int w, int h, int k, random_state *rs); +/* + * findloop.c + */ +struct findloopstate; +struct findloopstate *findloop_new_state(int nvertices); +void findloop_free_state(struct findloopstate *); +/* + * Callback provided by the client code to enumerate the graph + * vertices joined directly to a given vertex. + * + * Semantics: if vertex >= 0, return one of its neighbours; if vertex + * < 0, return a previously unmentioned neighbour of whatever vertex + * was last passed as input. Write to 'ctx' as necessary to store + * state. In either case, return < 0 if no such vertex can be found. + */ +typedef int (*neighbour_fn_t)(int vertex, void *ctx); +/* + * Actual function to find loops. 'ctx' will be passed unchanged to + * the 'neighbour' function to query graph edges. Returns FALSE if no + * loop was found, or TRUE if one was. + */ +int findloop_run(struct findloopstate *state, int nvertices, + neighbour_fn_t neighbour, void *ctx); +/* + * Query whether an edge is part of a loop, in the output of + * find_loops. + * + * Due to the internal storage format, if you pass u,v which are not + * connected at all, the output will be TRUE. (The algorithm actually + * stores an exhaustive list of *non*-loop edges, because there are + * fewer of those, so really it's querying whether the edge is on that + * list.) + */ +int findloop_is_loop_edge(struct findloopstate *state, int u, int v); + /* * Data structure containing the function calls and data specific * to a particular game. This is enclosed in a data structure so @@ -479,6 +575,7 @@ struct game { const char *winhelp_topic, *htmlhelp_topic; game_params *(*default_params)(void); int (*fetch_preset)(int i, char **name, game_params **params); + struct preset_menu *(*preset_menu)(void); void (*decode_params)(game_params *, char const *string); char *(*encode_params)(const game_params *, int full); void (*free_params)(game_params *params); @@ -587,4 +684,7 @@ extern const int gamecount; extern const game thegame; #endif +/* A little bit of help to lazy developers */ +#define DEFAULT_STATUSBAR_TEXT "Use status_bar() to fill this in." + #endif /* PUZZLES_PUZZLES_H */