Initial support for HTML Help. All the ad-hoc help-file finding code
[u/mdw/putty] / windows / winhelp.c
diff --git a/windows/winhelp.c b/windows/winhelp.c
new file mode 100644 (file)
index 0000000..f7b2288
--- /dev/null
@@ -0,0 +1,123 @@
+/*\r
+ * winhelp.c: centralised functions to launch Windows help files,\r
+ * and to decide whether to use .HLP or .CHM help in any given\r
+ * situation.\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <assert.h>\r
+\r
+#include "putty.h"\r
+\r
+#include <htmlhelp.h>\r
+\r
+typedef HWND (CALLBACK *htmlhelp_t)(HWND, LPCSTR, UINT, DWORD);\r
+\r
+static char *help_path, *chm_path;\r
+static int help_has_contents;\r
+static int requested_help;\r
+static DWORD html_help_cookie;\r
+static htmlhelp_t htmlhelp;\r
+\r
+void init_help(void)\r
+{\r
+    char b[2048], *p, *q, *r;\r
+    FILE *fp;\r
+\r
+    GetModuleFileName(NULL, b, sizeof(b) - 1);\r
+    r = b;\r
+    p = strrchr(b, '\\');\r
+    if (p && p >= r) r = p+1;\r
+    q = strrchr(b, ':');\r
+    if (q && q >= r) r = q+1;\r
+    strcpy(r, PUTTY_HELP_FILE);\r
+    if ( (fp = fopen(b, "r")) != NULL) {\r
+       help_path = dupstr(b);\r
+       fclose(fp);\r
+    } else\r
+       help_path = NULL;\r
+    strcpy(r, PUTTY_HELP_CONTENTS);\r
+    if ( (fp = fopen(b, "r")) != NULL) {\r
+       help_has_contents = TRUE;\r
+       fclose(fp);\r
+    } else\r
+       help_has_contents = FALSE;\r
+\r
+    strcpy(r, PUTTY_CHM_FILE);\r
+    if ( (fp = fopen(b, "r")) != NULL) {\r
+       chm_path = dupstr(b);\r
+       fclose(fp);\r
+    } else\r
+       chm_path = NULL;\r
+    if (chm_path) {\r
+       HINSTANCE dllHH = LoadLibrary("hhctrl.ocx");\r
+       if (dllHH) {\r
+           htmlhelp = (htmlhelp_t)GetProcAddress(dllHH, "HtmlHelpA");\r
+           if (!htmlhelp)\r
+               FreeLibrary(dllHH);\r
+       }\r
+       if (htmlhelp)\r
+           htmlhelp(NULL, NULL, HH_INITIALIZE, (DWORD)&html_help_cookie);\r
+       else\r
+           chm_path = NULL;\r
+    }\r
+}\r
+\r
+void shutdown_help(void)\r
+{\r
+    if (chm_path)\r
+       htmlhelp(NULL, NULL, HH_UNINITIALIZE, html_help_cookie);\r
+}\r
+\r
+int has_help(void)\r
+{\r
+    /*\r
+     * FIXME: it would be nice here to disregard help_path on\r
+     * platforms that didn't have WINHLP32. But that's probably\r
+     * unrealistic, since even Vista will have it if the user\r
+     * specifically downloads it.\r
+     */\r
+    return (help_path || chm_path);\r
+}\r
+\r
+void launch_help(HWND hwnd, const char *topic)\r
+{\r
+    if (topic) {\r
+       int colonpos = strcspn(topic, ":");\r
+\r
+       if (chm_path) {\r
+           char *fname;\r
+           assert(topic[colonpos] != '\0');\r
+           fname = dupprintf("%s::/%s.html>main", chm_path,\r
+                             topic + colonpos + 1);\r
+           htmlhelp(hwnd, fname, HH_DISPLAY_TOPIC, 0);\r
+           sfree(fname);\r
+       } else if (help_path) {\r
+           char *cmd = dupprintf("JI(`',`%.*s')", colonpos, topic);\r
+           WinHelp(hwnd, help_path, HELP_COMMAND, (DWORD)cmd);\r
+           sfree(cmd);\r
+       }\r
+    } else {\r
+       if (chm_path) {\r
+           htmlhelp(hwnd, chm_path, HH_DISPLAY_TOPIC, 0);\r
+       } else if (help_path) {\r
+           WinHelp(hwnd, help_path,\r
+                   help_has_contents ? HELP_FINDER : HELP_CONTENTS, 0);\r
+       }\r
+    }\r
+    requested_help = TRUE;\r
+}\r
+\r
+void quit_help(HWND hwnd)\r
+{\r
+    if (requested_help) {\r
+       if (chm_path) {\r
+           htmlhelp(NULL, NULL, HH_CLOSE_ALL, 0);\r
+       } else if (help_path) {\r
+           WinHelp(hwnd, help_path, HELP_QUIT, 0);\r
+       }\r
+       requested_help = FALSE;\r
+    }\r
+}\r