chiark / gitweb /
use gtk native mechanisms to look up text tags in help
[disorder] / disobedience / help.c
index 3510c28583e182138729e45493cf47a1db201e56..7fbde805090e0b1a2789675319f17572550ba2b1 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  * USA
  */
+/** @file disobedience/help.c
+ * @brief Help support
+ */
 
 #include "disobedience.h"
-#include "table.h"
 #include "html.h"
 #include "manual.h"
 
@@ -33,29 +35,35 @@ struct tag {
   /** @brief Called to set up the tag */
   void (*init)(GtkTextTag *tag);
   
-  /** @brief GTK+ tag object */
-  GtkTextTag *tag;
 };
 
+/** @brief Initialize the bold tag
+ *
+ * This doesn't seem to work on OS X though the italic and monospace tags are
+ * fine, and bold is OK on Linux, even connecting to the Apple X swerver.
+ */
 static void init_bold(GtkTextTag *tag) {
   g_object_set(G_OBJECT(tag), "weight", PANGO_WEIGHT_BOLD, (char *)0);
 }
 
+/** @brief Initialize the italic tag */
 static void init_italic(GtkTextTag *tag) {
   g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, (char *)0);
 }
 
+/** @brief Initialize the pre tag */
 static void init_pre(GtkTextTag *tag) {
   g_object_set(G_OBJECT(tag), "family", "monospace", (char *)0);
 }
+
 /** @brief Table of known tags
  *
  * Keep in alphabetical order
  */
-static  struct tag tags[] = {
-  { "b", init_bold, 0 },
-  { "i", init_italic, 0 },
-  { "pre", init_pre, 0 }
+static const struct tag tags[] = {
+  { "b", init_bold },
+  { "i", init_italic },
+  { "pre", init_pre }
 };
 
 /** @brief Number of known tags */
@@ -66,6 +74,9 @@ struct state {
   /** @brief The buffer to insert into */
   GtkTextBuffer *buffer;
 
+  /** @brief The buffer's tag table */
+  GtkTextTagTable *tagtable;
+
   /** @brief True if we are inside <body> */
   int body;
 
@@ -108,7 +119,7 @@ static void html_close(const char *tag,
                       void *u) {
   struct state *const s = u;
   GtkTextIter start[1], end[1];
-  int n;
+  GtkTextTag *texttag;
 
   if(!strcmp(tag, "body"))
     --s->body;
@@ -119,7 +130,8 @@ static void html_close(const char *tag,
   if(!s->body)
     return;
   /* see if this is a known tag */
-  if((n = TABLE_FIND(tags, struct tag, name, tag)) < 0)
+  texttag = gtk_text_tag_table_lookup(s->tagtable, tag);
+  if(!texttag)
     return;
   /* pop the mark at the start of the region */
   assert(s->marks->nvec > 0);
@@ -127,8 +139,8 @@ static void html_close(const char *tag,
                                   s->marks->vec[--s->marks->nvec]);
   gtk_text_buffer_get_iter_at_mark(s->buffer, end,
                                   gtk_text_buffer_get_insert(s->buffer));
-  /* apply a tag */
-  gtk_text_buffer_apply_tag(s->buffer, tags[n].tag, start, end);
+  /* apply the tag */
+  gtk_text_buffer_apply_tag(s->buffer, texttag, start, end);
   /* don't need the start mark any more */
   gtk_text_buffer_delete_mark(s->buffer, s->marks->vec[s->marks->nvec]);
 }
@@ -174,23 +186,22 @@ static void insert_html(GtkTextBuffer *buffer,
                        const char *html) {
   struct state s[1];
   size_t n;
-  GtkTextTagTable *tagtable;
 
   memset(s, 0, sizeof *s);
   s->buffer = buffer;
   markstack_init(s->marks);
   /* initialize tags */
-  if(!tags[0].tag)
-    for(n = 0; n < NTAGS; ++n)
-      tags[n].init(tags[n].tag = gtk_text_tag_new(0));
-  /* add tags to this buffer */
-  tagtable = gtk_text_buffer_get_tag_table(s->buffer);
-  for(n = 0; n < NTAGS; ++n)
-    gtk_text_tag_table_add(tagtable, tags[n].tag);
+  s->tagtable = gtk_text_buffer_get_tag_table(s->buffer);
+  for(n = 0; n < NTAGS; ++n) {
+    GtkTextTag *const tag = gtk_text_tag_new(tags[n].name);
+    tags[n].init(tag);
+    gtk_text_tag_table_add(s->tagtable, tag);
+  }
   /* convert the input */
   html_parse(&insert_html_callbacks, html, s);
 }
 
+/** @brief Create a GtkTextBuffer with @p html rendered into it */
 static GtkTextBuffer *html_buffer(const char *html) {
   GtkTextBuffer *buffer = gtk_text_buffer_new(NULL);
 
@@ -198,8 +209,10 @@ static GtkTextBuffer *html_buffer(const char *html) {
   return buffer;
 }
 
+/** @brief The manual page window */
 static GtkWidget *help_window;
 
+/** @brief Pop up the manual page in a window */
 void popup_help(void) {
   GtkWidget *view;
   
@@ -210,12 +223,10 @@ void popup_help(void) {
   help_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
   g_signal_connect(help_window, "destroy",
                   G_CALLBACK(gtk_widget_destroyed), &help_window);
-  gtk_window_set_title(GTK_WINDOW(help_window), "Disobedience Manual");
+  gtk_window_set_title(GTK_WINDOW(help_window), "Disobedience Manual Page");
   view = gtk_text_view_new_with_buffer(html_buffer(manual));
   gtk_text_view_set_editable(GTK_TEXT_VIEW(view), FALSE);
-  gtk_container_add(GTK_CONTAINER(help_window),
-                   scroll_widget(view,
-                                 "help"));
+  gtk_container_add(GTK_CONTAINER(help_window), scroll_widget(view));
   gtk_window_set_default_size(GTK_WINDOW(help_window), 512, 512);
   gtk_widget_show_all(help_window);
 }