diff options
Diffstat (limited to 'apps/plugins/puzzles/src/puzzles.h')
-rw-r--r-- | apps/plugins/puzzles/src/puzzles.h | 251 |
1 files changed, 176 insertions, 75 deletions
diff --git a/apps/plugins/puzzles/src/puzzles.h b/apps/plugins/puzzles/src/puzzles.h index 29b00ddaf0..44a056d78f 100644 --- a/apps/plugins/puzzles/src/puzzles.h +++ b/apps/plugins/puzzles/src/puzzles.h | |||
@@ -18,6 +18,9 @@ | |||
18 | #define STR_INT(x) #x | 18 | #define STR_INT(x) #x |
19 | #define STR(x) STR_INT(x) | 19 | #define STR(x) STR_INT(x) |
20 | 20 | ||
21 | /* An upper bound on the length of sprintf'ed integers (signed or unsigned). */ | ||
22 | #define MAX_DIGITS(x) (sizeof(x) * CHAR_BIT / 3 + 2) | ||
23 | |||
21 | /* NB not perfect because they evaluate arguments multiple times. */ | 24 | /* NB not perfect because they evaluate arguments multiple times. */ |
22 | #ifndef max | 25 | #ifndef max |
23 | #define max(x,y) ( (x)>(y) ? (x) : (y) ) | 26 | #define max(x,y) ( (x)>(y) ? (x) : (y) ) |
@@ -69,6 +72,7 @@ enum { | |||
69 | (m) == CURSOR_RIGHT || (m) == CURSOR_LEFT ) | 72 | (m) == CURSOR_RIGHT || (m) == CURSOR_LEFT ) |
70 | #define IS_CURSOR_SELECT(m) ( (m) == CURSOR_SELECT || (m) == CURSOR_SELECT2) | 73 | #define IS_CURSOR_SELECT(m) ( (m) == CURSOR_SELECT || (m) == CURSOR_SELECT2) |
71 | #define IS_UI_FAKE_KEY(m) ( (m) > UI_LOWER_BOUND && (m) < UI_UPPER_BOUND ) | 74 | #define IS_UI_FAKE_KEY(m) ( (m) > UI_LOWER_BOUND && (m) < UI_UPPER_BOUND ) |
75 | #define STRIP_BUTTON_MODIFIERS(m) ( (unsigned)(m) & ~MOD_MASK ) | ||
72 | 76 | ||
73 | /* | 77 | /* |
74 | * Flags in the back end's `flags' word. | 78 | * Flags in the back end's `flags' word. |
@@ -83,14 +87,6 @@ enum { | |||
83 | #define REQUIRE_NUMPAD ( 1 << 11 ) | 87 | #define REQUIRE_NUMPAD ( 1 << 11 ) |
84 | /* end of `flags' word definitions */ | 88 | /* end of `flags' word definitions */ |
85 | 89 | ||
86 | #ifdef _WIN32_WCE | ||
87 | /* Pocket PC devices have small, portrait screen that requires more vivid colours */ | ||
88 | #define SMALL_SCREEN | ||
89 | #define PORTRAIT_SCREEN | ||
90 | #define VIVID_COLOURS | ||
91 | #define STYLUS_BASED | ||
92 | #endif | ||
93 | |||
94 | #define IGNOREARG(x) ( (x) = (x) ) | 90 | #define IGNOREARG(x) ( (x) = (x) ) |
95 | 91 | ||
96 | typedef struct frontend frontend; | 92 | typedef struct frontend frontend; |
@@ -132,8 +128,13 @@ typedef struct psdata psdata; | |||
132 | */ | 128 | */ |
133 | enum { C_STRING, C_CHOICES, C_BOOLEAN, C_END }; | 129 | enum { C_STRING, C_CHOICES, C_BOOLEAN, C_END }; |
134 | struct config_item { | 130 | struct config_item { |
135 | /* Not dynamically allocated */ | 131 | /* Not dynamically allocated: the GUI display name for the option */ |
136 | const char *name; | 132 | const char *name; |
133 | /* Not dynamically allocated: the keyword identifier for the | ||
134 | * option. Only examined in the case where this structure is being | ||
135 | * used for options that appear in config files, i.e. the | ||
136 | * get_prefs method fills this in but configure does not. */ | ||
137 | const char *kw; | ||
137 | /* Value from the above C_* enum */ | 138 | /* Value from the above C_* enum */ |
138 | int type; | 139 | int type; |
139 | union { | 140 | union { |
@@ -151,6 +152,13 @@ struct config_item { | |||
151 | */ | 152 | */ |
152 | const char *choicenames; | 153 | const char *choicenames; |
153 | /* | 154 | /* |
155 | * choicekws is non-NULL, not dynamically allocated, and | ||
156 | * contains a parallel list of keyword strings used to | ||
157 | * represent the enumeration in config files. As with 'kw' | ||
158 | * above, this is only expected to be set by get_prefs. | ||
159 | */ | ||
160 | const char *choicekws; | ||
161 | /* | ||
154 | * Indicates the chosen index from the options in | 162 | * Indicates the chosen index from the options in |
155 | * choicenames. In the above example, 0==Foo, 1==Bar and | 163 | * choicenames. In the above example, 0==Foo, 1==Bar and |
156 | * 2==Baz. | 164 | * 2==Baz. |
@@ -256,8 +264,10 @@ void draw_text(drawing *dr, int x, int y, int fonttype, int fontsize, | |||
256 | int align, int colour, const char *text); | 264 | int align, int colour, const char *text); |
257 | void draw_rect(drawing *dr, int x, int y, int w, int h, int colour); | 265 | void draw_rect(drawing *dr, int x, int y, int w, int h, int colour); |
258 | void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour); | 266 | void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour); |
259 | void draw_polygon(drawing *dr, int *coords, int npoints, | 267 | void draw_polygon(drawing *dr, const int *coords, int npoints, |
260 | int fillcolour, int outlinecolour); | 268 | int fillcolour, int outlinecolour); |
269 | void draw_polygon_fallback(drawing *dr, const int *coords, int npoints, | ||
270 | int fillcolour, int outlinecolour); | ||
261 | void draw_circle(drawing *dr, int cx, int cy, int radius, | 271 | void draw_circle(drawing *dr, int cx, int cy, int radius, |
262 | int fillcolour, int outlinecolour); | 272 | int fillcolour, int outlinecolour); |
263 | void draw_thick_line(drawing *dr, float thickness, | 273 | void draw_thick_line(drawing *dr, float thickness, |
@@ -307,13 +317,16 @@ void midend_free(midend *me); | |||
307 | const game *midend_which_game(midend *me); | 317 | const game *midend_which_game(midend *me); |
308 | void midend_set_params(midend *me, game_params *params); | 318 | void midend_set_params(midend *me, game_params *params); |
309 | game_params *midend_get_params(midend *me); | 319 | game_params *midend_get_params(midend *me); |
310 | void midend_size(midend *me, int *x, int *y, bool user_size); | 320 | void midend_size(midend *me, int *x, int *y, bool user_size, |
321 | double device_pixel_ratio); | ||
311 | void midend_reset_tilesize(midend *me); | 322 | void midend_reset_tilesize(midend *me); |
312 | void midend_new_game(midend *me); | 323 | void midend_new_game(midend *me); |
313 | void midend_restart_game(midend *me); | 324 | void midend_restart_game(midend *me); |
314 | void midend_stop_anim(midend *me); | 325 | void midend_stop_anim(midend *me); |
315 | bool midend_process_key(midend *me, int x, int y, int button); | 326 | enum { PKR_QUIT = 0, PKR_SOME_EFFECT, PKR_NO_EFFECT, PKR_UNUSED }; |
327 | int midend_process_key(midend *me, int x, int y, int button); | ||
316 | key_label *midend_request_keys(midend *me, int *nkeys); | 328 | key_label *midend_request_keys(midend *me, int *nkeys); |
329 | const char *midend_current_key_label(midend *me, int button); | ||
317 | void midend_force_redraw(midend *me); | 330 | void midend_force_redraw(midend *me); |
318 | void midend_redraw(midend *me); | 331 | void midend_redraw(midend *me); |
319 | float *midend_colours(midend *me, int *ncolours); | 332 | float *midend_colours(midend *me, int *ncolours); |
@@ -322,7 +335,7 @@ void midend_timer(midend *me, float tplus); | |||
322 | struct preset_menu *midend_get_presets(midend *me, int *id_limit); | 335 | struct preset_menu *midend_get_presets(midend *me, int *id_limit); |
323 | int midend_which_preset(midend *me); | 336 | int midend_which_preset(midend *me); |
324 | bool midend_wants_statusbar(midend *me); | 337 | bool midend_wants_statusbar(midend *me); |
325 | enum { CFG_SETTINGS, CFG_SEED, CFG_DESC, CFG_FRONTEND_SPECIFIC }; | 338 | enum { CFG_SETTINGS, CFG_SEED, CFG_DESC, CFG_PREFS, CFG_FRONTEND_SPECIFIC }; |
326 | config_item *midend_get_config(midend *me, int which, char **wintitle); | 339 | config_item *midend_get_config(midend *me, int which, char **wintitle); |
327 | const char *midend_set_config(midend *me, int which, config_item *cfg); | 340 | const char *midend_set_config(midend *me, int which, config_item *cfg); |
328 | const char *midend_game_id(midend *me, const char *id); | 341 | const char *midend_game_id(midend *me, const char *id); |
@@ -343,6 +356,11 @@ void midend_serialise(midend *me, | |||
343 | const char *midend_deserialise(midend *me, | 356 | const char *midend_deserialise(midend *me, |
344 | bool (*read)(void *ctx, void *buf, int len), | 357 | bool (*read)(void *ctx, void *buf, int len), |
345 | void *rctx); | 358 | void *rctx); |
359 | const char *midend_load_prefs( | ||
360 | midend *me, bool (*read)(void *ctx, void *buf, int len), void *rctx); | ||
361 | void midend_save_prefs(midend *me, | ||
362 | void (*write)(void *ctx, const void *buf, int len), | ||
363 | void *wctx); | ||
346 | const char *identify_game(char **name, | 364 | const char *identify_game(char **name, |
347 | bool (*read)(void *ctx, void *buf, int len), | 365 | bool (*read)(void *ctx, void *buf, int len), |
348 | void *rctx); | 366 | void *rctx); |
@@ -374,12 +392,22 @@ void free_cfg(config_item *cfg); | |||
374 | void free_keys(key_label *keys, int nkeys); | 392 | void free_keys(key_label *keys, int nkeys); |
375 | void obfuscate_bitmap(unsigned char *bmp, int bits, bool decode); | 393 | void obfuscate_bitmap(unsigned char *bmp, int bits, bool decode); |
376 | char *fgetline(FILE *fp); | 394 | char *fgetline(FILE *fp); |
395 | char *make_prefs_path(const char *dir, const char *sep, | ||
396 | const game *game, const char *suffix); | ||
397 | int n_times_root_k(int n, int k); | ||
377 | 398 | ||
378 | /* allocates output each time. len is always in bytes of binary data. | 399 | /* allocates output each time. len is always in bytes of binary data. |
379 | * May assert (or just go wrong) if lengths are unchecked. */ | 400 | * May assert (or just go wrong) if lengths are unchecked. */ |
380 | char *bin2hex(const unsigned char *in, int inlen); | 401 | char *bin2hex(const unsigned char *in, int inlen); |
381 | unsigned char *hex2bin(const char *in, int outlen); | 402 | unsigned char *hex2bin(const char *in, int outlen); |
382 | 403 | ||
404 | /* Returns 0 or 1 if the environment variable is set, or dflt if not. | ||
405 | * dflt may be a third value if it needs to be. */ | ||
406 | int getenv_bool(const char *name, int dflt); | ||
407 | |||
408 | /* Mixes two colours in specified proportions. */ | ||
409 | void colour_mix(const float src1[3], const float src2[3], float p, | ||
410 | float dst[3]); | ||
383 | /* Sets (and possibly dims) background from frontend default colour, | 411 | /* Sets (and possibly dims) background from frontend default colour, |
384 | * and auto-generates highlight and lowlight colours too. */ | 412 | * and auto-generates highlight and lowlight colours too. */ |
385 | void game_mkhighlight(frontend *fe, float *ret, | 413 | void game_mkhighlight(frontend *fe, float *ret, |
@@ -392,14 +420,15 @@ void game_mkhighlight_specific(frontend *fe, float *ret, | |||
392 | /* Randomly shuffles an array of items. */ | 420 | /* Randomly shuffles an array of items. */ |
393 | void shuffle(void *array, int nelts, int eltsize, random_state *rs); | 421 | void shuffle(void *array, int nelts, int eltsize, random_state *rs); |
394 | 422 | ||
395 | /* Draw a rectangle outline, using the drawing API's draw_line. */ | 423 | /* Draw a rectangle outline, using the drawing API's draw_polygon. */ |
396 | void draw_rect_outline(drawing *dr, int x, int y, int w, int h, | 424 | void draw_rect_outline(drawing *dr, int x, int y, int w, int h, |
397 | int colour); | 425 | int colour); |
398 | 426 | ||
399 | /* Draw a set of rectangle corners (e.g. for a cursor display). */ | 427 | /* Draw a set of rectangle corners (e.g. for a cursor display). */ |
400 | void draw_rect_corners(drawing *dr, int cx, int cy, int r, int col); | 428 | void draw_rect_corners(drawing *dr, int cx, int cy, int r, int col); |
401 | 429 | ||
402 | void move_cursor(int button, int *x, int *y, int maxw, int maxh, bool wrap); | 430 | char *move_cursor(int button, int *x, int *y, int maxw, int maxh, bool wrap, |
431 | bool *visible); | ||
403 | 432 | ||
404 | /* Used in netslide.c and sixteen.c for cursor movement around edge. */ | 433 | /* Used in netslide.c and sixteen.c for cursor movement around edge. */ |
405 | int c2pos(int w, int h, int cx, int cy); | 434 | int c2pos(int w, int h, int cx, int cy); |
@@ -416,37 +445,55 @@ void draw_text_outline(drawing *dr, int x, int y, int fonttype, | |||
416 | * less than buffer size. */ | 445 | * less than buffer size. */ |
417 | void copy_left_justified(char *buf, size_t sz, const char *str); | 446 | void copy_left_justified(char *buf, size_t sz, const char *str); |
418 | 447 | ||
419 | /* An ugly, but working float-to-string implementation for platforms | ||
420 | * that don't have one */ | ||
421 | int ftoa(char *buf, float f); | ||
422 | |||
423 | /* Returns a generic label based on the value of `button.' To be used | 448 | /* Returns a generic label based on the value of `button.' To be used |
424 | whenever a `label' field returned by the request_keys() game | 449 | whenever a `label' field returned by the request_keys() game |
425 | function is NULL. Dynamically allocated, to be freed by caller. */ | 450 | function is NULL. Dynamically allocated, to be freed by caller. */ |
426 | char *button2label(int button); | 451 | char *button2label(int button); |
427 | 452 | ||
453 | /* Swap two regions of memory. The two regions must not | ||
454 | * overlap. (Note: the natural name for this might be "memswap", but | ||
455 | * the mem* namespace is reserved for future expansion by the C99 | ||
456 | * standard per clause 7.26.11.1.) */ | ||
457 | void swap_regions(void *av, void *bv, size_t size); | ||
458 | |||
459 | /* comparator for sorting ints with qsort() */ | ||
460 | int compare_integers(const void *av, const void *bv); | ||
461 | |||
428 | /* | 462 | /* |
429 | * dsf.c | 463 | * dsf.c |
430 | */ | 464 | */ |
431 | int *snew_dsf(int size); | 465 | typedef struct DSF DSF; |
432 | 466 | DSF *dsf_new(int size); | |
433 | void print_dsf(int *dsf, int size); | 467 | void dsf_free(DSF *dsf); |
434 | 468 | ||
435 | /* Return the canonical element of the equivalence class containing element | 469 | void dsf_copy(DSF *to, DSF *from); |
436 | * val. If 'inverse' is non-NULL, this function will put into it a flag | 470 | |
437 | * indicating whether the canonical element is inverse to val. */ | 471 | /* Basic dsf operations, return the canonical element of a class, |
438 | int edsf_canonify(int *dsf, int val, bool *inverse); | 472 | * check if two elements are in the same class, and return the size of |
439 | int dsf_canonify(int *dsf, int val); | 473 | * a class. These work on all types of dsf. */ |
440 | int dsf_size(int *dsf, int val); | 474 | int dsf_canonify(DSF *dsf, int n); |
441 | 475 | bool dsf_equivalent(DSF *dsf, int n1, int n2); | |
442 | /* Allow the caller to specify that two elements should be in the same | 476 | int dsf_size(DSF *dsf, int n); |
443 | * equivalence class. If 'inverse' is true, the elements are actually opposite | 477 | |
444 | * to one another in some sense. This function will fail an assertion if the | 478 | /* Merge two elements and their classes. Not legal on a flip dsf. */ |
445 | * caller gives it self-contradictory data, ie if two elements are claimed to | 479 | void dsf_merge(DSF *dsf, int n1, int n2); |
446 | * be both opposite and non-opposite. */ | 480 | |
447 | void edsf_merge(int *dsf, int v1, int v2, bool inverse); | 481 | /* Special dsf that tracks the minimal element of every equivalence |
448 | void dsf_merge(int *dsf, int v1, int v2); | 482 | * class, and a function to query it. */ |
449 | void dsf_init(int *dsf, int len); | 483 | DSF *dsf_new_min(int size); |
484 | int dsf_minimal(DSF *dsf, int n); | ||
485 | |||
486 | /* Special dsf that tracks whether pairs of elements in the same class | ||
487 | * have flipped sense relative to each other. Merge function takes an | ||
488 | * argument saying whether n1 and n2 are opposite to each other; | ||
489 | * canonify function will report whether n is opposite to the returned | ||
490 | * element. */ | ||
491 | DSF *dsf_new_flip(int size); | ||
492 | void dsf_merge_flip(DSF *dsf, int n1, int n2, bool flip); | ||
493 | int dsf_canonify_flip(DSF *dsf, int n, bool *flip); | ||
494 | |||
495 | /* Reinitialise a dsf to the starting 'all elements distinct' state. */ | ||
496 | void dsf_reinit(DSF *dsf); | ||
450 | 497 | ||
451 | /* | 498 | /* |
452 | * tdq.c | 499 | * tdq.c |
@@ -507,7 +554,7 @@ void random_free(random_state *state); | |||
507 | char *random_state_encode(random_state *state); | 554 | char *random_state_encode(random_state *state); |
508 | random_state *random_state_decode(const char *input); | 555 | random_state *random_state_decode(const char *input); |
509 | /* random.c also exports SHA, which occasionally comes in useful. */ | 556 | /* random.c also exports SHA, which occasionally comes in useful. */ |
510 | #if __STDC_VERSION__ >= 199901L | 557 | #if HAVE_STDINT_H |
511 | #include <stdint.h> | 558 | #include <stdint.h> |
512 | typedef uint32_t uint32; | 559 | typedef uint32_t uint32; |
513 | #elif UINT_MAX >= 4294967295L | 560 | #elif UINT_MAX >= 4294967295L |
@@ -532,7 +579,7 @@ void SHA_Simple(const void *p, int len, unsigned char *output); | |||
532 | document *document_new(int pw, int ph, float userscale); | 579 | document *document_new(int pw, int ph, float userscale); |
533 | void document_free(document *doc); | 580 | void document_free(document *doc); |
534 | void document_add_puzzle(document *doc, const game *game, game_params *par, | 581 | void document_add_puzzle(document *doc, const game *game, game_params *par, |
535 | game_state *st, game_state *st2); | 582 | game_ui *ui, game_state *st, game_state *st2); |
536 | int document_npages(const document *doc); | 583 | int document_npages(const document *doc); |
537 | void document_begin(const document *doc, drawing *dr); | 584 | void document_begin(const document *doc, drawing *dr); |
538 | void document_end(const document *doc, drawing *dr); | 585 | void document_end(const document *doc, drawing *dr); |
@@ -564,7 +611,9 @@ void free_combi(combi_ctx *combi); | |||
564 | * divvy.c | 611 | * divvy.c |
565 | */ | 612 | */ |
566 | /* divides w*h rectangle into pieces of size k. Returns w*h dsf. */ | 613 | /* divides w*h rectangle into pieces of size k. Returns w*h dsf. */ |
567 | int *divvy_rectangle(int w, int h, int k, random_state *rs); | 614 | DSF *divvy_rectangle(int w, int h, int k, random_state *rs); |
615 | /* Same, but only tries once, and may fail. (Exposed for test program.) */ | ||
616 | DSF *divvy_rectangle_attempt(int w, int h, int k, random_state *rs); | ||
568 | 617 | ||
569 | /* | 618 | /* |
570 | * findloop.c | 619 | * findloop.c |
@@ -661,19 +710,24 @@ struct game { | |||
661 | bool can_format_as_text_ever; | 710 | bool can_format_as_text_ever; |
662 | bool (*can_format_as_text_now)(const game_params *params); | 711 | bool (*can_format_as_text_now)(const game_params *params); |
663 | char *(*text_format)(const game_state *state); | 712 | char *(*text_format)(const game_state *state); |
713 | config_item *(*get_prefs)(game_ui *ui); | ||
714 | void (*set_prefs)(game_ui *ui, const config_item *cfg); | ||
664 | game_ui *(*new_ui)(const game_state *state); | 715 | game_ui *(*new_ui)(const game_state *state); |
665 | void (*free_ui)(game_ui *ui); | 716 | void (*free_ui)(game_ui *ui); |
666 | char *(*encode_ui)(const game_ui *ui); | 717 | char *(*encode_ui)(const game_ui *ui); |
667 | void (*decode_ui)(game_ui *ui, const char *encoding); | 718 | void (*decode_ui)(game_ui *ui, const char *encoding, |
719 | const game_state *state); | ||
668 | key_label *(*request_keys)(const game_params *params, int *nkeys); | 720 | key_label *(*request_keys)(const game_params *params, int *nkeys); |
669 | void (*changed_state)(game_ui *ui, const game_state *oldstate, | 721 | void (*changed_state)(game_ui *ui, const game_state *oldstate, |
670 | const game_state *newstate); | 722 | const game_state *newstate); |
723 | const char *(*current_key_label)(const game_ui *ui, | ||
724 | const game_state *state, int button); | ||
671 | char *(*interpret_move)(const game_state *state, game_ui *ui, | 725 | char *(*interpret_move)(const game_state *state, game_ui *ui, |
672 | const game_drawstate *ds, int x, int y, int button); | 726 | const game_drawstate *ds, int x, int y, int button); |
673 | game_state *(*execute_move)(const game_state *state, const char *move); | 727 | game_state *(*execute_move)(const game_state *state, const char *move); |
674 | int preferred_tilesize; | 728 | int preferred_tilesize; |
675 | void (*compute_size)(const game_params *params, int tilesize, | 729 | void (*compute_size)(const game_params *params, int tilesize, |
676 | int *x, int *y); | 730 | const game_ui *ui, int *x, int *y); |
677 | void (*set_size)(drawing *dr, game_drawstate *ds, | 731 | void (*set_size)(drawing *dr, game_drawstate *ds, |
678 | const game_params *params, int tilesize); | 732 | const game_params *params, int tilesize); |
679 | float *(*colours)(frontend *fe, int *ncolours); | 733 | float *(*colours)(frontend *fe, int *ncolours); |
@@ -693,51 +747,86 @@ struct game { | |||
693 | int *x, int *y, int *w, int *h); | 747 | int *x, int *y, int *w, int *h); |
694 | int (*status)(const game_state *state); | 748 | int (*status)(const game_state *state); |
695 | bool can_print, can_print_in_colour; | 749 | bool can_print, can_print_in_colour; |
696 | void (*print_size)(const game_params *params, float *x, float *y); | 750 | void (*print_size)(const game_params *params, const game_ui *ui, |
697 | void (*print)(drawing *dr, const game_state *state, int tilesize); | 751 | float *x, float *y); |
752 | void (*print)(drawing *dr, const game_state *state, const game_ui *ui, | ||
753 | int tilesize); | ||
698 | bool wants_statusbar; | 754 | bool wants_statusbar; |
699 | bool is_timed; | 755 | bool is_timed; |
700 | bool (*timing_state)(const game_state *state, game_ui *ui); | 756 | bool (*timing_state)(const game_state *state, game_ui *ui); |
701 | int flags; | 757 | int flags; |
702 | }; | 758 | }; |
703 | 759 | ||
760 | #define GET_HANDLE_AS_TYPE(dr, type) ((type*)((dr)->handle)) | ||
761 | |||
762 | struct drawing { | ||
763 | const drawing_api *api; | ||
764 | void *handle; | ||
765 | }; | ||
766 | |||
704 | /* | 767 | /* |
705 | * Data structure containing the drawing API implemented by the | 768 | * Data structure containing the drawing API implemented by the |
706 | * front end and also by cross-platform printing modules such as | 769 | * front end and also by cross-platform printing modules such as |
707 | * PostScript. | 770 | * PostScript. |
708 | */ | 771 | */ |
709 | struct drawing_api { | 772 | struct drawing_api { |
710 | void (*draw_text)(void *handle, int x, int y, int fonttype, int fontsize, | 773 | /* |
774 | * API version. Increment this when there is a breaking change to | ||
775 | * this API which requires front ends to change. | ||
776 | * | ||
777 | * There is expliclty not a public LATEST_API_VERSION define, so | ||
778 | * that front end authors will need to manually intervene when the | ||
779 | * version number changes. Naturally, this should be done | ||
780 | * sparingly. | ||
781 | * | ||
782 | * If a function is ever added to this API, please move this field | ||
783 | * to the _end_ of the structure, so that changes thereafter will | ||
784 | * shift the position of the version and lead to a compilation | ||
785 | * error if old implementations are not updated. Then remove this | ||
786 | * comment. | ||
787 | * | ||
788 | * The latest version number is 1. | ||
789 | * | ||
790 | * Change log: | ||
791 | * | ||
792 | * Version 1 (2024-08-14): Introduction of version number, in | ||
793 | * conjunction with changing every API function to take `drawing | ||
794 | * *` instead of `void *`. See commit f379130 for the detailed | ||
795 | * rationale behind this change. | ||
796 | */ | ||
797 | int version; | ||
798 | |||
799 | void (*draw_text)(drawing *dr, int x, int y, int fonttype, int fontsize, | ||
711 | int align, int colour, const char *text); | 800 | int align, int colour, const char *text); |
712 | void (*draw_rect)(void *handle, int x, int y, int w, int h, int colour); | 801 | void (*draw_rect)(drawing *dr, int x, int y, int w, int h, int colour); |
713 | void (*draw_line)(void *handle, int x1, int y1, int x2, int y2, | 802 | void (*draw_line)(drawing *dr, int x1, int y1, int x2, int y2, |
714 | int colour); | 803 | int colour); |
715 | void (*draw_polygon)(void *handle, int *coords, int npoints, | 804 | void (*draw_polygon)(drawing *dr, const int *coords, int npoints, |
716 | int fillcolour, int outlinecolour); | 805 | int fillcolour, int outlinecolour); |
717 | void (*draw_circle)(void *handle, int cx, int cy, int radius, | 806 | void (*draw_circle)(drawing *dr, int cx, int cy, int radius, |
718 | int fillcolour, int outlinecolour); | 807 | int fillcolour, int outlinecolour); |
719 | void (*draw_update)(void *handle, int x, int y, int w, int h); | 808 | void (*draw_update)(drawing *dr, int x, int y, int w, int h); |
720 | void (*clip)(void *handle, int x, int y, int w, int h); | 809 | void (*clip)(drawing *dr, int x, int y, int w, int h); |
721 | void (*unclip)(void *handle); | 810 | void (*unclip)(drawing *dr); |
722 | void (*start_draw)(void *handle); | 811 | void (*start_draw)(drawing *dr); |
723 | void (*end_draw)(void *handle); | 812 | void (*end_draw)(drawing *dr); |
724 | void (*status_bar)(void *handle, const char *text); | 813 | void (*status_bar)(drawing *dr, const char *text); |
725 | blitter *(*blitter_new)(void *handle, int w, int h); | 814 | blitter *(*blitter_new)(drawing *dr, int w, int h); |
726 | void (*blitter_free)(void *handle, blitter *bl); | 815 | void (*blitter_free)(drawing *dr, blitter *bl); |
727 | void (*blitter_save)(void *handle, blitter *bl, int x, int y); | 816 | void (*blitter_save)(drawing *dr, blitter *bl, int x, int y); |
728 | void (*blitter_load)(void *handle, blitter *bl, int x, int y); | 817 | void (*blitter_load)(drawing *dr, blitter *bl, int x, int y); |
729 | void (*begin_doc)(void *handle, int pages); | 818 | void (*begin_doc)(drawing *dr, int pages); |
730 | void (*begin_page)(void *handle, int number); | 819 | void (*begin_page)(drawing *dr, int number); |
731 | void (*begin_puzzle)(void *handle, float xm, float xc, | 820 | void (*begin_puzzle)(drawing *dr, float xm, float xc, |
732 | float ym, float yc, int pw, int ph, float wmm); | 821 | float ym, float yc, int pw, int ph, float wmm); |
733 | void (*end_puzzle)(void *handle); | 822 | void (*end_puzzle)(drawing *dr); |
734 | void (*end_page)(void *handle, int number); | 823 | void (*end_page)(drawing *dr, int number); |
735 | void (*end_doc)(void *handle); | 824 | void (*end_doc)(drawing *dr); |
736 | void (*line_width)(void *handle, float width); | 825 | void (*line_width)(drawing *dr, float width); |
737 | void (*line_dotted)(void *handle, bool dotted); | 826 | void (*line_dotted)(drawing *dr, bool dotted); |
738 | char *(*text_fallback)(void *handle, const char *const *strings, | 827 | char *(*text_fallback)(drawing *dr, const char *const *strings, |
739 | int nstrings); | 828 | int nstrings); |
740 | void (*draw_thick_line)(void *handle, float thickness, | 829 | void (*draw_thick_line)(drawing *dr, float thickness, |
741 | float x1, float y1, float x2, float y2, | 830 | float x1, float y1, float x2, float y2, |
742 | int colour); | 831 | int colour); |
743 | }; | 832 | }; |
@@ -750,17 +839,29 @@ struct drawing_api { | |||
750 | #ifdef COMBINED | 839 | #ifdef COMBINED |
751 | extern const game *gamelist[]; | 840 | extern const game *gamelist[]; |
752 | extern const int gamecount; | 841 | extern const int gamecount; |
842 | /* Also pre-declare every individual 'struct game' we expect */ | ||
843 | #define GAME(x) extern const game x; | ||
844 | #include "generated-games.h" | ||
845 | #undef GAME | ||
753 | #else | 846 | #else |
754 | extern const game thegame; | 847 | extern const game thegame; |
755 | #endif | 848 | #endif |
756 | 849 | ||
757 | /* | 850 | /* |
758 | * Special string value to return from interpret_move in the case | 851 | * Special string values to return from interpret_move. |
759 | * where the game UI has been updated but no actual move is being | 852 | * |
760 | * appended to the undo chain. Must be declared as a non-const char, | 853 | * MOVE_UI_UPDATE is for the case where the game UI has been updated |
761 | * but should never actually be modified by anyone. | 854 | * but no actual move is being appended to the undo chain. |
855 | * | ||
856 | * MOVE_NO_EFFECT is for when the key was understood by the puzzle, | ||
857 | * but it happens that there isn't effect, not even a UI change. | ||
858 | * | ||
859 | * MOVE_UNUSED is for keys that the puzzle has no use for at all. | ||
860 | * | ||
861 | * Each must be declared as a non-const char, but should never | ||
862 | * actually be modified by anyone. | ||
762 | */ | 863 | */ |
763 | extern char UI_UPDATE[]; | 864 | extern char MOVE_UI_UPDATE[], MOVE_NO_EFFECT[], MOVE_UNUSED[]; |
764 | 865 | ||
765 | /* A little bit of help to lazy developers */ | 866 | /* A little bit of help to lazy developers */ |
766 | #define DEFAULT_STATUSBAR_TEXT "Use status_bar() to fill this in." | 867 | #define DEFAULT_STATUSBAR_TEXT "Use status_bar() to fill this in." |