chiark / gitweb /
HTML Help support for Puzzles, with the same kind of automatic
authorSimon Tatham <anakin@pobox.com>
Sun, 24 Dec 2006 15:56:47 +0000 (15:56 +0000)
committerSimon Tatham <anakin@pobox.com>
Sun, 24 Dec 2006 15:56:47 +0000 (15:56 +0000)
fallback behaviour as PuTTY's support.

[originally from svn r7009]

29 files changed:
blackbox.c
bridges.c
cube.c
dominosa.c
fifteen.c
flip.c
guess.c
inertia.c
lightup.c
loopy.c
map.c
mines.c
net.c
netslide.c
nullgame.c
pattern.c
pegs.c
puzzles.h
rect.c
samegame.c
sixteen.c
slant.c
solo.c
tents.c
twiddle.c
unfinished/pearl.c
unfinished/sokoban.c
untangle.c
windows.c

index 165ee2e67c8eb77154e171c40d6517256a020e09..dbb499981b667ab11766924f193c8c35bc6fcbf8 100644 (file)
@@ -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,
index 93faf327349b111770b51f6f1a0a92dfd6584ffb..a8fd8b3a9df9620fea7f7c82de6278d4ef85ba9d 100644 (file)
--- 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 8270f1beffcb8d15d42643cb989b64d1d034db3f..bc919730b89941f164d6e9d551c4c6e08014051c 100644 (file)
--- 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,
index 91745670fa676056625e8b54875ad03a133fad01..0264675bc96e398d031ed90b58351553c30c8342 100644 (file)
@@ -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,
index c4b0adda4ab404ceee8448e22d5e98e1703be09c..d3a02f390b6463a0c27a38ac0af376753d0f6ab5 100644 (file)
--- 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 a8fd47190605bd8f285d972dde87cd122cf1f1b2..0a537c3dc52c3c60483fe4dc78af3f14292ace6e 100644 (file)
--- 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 d1e123a22331ea3a833fe0d5d847313e5b015919..6fb3630383bf04863ae1f2584d678c61b95f5333 100644 (file)
--- 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,
index 15a329f25222b0dde2c42ce0794ff65532b9b7bc..10ea53856a7ff90ef5a2bd811bb064255574396b 100644 (file)
--- 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,
index f1d9cc75f2f314f27a80111112fb00e37a3485d1..14c6974067a8839a3d0a555278ab7f82b149e46b 100644 (file)
--- 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 20d1e967d3c7c89aada812420c95c7eacda5fcae..8976b69134a3fa70997f83edde60931107e0c7f5 100644 (file)
--- 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 d70d4282b6fcb374567af57a775633e19c8b3633..098fc47d355c2d0343c207dccf3f9d456f3ee723 100644 (file)
--- 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 e0e6eb0d1fe6400ceff32cea78160e6c2e11c217..73aea0b247ef78b8085f3dc60c623ef1c97b8b6d 100644 (file)
--- 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 c479963e546b26115eff24a331077c514fecb948..eb83a1617d35832deb401bd598fef926a6c63688 100644 (file)
--- 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,
index d935b954c3922f9d7578cc39ba04c840c1be9104..8f2da255773a293f6525ec0464ea68576759931a 100644 (file)
@@ -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,
index 05baed3bace9eb2defc4655147b4c0a0f66fa56b..4888a78a5edb74f0ee2d31d2576546d4b56d6373 100644 (file)
@@ -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,
index eacade4eb57cbc7bdca7d98513b6d5099cf42416..a85877f9ba79012eb404d2174d14f5215c0b1dbc 100644 (file)
--- 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 560bf0ae318e1f9b648cac3523ee182e649dc1bd..d1addd1482da5607b8e2f596c4749e16dfc1b2b4 100644 (file)
--- 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,
index f67da1c6425c42d78817c85f4820ff956a8c3688..49c2a07b1bb5679407d05bfd9c7b7cc0d061bbfa 100644 (file)
--- 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 1b232ae82067e3cfde469504dea17987114587fd..e73db7df21b545971510a0458d88b8a58080052b 100644 (file)
--- 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,
index 2a28f1d9227abb69ad6716af3a937195e2586cfd..f66e8898191224d7aac14527582c38bdb96865dd 100644 (file)
@@ -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,
index 75751b972dcf97f231f5789172befcd62664058b..f16bc96ef05c534551aec737838250d5b2d7d3e4 100644 (file)
--- 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 c1ddc09bed9fb6b2a7e3922ba4cb60f0a4f14891..fc472091eddcefb44a9d87196974b253a9dbd523 100644 (file)
--- 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 923113a98b408ca2536a1fc835613dada8208fca..a2f40eb0805da3f21c44c6f2999fe4dd03ccc563 100644 (file)
--- 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 afed169ca4bd3f48d9519e6b647c5e64a1477801..e5e8c6f3b781966987f65a32586976221c1e02be 100644 (file)
--- 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,
index daf691c325312ac39273b6bb508991b53008f92b..6b89d3af3eaf5ab9fa7d7260c1ef5f3838408cc2 100644 (file)
--- 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,
index 0ef6247e1f7dd1b14e9e555352fed3f736a5e7db..af2541559842fca4930577deb436281abb8d6edc 100644 (file)
@@ -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,
index d67f9073e569d9b372031295bf3c3ad094bf18a2..bb2e68fe2c4e317bd120a0a92cf21eb23fb9ce44 100644 (file)
@@ -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,
index ed672e41a0f35feb9ec2ec6ecf626ffa94a2150d..18b4acaac9679613d71306e8150634398e36d10c 100644 (file)
@@ -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,
index f4cbfe4dce07c4b768729d877a99b9ff9180be76..f7621dfdfbc6b8c011aac357174e622d6744ab19 100644 (file)
--- a/windows.c
+++ b/windows.c
@@ -4,6 +4,7 @@
 
 #include <windows.h>
 #include <commctrl.h>
+#include <htmlhelp.h>
 
 #include <stdio.h>
 #include <assert.h>
 
 #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;
 }