HTML Help support for Puzzles, with the same kind of automatic

fallback behaviour as PuTTY's support.

[originally from svn r7009]
This commit is contained in:
Simon Tatham
2006-12-24 15:56:47 +00:00
parent d1cfcffa05
commit 7b1f7d3e01
29 changed files with 192 additions and 68 deletions

View 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,

View File

@ -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,

2
cube.c
View File

@ -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,

View 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,

View File

@ -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,

2
flip.c
View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

2
map.c
View File

@ -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,

View File

@ -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,

2
net.c
View File

@ -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,

View 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,

View 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,

View File

@ -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,

2
pegs.c
View File

@ -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,

View File

@ -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);

2
rect.c
View File

@ -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,

View 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,

View File

@ -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,

View File

@ -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,

2
solo.c
View File

@ -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,

View File

@ -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,

View File

@ -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,

View 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,

View 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,

View 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,

204
windows.c
View File

@ -4,6 +4,7 @@
#include <windows.h>
#include <commctrl.h>
#include <htmlhelp.h>
#include <stdio.h>
#include <assert.h>
@ -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;
}