1 Author: Ben Hutchings <ben@decadent.org.uk>
2 Description: Add HTML-based online help
4 This works along the same lines as the Windows implementation,
5 though we have to try a bit harder to find a help browser.
10 * gtk.c: GTK front end for my puzzle collection.
13 +#ifndef _POSIX_C_SOURCE
14 +#define _POSIX_C_SOURCE 1 /* for PATH_MAX */
29 #include <sys/resource.h>
30 @@ -2273,6 +2280,89 @@ static void menu_config_event(GtkMenuIte
31 midend_redraw(fe->me);
34 +#ifndef HELP_BROWSER_PATH
35 +#define HELP_BROWSER_PATH "xdg-open:sensible-browser"
38 +static void show_help(frontend *fe, const char *topic)
40 + const char *list = HELP_BROWSER_PATH;
41 + char path[PATH_MAX + 1];
49 + * Search for help file, trying:
50 + * 1. Version for this locale, ignoring encoding (HTML browsers
51 + * must handle multiple encodings)
52 + * 2. Version for this locale, ignoring encoding and country
53 + * 3. English version
55 + lang[0].s = setlocale(LC_MESSAGES, NULL);
56 + lang[0].len = strcspn(lang[0].s, ".@");
57 + lang[1].s = lang[0].s;
58 + lang[1].len = strcspn(lang[1].s, "_");
59 + if (lang[1].len > lang[0].len)
60 + lang[1].len = lang[0].len;
63 + for (i = 0; i < lenof(lang); i++) {
64 + sprintf(path, "%s/sgt-puzzles/help/%.*s/%s.html",
65 + SHAREDIR, lang[i].len, lang[i].s, topic);
66 + if (access(path, R_OK) == 0)
69 + if (i == lenof(lang)) {
70 + error_box(fe->window, "Help file is not installed");
76 + char buf[PATH_MAX + 1];
77 + const char *command;
78 + const char *argv[3];
80 + len = strcspn(list, ":");
81 + if (len <= PATH_MAX) {
82 + memcpy(buf, list, len);
85 + command = getenv(buf + 1);
92 + if (g_spawn_async(NULL, (char **)argv, NULL,
93 + G_SPAWN_SEARCH_PATH,
94 + NULL, NULL, NULL, NULL))
104 + error_box(fe->window, "Failed to start a help browser");
107 +static void menu_help_contents_event(GtkMenuItem *menuitem, gpointer data)
109 + show_help((frontend *)data, "index");
112 +static void menu_help_specific_event(GtkMenuItem *menuitem, gpointer data)
114 + show_help((frontend *)data, thegame.htmlhelp_topic);
117 static void menu_about_event(GtkMenuItem *menuitem, gpointer data)
119 frontend *fe = (frontend *)data;
120 @@ -2593,6 +2683,25 @@ static frontend *new_window(char *arg, i
121 menu = gtk_menu_new();
122 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu);
124 + menuitem = gtk_menu_item_new_with_label("Contents");
125 + gtk_container_add(GTK_CONTAINER(menu), menuitem);
126 + g_signal_connect(G_OBJECT(menuitem), "activate",
127 + G_CALLBACK(menu_help_contents_event), fe);
128 + gtk_widget_show(menuitem);
130 + if (thegame.htmlhelp_topic) {
132 + assert(thegame.name);
133 + item = snewn(9+strlen(thegame.name), char); /*ick*/
134 + sprintf(item, "Help on %s", thegame.name);
135 + menuitem = gtk_menu_item_new_with_label(item);
137 + gtk_container_add(GTK_CONTAINER(menu), menuitem);
138 + g_signal_connect(G_OBJECT(menuitem), "activate",
139 + G_CALLBACK(menu_help_specific_event), fe);
140 + gtk_widget_show(menuitem);
143 menuitem = gtk_menu_item_new_with_label("About");
144 gtk_container_add(GTK_CONTAINER(menu), menuitem);
145 g_signal_connect(G_OBJECT(menuitem), "activate",
148 @@ -95,6 +95,7 @@ Puzzles.dmg: Puzzles
151 bin_PROGRAMS = $(GAMES)
152 +GTK_CFLAGS += -DSHAREDIR="\"$(datarootdir)\""