* gtk.c: GTK front end for my puzzle collection.
*/
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 1 /* for PATH_MAX */
+#endif
+
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <math.h>
+#include <limits.h>
+#include <unistd.h>
+#include <locale.h>
#include <sys/time.h>
#include <sys/resource.h>
midend_redraw(fe->me);
}
+#ifndef HELP_BROWSER_PATH
+#define HELP_BROWSER_PATH "xdg-open:sensible-browser"
+#endif
+
+static void show_help(frontend *fe, const char *topic)
+{
+ const char *list = HELP_BROWSER_PATH;
+ char path[PATH_MAX + 1];
+ struct {
+ const char *s;
+ int len;
+ } lang[3];
+ int i;
+
+ /*
+ * Search for help file, trying:
+ * 1. Version for this locale, ignoring encoding (HTML browsers
+ * must handle multiple encodings)
+ * 2. Version for this locale, ignoring encoding and country
+ * 3. English version
+ */
+ lang[0].s = setlocale(LC_MESSAGES, NULL);
+ lang[0].len = strcspn(lang[0].s, ".@");
+ lang[1].s = lang[0].s;
+ lang[1].len = strcspn(lang[1].s, "_");
+ if (lang[1].len > lang[0].len)
+ lang[1].len = lang[0].len;
+ lang[2].s = "en";
+ lang[2].len = 2;
+ for (i = 0; i < lenof(lang); i++) {
+ sprintf(path, "%s/sgt-puzzles/help/%.*s/%s.html",
+ SHAREDIR, lang[i].len, lang[i].s, topic);
+ if (access(path, R_OK) == 0)
+ break;
+ }
+ if (i == lenof(lang)) {
+ error_box(fe->window, "Help file is not installed");
+ return;
+ }
+
+ for (;;) {
+ size_t len;
+ char buf[PATH_MAX + 1];
+ const char *command;
+ const char *argv[3];
+
+ len = strcspn(list, ":");
+ if (len <= PATH_MAX) {
+ memcpy(buf, list, len);
+ buf[len] = 0;
+ if (buf[0] == '$')
+ command = getenv(buf + 1);
+ else
+ command = buf;
+ if (command) {
+ argv[0] = command;
+ argv[1] = path;
+ argv[2] = NULL;
+ if (g_spawn_async(NULL, (char **)argv, NULL,
+ G_SPAWN_SEARCH_PATH,
+ NULL, NULL, NULL, NULL))
+ return;
+ }
+ }
+
+ if (!list[len])
+ break;
+ list += len + 1;
+ }
+
+ error_box(fe->window, "Failed to start a help browser");
+}
+
+static void menu_help_contents_event(GtkMenuItem *menuitem, gpointer data)
+{
+ show_help((frontend *)data, "index");
+}
+
+static void menu_help_specific_event(GtkMenuItem *menuitem, gpointer data)
+{
+ show_help((frontend *)data, thegame.htmlhelp_topic);
+}
+
static void menu_about_event(GtkMenuItem *menuitem, gpointer data)
{
frontend *fe = (frontend *)data;
menu = gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu);
+ menuitem = gtk_menu_item_new_with_label("Contents");
+ gtk_container_add(GTK_CONTAINER(menu), menuitem);
+ g_signal_connect(G_OBJECT(menuitem), "activate",
+ G_CALLBACK(menu_help_contents_event), fe);
+ gtk_widget_show(menuitem);
+
+ if (thegame.htmlhelp_topic) {
+ char *item;
+ assert(thegame.name);
+ item = snewn(9+strlen(thegame.name), char); /*ick*/
+ sprintf(item, "Help on %s", thegame.name);
+ menuitem = gtk_menu_item_new_with_label(item);
+ sfree(item);
+ gtk_container_add(GTK_CONTAINER(menu), menuitem);
+ g_signal_connect(G_OBJECT(menuitem), "activate",
+ G_CALLBACK(menu_help_specific_event), fe);
+ gtk_widget_show(menuitem);
+ }
+
menuitem = gtk_menu_item_new_with_label("About");
gtk_container_add(GTK_CONTAINER(menu), menuitem);
g_signal_connect(G_OBJECT(menuitem), "activate",