X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/83c0438ffd33d0f6a608dceec3c889d65fb74c28..a0f67a83de82f11679d0cf8ea7f170ca808fc596:/windows.c diff --git a/windows.c b/windows.c index f4cbfe4..82767e4 100644 --- a/windows.c +++ b/windows.c @@ -4,6 +4,9 @@ #include #include +#ifndef NO_HTMLHELP +#include +#endif /* NO_HTMLHELP */ #include #include @@ -35,6 +38,19 @@ #define HELP_FILE_NAME "puzzles.hlp" #define HELP_CNT_NAME "puzzles.cnt" +#ifndef NO_HTMLHELP +#define CHM_FILE_NAME "puzzles.chm" +#endif /* NO_HTMLHELP */ + +#ifndef NO_HTMLHELP +typedef HWND (CALLBACK *htmlhelp_t)(HWND, LPCSTR, UINT, DWORD); +static htmlhelp_t htmlhelp; +static HINSTANCE hh_dll; +#endif /* NO_HTMLHELP */ +enum { NONE, HLP, CHM } help_type; +char *help_path; +const char *help_topic; +int help_has_contents; #ifdef DEBUGGING static FILE *debug_fp = NULL; @@ -68,7 +84,7 @@ void debug_printf(char *fmt, ...) va_list ap; va_start(ap, fmt); - vsprintf(buf, fmt, ap); + _vsnprintf(buf, 4095, fmt, ap); dputs(buf); va_end(ap); } @@ -119,8 +135,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,32 +996,155 @@ 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; + +#ifndef NO_HTMLHELP + /* + * 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) { + help_path = dupstr(b); + help_type = CHM; + help_topic = thegame.htmlhelp_topic; + return; + } + } +#endif /* NO_HTMLHELP */ + + /* + * 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, const 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: +#ifndef NO_HTMLHELP + 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; +#endif /* NO_HTMLHELP */ + 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: +#ifndef NO_HTMLHELP + assert(htmlhelp); + htmlhelp(NULL, NULL, HH_CLOSE_ALL, 0); + break; +#endif /* NO_HTMLHELP */ + case NONE: + assert(!"This shouldn't happen"); + break; + } + fe->help_running = FALSE; + } +} + +/* + * Terminate Help on process exit. + */ +static void cleanup_help(void) +{ + /* Nothing to do currently. + * (If we were running HTML Help single-threaded, this is where we'd + * call HH_UNINITIALIZE.) */ } static void check_window_size(frontend *fe, int *px, int *py) @@ -1096,14 +1234,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; @@ -1213,11 +1350,11 @@ static frontend *new_window(HINSTANCE inst, char *game_id, char **error) } AppendMenu(menu, MF_SEPARATOR, 0, 0); - AppendMenu(menu, MF_ENABLED, IDM_LOAD, "Load"); - AppendMenu(menu, MF_ENABLED, IDM_SAVE, "Save"); + AppendMenu(menu, MF_ENABLED, IDM_LOAD, "Load..."); + AppendMenu(menu, MF_ENABLED, IDM_SAVE, "Save..."); AppendMenu(menu, MF_SEPARATOR, 0, 0); if (thegame.can_print) { - AppendMenu(menu, MF_ENABLED, IDM_PRINT, "Print"); + AppendMenu(menu, MF_ENABLED, IDM_PRINT, "Print..."); AppendMenu(menu, MF_SEPARATOR, 0, 0); } AppendMenu(menu, MF_ENABLED, IDM_UNDO, "Undo"); @@ -1235,10 +1372,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 +2228,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 +2246,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } break; case WM_DESTROY: + stop_help(fe); PostQuitMessage(0); return 0; case WM_PAINT: @@ -2321,7 +2450,9 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = inst; - wndclass.hIcon = LoadIcon(inst, IDI_APPLICATION); + wndclass.hIcon = LoadIcon(inst, MAKEINTRESOURCE(200)); + if (!wndclass.hIcon) /* in case resource file is absent */ + wndclass.hIcon = LoadIcon(inst, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = NULL; wndclass.lpszMenuName = NULL; @@ -2333,6 +2464,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 +2477,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) DispatchMessage(&msg); } + cleanup_help(); + return msg.wParam; }