chiark / gitweb /
_online-help
authorBen Hutchings <ben@decadent.org.uk>
Tue, 17 Jan 2017 23:57:33 +0000 (23:57 +0000)
committerBen Hutchings <ben@decadent.org.uk>
Tue, 17 Jan 2017 23:57:33 +0000 (23:57 +0000)
This works along the same lines as the Windows implementation,
though we have to try a bit harder to find a help browser.

Gbp-Pq: Name 202_online-help.diff

Recipe
gtk.c

diff --git a/Recipe b/Recipe
index ba8317f51a090c4ced54d305cdae2e1e212df4f0..cda48147685b91b1b9ffb1a295956db1598499f9 100644 (file)
--- a/Recipe
+++ b/Recipe
@@ -95,6 +95,7 @@ Puzzles.dmg: Puzzles
 
 !begin am
 bin_PROGRAMS = $(GAMES)
+GTK_CFLAGS += -DSHAREDIR="\"$(datarootdir)\""
 !end
 !begin am_begin
 GAMES =
diff --git a/gtk.c b/gtk.c
index 53f5d2201b12577a8b65c5d4a0c2f8dbea5b3d29..5bd1025f541c85a0004454c435914d4b7b0202ac 100644 (file)
--- a/gtk.c
+++ b/gtk.c
@@ -2,6 +2,10 @@
  * 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>
@@ -10,6 +14,9 @@
 #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>
@@ -2273,6 +2280,89 @@ static void menu_config_event(GtkMenuItem *menuitem, gpointer data)
     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;
@@ -2593,6 +2683,25 @@ static frontend *new_window(char *arg, int argtype, char **error)
     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",