HTML Help support for Puzzles, with the same kind of automatic
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 24 Dec 2006 15:56:47 +0000 (15:56 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 24 Dec 2006 15:56:47 +0000 (15:56 +0000)
fallback behaviour as PuTTY's support.

git-svn-id: svn://svn.tartarus.org/sgt/puzzles@7009 cda61777-01e9-0310-a592-d414129be87e

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 165ee2e..dbb4999 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 93faf32..a8fd8b3 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 8270f1b..bc91973 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 9174567..0264675 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 c4b0add..d3a02f3 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 a8fd471..0a537c3 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 d1e123a..6fb3630 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 15a329f..10ea538 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 f1d9cc7..14c6974 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 20d1e96..8976b69 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 d70d428..098fc47 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 e0e6eb0..73aea0b 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 c479963..eb83a16 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 d935b95..8f2da25 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 05baed3..4888a78 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 eacade4..a85877f 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 560bf0a..d1addd1 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 f67da1c..49c2a07 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 1b232ae..e73db7d 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 2a28f1d..f66e889 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 75751b9..f16bc96 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 c1ddc09..fc47209 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 923113a..a2f40eb 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 afed169..e5e8c6f 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 daf691c..6b89d3a 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 0ef6247..af25415 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 d67f907..bb2e68f 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 ed672e4..18b4aca 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 f4cbfe4..f7621df 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;
 }