From 750037d76de7c1ab5d46aaf8a712f32599e7d563 Mon Sep 17 00:00:00 2001 From: simon Date: Sun, 24 Dec 2006 15:56:47 +0000 Subject: [PATCH] HTML Help support for Puzzles, with the same kind of automatic fallback behaviour as PuTTY's support. git-svn-id: svn://svn.tartarus.org/sgt/puzzles@7009 cda61777-01e9-0310-a592-d414129be87e --- blackbox.c | 2 +- bridges.c | 2 +- cube.c | 2 +- dominosa.c | 2 +- fifteen.c | 2 +- flip.c | 2 +- guess.c | 2 +- inertia.c | 2 +- lightup.c | 2 +- loopy.c | 2 +- map.c | 2 +- mines.c | 2 +- net.c | 2 +- netslide.c | 2 +- nullgame.c | 2 +- pattern.c | 2 +- pegs.c | 2 +- puzzles.h | 2 +- rect.c | 2 +- samegame.c | 2 +- sixteen.c | 2 +- slant.c | 2 +- solo.c | 2 +- tents.c | 2 +- twiddle.c | 2 +- unfinished/pearl.c | 2 +- unfinished/sokoban.c | 2 +- untangle.c | 2 +- windows.c | 204 +++++++++++++++++++++++++++++++++++++++++---------- 29 files changed, 192 insertions(+), 68 deletions(-) diff --git a/blackbox.c b/blackbox.c index 165ee2e..dbb4999 100644 --- a/blackbox.c +++ b/blackbox.c @@ -1398,7 +1398,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Black Box", "games.blackbox", + "Black Box", "games.blackbox", "blackbox", default_params, game_fetch_preset, decode_params, diff --git a/bridges.c b/bridges.c index 93faf32..a8fd8b3 100644 --- a/bridges.c +++ b/bridges.c @@ -2629,7 +2629,7 @@ static void game_print(drawing *dr, game_state *state, int ts) #endif const struct game thegame = { - "Bridges", "games.bridges", + "Bridges", "games.bridges", "bridges", default_params, game_fetch_preset, decode_params, diff --git a/cube.c b/cube.c index 8270f1b..bc91973 100644 --- a/cube.c +++ b/cube.c @@ -1700,7 +1700,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Cube", "games.cube", + "Cube", "games.cube", "cube", default_params, game_fetch_preset, decode_params, diff --git a/dominosa.c b/dominosa.c index 9174567..0264675 100644 --- a/dominosa.c +++ b/dominosa.c @@ -1740,7 +1740,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Dominosa", "games.dominosa", + "Dominosa", "games.dominosa", "dominosa", default_params, game_fetch_preset, decode_params, diff --git a/fifteen.c b/fifteen.c index c4b0add..d3a02f3 100644 --- a/fifteen.c +++ b/fifteen.c @@ -838,7 +838,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Fifteen", "games.fifteen", + "Fifteen", "games.fifteen", "fifteen", default_params, game_fetch_preset, decode_params, diff --git a/flip.c b/flip.c index a8fd471..0a537c3 100644 --- a/flip.c +++ b/flip.c @@ -1266,7 +1266,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Flip", "games.flip", + "Flip", "games.flip", "flip", default_params, game_fetch_preset, decode_params, diff --git a/guess.c b/guess.c index d1e123a..6fb3630 100644 --- a/guess.c +++ b/guess.c @@ -1324,7 +1324,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Guess", "games.guess", + "Guess", "games.guess", "guess", default_params, game_fetch_preset, decode_params, diff --git a/inertia.c b/inertia.c index 15a329f..10ea538 100644 --- a/inertia.c +++ b/inertia.c @@ -2152,7 +2152,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Inertia", "games.inertia", + "Inertia", "games.inertia", "inertia", default_params, game_fetch_preset, decode_params, diff --git a/lightup.c b/lightup.c index f1d9cc7..14c6974 100644 --- a/lightup.c +++ b/lightup.c @@ -2216,7 +2216,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Light Up", "games.lightup", + "Light Up", "games.lightup", "lightup", default_params, game_fetch_preset, decode_params, diff --git a/loopy.c b/loopy.c index 20d1e96..8976b69 100644 --- a/loopy.c +++ b/loopy.c @@ -3811,7 +3811,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Loopy", "games.loopy", + "Loopy", "games.loopy", "loopy", default_params, game_fetch_preset, decode_params, diff --git a/map.c b/map.c index d70d428..098fc47 100644 --- a/map.c +++ b/map.c @@ -3084,7 +3084,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Map", "games.map", + "Map", "games.map", "map", default_params, game_fetch_preset, decode_params, diff --git a/mines.c b/mines.c index e0e6eb0..73aea0b 100644 --- a/mines.c +++ b/mines.c @@ -3070,7 +3070,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Mines", "games.mines", + "Mines", "games.mines", "mines", default_params, game_fetch_preset, decode_params, diff --git a/net.c b/net.c index c479963..eb83a16 100644 --- a/net.c +++ b/net.c @@ -2824,7 +2824,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Net", "games.net", + "Net", "games.net", "net", default_params, game_fetch_preset, decode_params, diff --git a/netslide.c b/netslide.c index d935b95..8f2da25 100644 --- a/netslide.c +++ b/netslide.c @@ -1780,7 +1780,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Netslide", "games.netslide", + "Netslide", "games.netslide", "netslide", default_params, game_fetch_preset, decode_params, diff --git a/nullgame.c b/nullgame.c index 05baed3..4888a78 100644 --- a/nullgame.c +++ b/nullgame.c @@ -251,7 +251,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Null Game", NULL, + "Null Game", NULL, NULL, default_params, game_fetch_preset, decode_params, diff --git a/pattern.c b/pattern.c index eacade4..a85877f 100644 --- a/pattern.c +++ b/pattern.c @@ -1243,7 +1243,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Pattern", "games.pattern", + "Pattern", "games.pattern", "pattern", default_params, game_fetch_preset, decode_params, diff --git a/pegs.c b/pegs.c index 560bf0a..d1addd1 100644 --- a/pegs.c +++ b/pegs.c @@ -1186,7 +1186,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Pegs", "games.pegs", + "Pegs", "games.pegs", "pegs", default_params, game_fetch_preset, decode_params, diff --git a/puzzles.h b/puzzles.h index f67da1c..49c2a07 100644 --- a/puzzles.h +++ b/puzzles.h @@ -364,7 +364,7 @@ void free_combi(combi_ctx *combi); */ struct game { const char *name; - const char *winhelp_topic; + const char *winhelp_topic, *htmlhelp_topic; game_params *(*default_params)(void); int (*fetch_preset)(int i, char **name, game_params **params); void (*decode_params)(game_params *, char const *string); diff --git a/rect.c b/rect.c index 1b232ae..e73db7d 100644 --- a/rect.c +++ b/rect.c @@ -2836,7 +2836,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Rectangles", "games.rectangles", + "Rectangles", "games.rectangles", "rectangles", default_params, game_fetch_preset, decode_params, diff --git a/samegame.c b/samegame.c index 2a28f1d..f66e889 100644 --- a/samegame.c +++ b/samegame.c @@ -1626,7 +1626,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Same Game", "games.samegame", + "Same Game", "games.samegame", "samegame", default_params, game_fetch_preset, decode_params, diff --git a/sixteen.c b/sixteen.c index 75751b9..f16bc96 100644 --- a/sixteen.c +++ b/sixteen.c @@ -1014,7 +1014,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Sixteen", "games.sixteen", + "Sixteen", "games.sixteen", "sixteen", default_params, game_fetch_preset, decode_params, diff --git a/slant.c b/slant.c index c1ddc09..fc47209 100644 --- a/slant.c +++ b/slant.c @@ -2186,7 +2186,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Slant", "games.slant", + "Slant", "games.slant", "slant", default_params, game_fetch_preset, decode_params, diff --git a/solo.c b/solo.c index 923113a..a2f40eb 100644 --- a/solo.c +++ b/solo.c @@ -3052,7 +3052,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Solo", "games.solo", + "Solo", "games.solo", "solo", default_params, game_fetch_preset, decode_params, diff --git a/tents.c b/tents.c index afed169..e5e8c6f 100644 --- a/tents.c +++ b/tents.c @@ -2053,7 +2053,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Tents", "games.tents", + "Tents", "games.tents", "tents", default_params, game_fetch_preset, decode_params, diff --git a/twiddle.c b/twiddle.c index daf691c..6b89d3a 100644 --- a/twiddle.c +++ b/twiddle.c @@ -1181,7 +1181,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Twiddle", "games.twiddle", + "Twiddle", "games.twiddle", "twiddle", default_params, game_fetch_preset, decode_params, diff --git a/unfinished/pearl.c b/unfinished/pearl.c index 0ef6247..af25415 100644 --- a/unfinished/pearl.c +++ b/unfinished/pearl.c @@ -1364,7 +1364,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Pearl", NULL, + "Pearl", NULL, NULL, default_params, game_fetch_preset, decode_params, diff --git a/unfinished/sokoban.c b/unfinished/sokoban.c index d67f907..bb2e68f 100644 --- a/unfinished/sokoban.c +++ b/unfinished/sokoban.c @@ -1414,7 +1414,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Sokoban", NULL, + "Sokoban", NULL, NULL, default_params, game_fetch_preset, decode_params, diff --git a/untangle.c b/untangle.c index ed672e4..18b4aca 100644 --- a/untangle.c +++ b/untangle.c @@ -1425,7 +1425,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) #endif const struct game thegame = { - "Untangle", "games.untangle", + "Untangle", "games.untangle", "untangle", default_params, game_fetch_preset, decode_params, diff --git a/windows.c b/windows.c index f4cbfe4..f7621df 100644 --- a/windows.c +++ b/windows.c @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -35,6 +36,16 @@ #define HELP_FILE_NAME "puzzles.hlp" #define HELP_CNT_NAME "puzzles.cnt" +#define CHM_FILE_NAME "puzzles.chm" + +typedef HWND (CALLBACK *htmlhelp_t)(HWND, LPCSTR, UINT, DWORD); +static DWORD html_help_cookie; +static htmlhelp_t htmlhelp; +static HINSTANCE hh_dll; +enum { NONE, HLP, CHM } help_type; +char *help_path; +const char *help_topic; +int help_has_contents; #ifdef DEBUGGING static FILE *debug_fp = NULL; @@ -119,8 +130,7 @@ struct frontend { HFONT cfgfont; HBRUSH oldbr; HPEN oldpen; - char *help_path; - int help_has_contents; + int help_running; enum { DRAWING, PRINTING, NOTHING } drawstatus; DOCINFO di; int printcount, printw, printh, printsolns, printcurr, printcolour; @@ -981,31 +991,150 @@ void write_clip(HWND hwnd, char *data) } /* - * See if we can find a help file. + * Set up Help and see if we can find a help file. */ -static void find_help_file(frontend *fe) +static void init_help(void) { char b[2048], *p, *q, *r; FILE *fp; - if (!fe->help_path) { - GetModuleFileName(NULL, b, sizeof(b) - 1); - r = b; - p = strrchr(b, '\\'); - if (p && p >= r) r = p+1; - q = strrchr(b, ':'); - if (q && q >= r) r = q+1; - strcpy(r, HELP_FILE_NAME); - if ( (fp = fopen(b, "r")) != NULL) { - fe->help_path = dupstr(b); - fclose(fp); - } else - fe->help_path = NULL; - strcpy(r, HELP_CNT_NAME); - if ( (fp = fopen(b, "r")) != NULL) { - fe->help_has_contents = TRUE; - fclose(fp); - } else - fe->help_has_contents = FALSE; + + /* + * Find the executable file path, so we can look alongside + * it for help files. Trim the filename off the end. + */ + GetModuleFileName(NULL, b, sizeof(b) - 1); + r = b; + p = strrchr(b, '\\'); + if (p && p >= r) r = p+1; + q = strrchr(b, ':'); + if (q && q >= r) r = q+1; + + /* + * Try HTML Help first. + */ + strcpy(r, CHM_FILE_NAME); + if ( (fp = fopen(b, "r")) != NULL) { + fclose(fp); + + /* + * We have a .CHM. See if we can use it. + */ + hh_dll = LoadLibrary("hhctrl.ocx"); + if (hh_dll) { + htmlhelp = (htmlhelp_t)GetProcAddress(hh_dll, "HtmlHelpA"); + if (!htmlhelp) + FreeLibrary(hh_dll); + } + if (htmlhelp) { + htmlhelp(NULL, NULL, HH_INITIALIZE, (DWORD)&html_help_cookie); + help_path = dupstr(b); + help_type = CHM; + help_topic = thegame.htmlhelp_topic; + return; + } + } + + /* + * Now try old-style .HLP. + */ + strcpy(r, HELP_FILE_NAME); + if ( (fp = fopen(b, "r")) != NULL) { + fclose(fp); + + help_path = dupstr(b); + help_type = HLP; + + help_topic = thegame.winhelp_topic; + + /* + * See if there's a .CNT file alongside it. + */ + strcpy(r, HELP_CNT_NAME); + if ( (fp = fopen(b, "r")) != NULL) { + fclose(fp); + help_has_contents = TRUE; + } else + help_has_contents = FALSE; + + return; + } + + help_type = NONE; /* didn't find any */ +} + +/* + * Start Help. + */ +static void start_help(frontend *fe, char *topic) +{ + char *str = NULL; + int cmd; + + switch (help_type) { + case HLP: + assert(help_path); + if (topic) { + str = snewn(10+strlen(topic), char); + sprintf(str, "JI(`',`%s')", topic); + cmd = HELP_COMMAND; + } else if (help_has_contents) { + cmd = HELP_FINDER; + } else { + cmd = HELP_CONTENTS; + } + WinHelp(fe->hwnd, help_path, cmd, (DWORD)str); + fe->help_running = TRUE; + break; + case CHM: + assert(help_path); + assert(htmlhelp); + if (topic) { + str = snewn(20 + strlen(topic) + strlen(help_path), char); + sprintf(str, "%s::/%s.html>main", help_path, topic); + } else { + str = dupstr(help_path); + } + htmlhelp(fe->hwnd, str, HH_DISPLAY_TOPIC, 0); + fe->help_running = TRUE; + break; + case NONE: + assert(!"This shouldn't happen"); + break; + } + + sfree(str); +} + +/* + * Stop Help on window cleanup. + */ +static void stop_help(frontend *fe) +{ + if (fe->help_running) { + switch (help_type) { + case HLP: + WinHelp(fe->hwnd, help_path, HELP_QUIT, 0); + break; + case CHM: + assert(htmlhelp); + htmlhelp(NULL, NULL, HH_CLOSE_ALL, 0); + break; + case NONE: + assert(!"This shouldn't happen"); + break; + } + fe->help_running = FALSE; + } +} + +/* + * Terminate Help on process exit. + */ +static void cleanup_help(void) +{ + if (help_type == CHM) { + assert(htmlhelp); + htmlhelp(NULL, NULL, HH_UNINITIALIZE, html_help_cookie); } } @@ -1096,14 +1225,13 @@ static frontend *new_window(HINSTANCE inst, char *game_id, char **error) } } - fe->help_path = NULL; - find_help_file(fe); - fe->inst = inst; fe->timer = 0; fe->hwnd = NULL; + fe->help_running = FALSE; + fe->drawstatus = NOTHING; fe->dr = NULL; fe->fontstart = 0; @@ -1235,10 +1363,10 @@ static frontend *new_window(HINSTANCE inst, char *game_id, char **error) menu = CreateMenu(); AppendMenu(bar, MF_ENABLED|MF_POPUP, (UINT)menu, "Help"); AppendMenu(menu, MF_ENABLED, IDM_ABOUT, "About"); - if (fe->help_path) { + if (help_type != NONE) { AppendMenu(menu, MF_SEPARATOR, 0, 0); AppendMenu(menu, MF_ENABLED, IDM_HELPC, "Contents"); - if (thegame.winhelp_topic) { + if (help_topic) { char *item; assert(thegame.name); item = snewn(9+strlen(thegame.name), char); /*ick*/ @@ -2091,19 +2219,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, break; case IDM_HELPC: - assert(fe->help_path); - WinHelp(hwnd, fe->help_path, - fe->help_has_contents ? HELP_FINDER : HELP_CONTENTS, 0); - break; + start_help(fe, NULL); + break; case IDM_GAMEHELP: - assert(fe->help_path); - assert(thegame.winhelp_topic); - { - char *cmd = snewn(10+strlen(thegame.winhelp_topic), char); - sprintf(cmd, "JI(`',`%s')", thegame.winhelp_topic); - WinHelp(hwnd, fe->help_path, HELP_COMMAND, (DWORD)cmd); - sfree(cmd); - } + start_help(fe, help_topic); break; default: { @@ -2118,6 +2237,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } break; case WM_DESTROY: + stop_help(fe); PostQuitMessage(0); return 0; case WM_PAINT: @@ -2333,6 +2453,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) while (*cmdline && isspace((unsigned char)*cmdline)) cmdline++; + init_help(); + if (!new_window(inst, *cmdline ? cmdline : NULL, &error)) { char buf[128]; sprintf(buf, "%.100s Error", thegame.name); @@ -2344,5 +2466,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) DispatchMessage(&msg); } + cleanup_help(); + return msg.wParam; } -- 2.11.0