mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-20 23:51:29 -07:00
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:
@ -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,
|
||||
|
@ -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
2
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,
|
||||
|
@ -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,
|
||||
|
@ -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
2
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,
|
||||
|
2
guess.c
2
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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
2
loopy.c
2
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,
|
||||
|
2
map.c
2
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,
|
||||
|
2
mines.c
2
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,
|
||||
|
2
net.c
2
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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
2
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,
|
||||
|
@ -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
2
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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
2
slant.c
2
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,
|
||||
|
2
solo.c
2
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,
|
||||
|
2
tents.c
2
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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
204
windows.c
@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user