devhelp r1141 - in trunk: . data po src



Author: rhult
Date: Sun Oct  5 10:26:29 2008
New Revision: 1141
URL: http://svn.gnome.org/viewvc/devhelp?rev=1141&view=rev

Log:
2008-10-05  Richard Hult  <richard imendio com>

	* src/Makefile.am:
	* src/dh-assistant.c:
	* src/dh-assistant.h: Add a small "assistant" window for
	displaying just one hit.

	* data/Makefile.am:
	* data/assistant.css:
	* data/assistant.js: Add necessary glue for the assistant.
	
	* src/dh-base.[ch]: Remove unused function to get the windows.
	Hook up assistant, quit when there are no assistants or regular
	windows left.

	* src/dh-main.c: Add assistant search.


Added:
   trunk/data/assistant.css
   trunk/data/assistant.js
   trunk/src/dh-assistant.c
   trunk/src/dh-assistant.h
Modified:
   trunk/ChangeLog
   trunk/data/Makefile.am
   trunk/po/ChangeLog
   trunk/po/POTFILES.in
   trunk/po/sv.po
   trunk/src/Makefile.am
   trunk/src/dh-base.c
   trunk/src/dh-base.h
   trunk/src/dh-main.c

Modified: trunk/data/Makefile.am
==============================================================================
--- trunk/data/Makefile.am	(original)
+++ trunk/data/Makefile.am	Sun Oct  5 10:26:29 2008
@@ -3,6 +3,11 @@
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libdevhelp-1.0.pc
 
+assistantdir = $(datadir)/devhelp/assistant
+assistant_DATA = 		\
+	assistant.js		\
+	assistant.css
+
 @INTLTOOL_DESKTOP_RULE@
 
 DESKTOP_IN_FILES = devhelp.desktop.in
@@ -21,7 +26,8 @@
 	$(DESKTOP_IN_FILES)	\
 	$(DESKTOP_FILES)        \
 	$(schemas_in_files)     \
-	$(schemas_DATA)
+	$(schemas_DATA)		\
+	$(assistant_DATA)
 
 install-data-local: $(schema_DATA)
 if GCONF_SCHEMAS_INSTALL

Added: trunk/data/assistant.css
==============================================================================
--- (empty file)
+++ trunk/data/assistant.css	Sun Oct  5 10:26:29 2008
@@ -0,0 +1,93 @@
+body {
+  margin: 0;
+  padding: 0;
+}
+
+body * {
+  font-size: 9pt;
+}
+
+.title {
+  font-size: 11pt;
+  margin: 6pt;
+
+  color: #a52a2a;
+}
+.subtitle {
+  font-size: 9pt;
+  margin: 6pt;
+
+  color: #a52a2a;
+}
+
+.content {
+  margin: 6pt;
+  line-height: 1.3em;
+}
+
+div.book {
+  display: none;
+  position: absolute;
+  right: 6pt;
+  top: 6pt;
+  color: #a52a2a;
+}
+
+div.warning {
+  color: #A52A2A;
+  margin: 0 !important;
+}
+div.warning h3 {
+  background: inherit;
+  padding: 0;
+  margin: 0;
+  font-size: inherit;
+}
+
+div.note {
+  margin: 0 !important;
+}
+div.note h3 {
+  padding: 0;
+  margin: 0;
+  font-size: inherit;
+}
+
+p {
+  margin-top: 0;
+  margin-left: 2pt;
+}
+
+div.variablelist {
+  padding: 6pt;
+  background: #dddddd;
+  -webkit-border-radius: 5px;
+}
+
+code {
+  font-family: "Bitstream Vera Sans Mono", Monaco, Courier, monospace;
+  font-size: 8pt;
+}
+
+pre.programlisting {
+  font-family: "Bitstream Vera Sans Mono", Monaco, Courier, monospace;
+  font-size: 8pt;
+  padding: 6pt;
+  background: #dddddd;
+  -webkit-border-radius: 5px;
+  overflow: hidden;
+}
+
+pre.programlisting a {
+  font-family: "Bitstream Vera Sans Mono", Monaco, Courier, monospace;
+  font-size: 8pt;
+}
+
+div.variablelist * {
+  vertical-align: top;
+  line-height: 1.3em;
+}
+
+hr {
+  display: none;
+}

Added: trunk/data/assistant.js
==============================================================================
--- (empty file)
+++ trunk/data/assistant.js	Sun Oct  5 10:26:29 2008
@@ -0,0 +1,203 @@
+function strStrip(str)
+{
+    var length;
+    var i;
+
+    length = str.length;
+    i = 0;
+    while (i < length && (str[i] == " " || str[i] == "\t"))
+        i++;
+    str = str.substr(i);
+
+    i = str.length - 1;
+    while (i >= 0 && (str[i] == " " || str[i] == "\t"))
+        i--;
+
+    return str.substr(0, i + 1);
+}
+
+function strCompactWhitespace(str)
+{
+    var length;
+    var i;
+    var ret;
+    var whitespace_count = 0;
+
+    ret = "";
+    length = str.length;
+    i = 0;
+    while (i < length) {
+        if (str[i] == " " || str[i] == "\t") {
+            whitespace_count++;
+        } else {
+            if (whitespace_count > 0) {
+                ret += " ";
+                whitespace_count = 0;
+            }
+            ret += str[i];
+        }
+
+        i++;
+    }
+
+    return ret;
+}
+
+function getIndexOfParen(str)
+{
+    var length = str.length;
+
+    for (var i = 0; i < length; i++) {
+        if (str[i] == "(")
+            return i;
+    }
+
+    return 0;
+}
+
+function getIndexOfLastWord(str)
+{
+    for (var i = str.length; i >= 0; i--) {
+        if (str[i] == " ")
+            return i + 1;
+    }
+
+    return -1;
+}
+
+function getIndexOfLastWordIgnoreAsterisk(str)
+{
+    for (var i = str.length; i >= 0; i--) {
+        if (str[i] == " " || str[i] == "*")
+            return i + 1;
+    }
+
+    return -1;
+}
+
+function buildPadding(length)
+{
+    var str = "";
+
+    while (length > 0) {
+        str += " ";
+        length--;
+    }
+
+    return str;
+}
+
+function reformatSignature()
+{
+    var elements = document.getElementsByClassName('programlisting');
+
+    listing = elements[0];
+
+    var input = listing.textContent;
+    var lines = input.split("\n");
+    var output;
+
+    var line;
+    var i = 0;
+    while (line = lines[i]) {
+        lines[i] = strCompactWhitespace(strStrip(line));
+        i++;
+    }
+
+    var indexOfParen = getIndexOfParen(lines[1]);
+
+    i = 1;
+    var lastWordIndices = Array(lines.length);
+    var maxIndexOfLastWord = 0;
+    var maxDiff = 0;
+    while (line = lines[i]) {
+        lastWordIndices[i] = getIndexOfLastWordIgnoreAsterisk(line);
+        tmp = getIndexOfLastWord(line);
+
+        if (i > 1) {
+            lastWordIndices[i] += indexOfParen + 1;
+            tmp += indexOfParen + 1;
+        }
+
+        if (tmp > maxIndexOfLastWord)
+            maxIndexOfLastWord = tmp;
+
+        if (lastWordIndices[i] - tmp > maxDiff)
+            maxDiff = lastWordIndices[i] - tmp;
+
+        i++;
+    }
+
+    maxIndexOfLastWord += maxDiff;
+
+    // Now get the formatted text.
+    var formattedLines = listing.innerHTML.split("\n");
+
+    i = 0;
+    while (line = formattedLines[i]) {
+        formattedLines[i] = strCompactWhitespace(strStrip(line));
+        i++;
+    }
+
+    var formattedLastWordIndices = Array(formattedLines.length);
+    i = 1;
+    while (line = formattedLines[i]) {
+        formattedLastWordIndices[i] = getIndexOfLastWord(line);
+
+        if (i > 1)
+            formattedLastWordIndices[i] += indexOfParen + 1;
+
+        i++;
+    }
+
+    i = 2;
+    padding = buildPadding(indexOfParen + 1);
+    while (line = formattedLines[i]) {
+        formattedLines[i] = padding + line;
+        i++;
+    }
+
+    i = 1;
+    while (line = formattedLines[i]) {
+        padding = buildPadding(maxIndexOfLastWord - lastWordIndices[i]);
+        formattedLines[i] = line.substr(0, formattedLastWordIndices[i]) +
+            padding + line.substr(formattedLastWordIndices[i]);
+
+        i++;
+    }
+
+    output = "";
+    i = 0;
+    while (line = formattedLines[i]) {
+        output = output + line + "\n";
+        i++;
+    }
+
+    listing.innerHTML = output;
+}
+
+function cleanupSignature()
+{
+    var elements = document.getElementsByClassName('programlisting');
+
+    listing = elements[0];
+
+    var input = listing.innerHTML;
+    var lines = input.split("\n");
+
+    var line;
+    var i = 0;
+    while (line = lines[i]) {
+        lines[i] = strCompactWhitespace(strStrip(line));
+        i++;
+    }
+
+    var output = "";
+    i = 0;
+    while (line = lines[i]) {
+        output = output + line + "\n";
+        i++;
+    }
+
+    listing.innerHTML = output;
+}

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Sun Oct  5 10:26:29 2008
@@ -5,6 +5,7 @@
 data/ui/devhelp.glade
 misc/gedit-plugin/devhelp.desktop.in
 misc/gedit-plugin/devhelp/devhelp.py
+src/dh-assistant.c
 src/dh-base.c
 src/dh-book-tree.c
 src/dh-keyword-model.c

Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am	(original)
+++ trunk/src/Makefile.am	Sun Oct  5 10:26:29 2008
@@ -8,7 +8,9 @@
 bin_PROGRAMS = devhelp
 
 devhelp_SOURCES =					\
-	dh-main.c
+	dh-main.c					\
+	dh-assistant.c					\
+	dh-assistant.h
 
 devhelp_CPPFLAGS =					\
 	$(AM_CPPFLAGS)

Added: trunk/src/dh-assistant.c
==============================================================================
--- (empty file)
+++ trunk/src/dh-assistant.c	Sun Oct  5 10:26:29 2008
@@ -0,0 +1,447 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include <string.h>
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+#include <webkit/webkit.h>
+#include "dh-window.h"
+#include "dh-link.h"
+#include "dh-assistant.h"
+
+typedef struct {
+        DhBase    *base;
+
+        GtkWidget *main_box;
+        GtkWidget *web_view;
+
+        gchar     *current_search;
+        DhLink    *current_link;
+} DhAssistantPriv;
+
+static void dh_assistant_class_init (DhAssistantClass *klass);
+static void dh_assistant_init       (DhAssistant      *assistant);
+
+G_DEFINE_TYPE (DhAssistant, dh_assistant, GTK_TYPE_WINDOW);
+
+#define GET_PRIVATE(instance) G_TYPE_INSTANCE_GET_PRIVATE \
+  (instance, DH_TYPE_ASSISTANT, DhAssistantPriv);
+
+static WebKitNavigationResponse
+assistant_navigation_requested_cb (WebKitWebView        *web_view,
+                                   WebKitWebFrame       *frame,
+                                   WebKitNetworkRequest *request,
+                                   DhAssistant          *assistant)
+{
+        DhAssistantPriv *priv;
+        const gchar     *uri;
+
+        priv = GET_PRIVATE (assistant);
+
+        uri = webkit_network_request_get_uri (request);
+
+        if (strcmp (uri, "about:blank") == 0) {
+                return WEBKIT_NAVIGATION_RESPONSE_ACCEPT;
+        }
+
+        if (g_str_has_prefix (uri, "file://")) {
+                GtkWidget *window;
+
+                window = dh_base_get_window (priv->base);
+                _dh_window_display_uri (DH_WINDOW (window), uri);
+        }
+
+        return WEBKIT_NAVIGATION_RESPONSE_IGNORE;
+}
+
+static gboolean
+assistant_key_press_event_cb (GtkWidget   *widget,
+                              GdkEventKey *event,
+                              DhAssistant *assistant)
+{
+        if (event->keyval == GDK_Escape) {
+                gtk_widget_destroy (GTK_WIDGET (assistant));
+                return TRUE;
+        }
+
+        return FALSE;
+}
+
+static gboolean
+assistant_button_press_event_cb (GtkWidget      *widget,
+                                 GdkEventButton *event,
+                                 gpointer        user_data)
+{
+        /* Block webkit's builtin context menu. */
+        if (event->button != 1) {
+                return TRUE;
+        }
+
+        return FALSE;
+}
+
+static void
+assistant_finalize (GObject *object)
+{
+        DhAssistantPriv *priv = GET_PRIVATE (object);
+
+        g_object_unref (priv->base);
+
+        g_free (priv->current_search);
+
+        if (priv->current_link) {
+                dh_link_unref (priv->current_link);
+        }
+
+        G_OBJECT_CLASS (dh_assistant_parent_class)->finalize (object);
+}
+
+static void
+dh_assistant_class_init (DhAssistantClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->finalize = assistant_finalize;
+
+        g_type_class_add_private (klass, sizeof (DhAssistantPriv));
+}
+
+static void
+dh_assistant_init (DhAssistant *assistant)
+{
+        DhAssistantPriv *priv = GET_PRIVATE (assistant);
+        GtkWidget       *scrolled_window;
+
+        priv->main_box = gtk_vbox_new (FALSE, 0);
+        gtk_widget_show (priv->main_box);
+        gtk_container_add (GTK_CONTAINER (assistant), priv->main_box);
+
+        gtk_window_set_icon_name (GTK_WINDOW (assistant), "devhelp");
+        gtk_window_set_default_size (GTK_WINDOW (assistant), 400, 400);
+
+        priv->web_view = webkit_web_view_new ();
+
+        g_signal_connect (priv->web_view, "navigation-requested",
+                          G_CALLBACK (assistant_navigation_requested_cb),
+                          assistant);
+        g_signal_connect (priv->web_view, "button-press-event",
+                          G_CALLBACK (assistant_button_press_event_cb),
+                          assistant);
+
+        g_signal_connect (priv->web_view, "key-press-event",
+                          G_CALLBACK (assistant_key_press_event_cb),
+                          assistant);
+
+        scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+                                        GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+        gtk_container_add (GTK_CONTAINER (scrolled_window), priv->web_view);
+
+        gtk_widget_show_all (scrolled_window);
+
+        webkit_web_view_open (WEBKIT_WEB_VIEW (priv->web_view),
+                              "about:blank");
+
+        gtk_box_pack_start (GTK_BOX (priv->main_box),
+                            scrolled_window, TRUE, TRUE, 0);
+}
+
+GtkWidget *
+dh_assistant_new (DhBase *base)
+{
+        DhAssistant     *assistant;
+        DhAssistantPriv *priv;
+
+        assistant = g_object_new (DH_TYPE_ASSISTANT, NULL);
+
+        priv = GET_PRIVATE (assistant);
+
+        priv->base = g_object_ref (base);
+
+        return GTK_WIDGET (assistant);
+}
+
+static const gchar *
+find_in_buffer (const gchar *buffer,
+                const gchar *key,
+                gsize        length,
+                gsize        key_length)
+{
+        gsize m = 0;
+        gsize i = 0;
+
+        while (i < length) {
+                if (key[m] == buffer[i]) {
+                        m++;
+                        if (m == key_length) {
+                                return buffer + i - m + 1;
+                        }
+                } else {
+                        m = 0;
+                }
+                i++;
+        }
+
+        return NULL;
+}
+
+static void
+assistant_set_link (DhAssistant *assistant,
+                    DhLink      *link)
+{
+        DhAssistantPriv *priv = GET_PRIVATE (assistant);
+        gchar           *uri;
+        const gchar     *anchor;
+        gchar           *filename;
+        GMappedFile     *file;
+        const gchar     *contents;
+        gsize            length;
+        gchar           *key;
+        gsize            key_length;
+        const gchar     *start;
+        const gchar     *end;
+
+        if (priv->current_link == link) {
+                return;
+        }
+
+        if (link) {
+                dh_link_ref (link);
+        }
+        if (priv->current_link) {
+                dh_link_unref (priv->current_link);
+        }
+        priv->current_link = link;
+
+        if (!link) {
+                webkit_web_view_open (WEBKIT_WEB_VIEW (priv->web_view),
+                                      "about:blank");
+                return;
+        }
+
+        uri = dh_link_get_uri (link);
+        anchor = strrchr (uri, '#');
+        if (anchor) {
+                filename = g_strndup (uri, anchor - uri);
+                anchor++;
+                g_free (uri);
+        } else {
+                g_free (uri);
+                return;
+        }
+
+        file = g_mapped_file_new (filename, FALSE, NULL);
+        if (!file) {
+                g_free (filename);
+                return;
+        }
+
+        contents = g_mapped_file_get_contents (file);
+        length = g_mapped_file_get_length (file);
+
+        key = g_strdup_printf ("<a name=\"%s\"", anchor);
+        key_length = strlen (key);
+
+        start = find_in_buffer (contents, key, length, key_length);
+        g_free (key);
+
+        end = NULL;
+
+        if (start) {
+                const gchar *start_key;
+                const gchar *end_key;
+
+                length -= start - contents;
+
+                start_key = "<pre class=\"programlisting\">";
+
+                start = find_in_buffer (start,
+                                        start_key,
+                                        length,
+                                        strlen (start_key));
+
+                end_key = "<div class=\"refsect";
+
+                if (start) {
+                        end = find_in_buffer (start, end_key,
+                                              length - strlen (start_key),
+                                              strlen (end_key));
+                }
+        }
+
+        if (start && end) {
+                gchar       *buf;
+                gchar       *name;
+                const gchar *function;
+                gchar       *html;
+                gchar       *tmp;
+                gchar       *base;
+
+                buf = g_strndup (start, end-start);
+
+                /* Try to reformat function signatures so they take less
+                 * space and look nicer. Don't reformat things that don't
+                 * look like functions.
+                 */
+                switch (dh_link_get_link_type (link)) {
+                case DH_LINK_TYPE_FUNCTION:
+                        name = strstr (buf, dh_link_get_name (link));
+                        if (name && name > buf) {
+                                name[-1] = '\n';
+                        }
+                        function = "onload=\"reformatSignature()\"";
+                        break;
+                case DH_LINK_TYPE_MACRO:
+                        function = "onload=\"cleanupSignature()\"";
+                        break;
+                default:
+                        function = "";
+                        break;
+                }
+
+                html = g_strdup_printf (
+                        "<html>"
+                        "<head>"
+                        "<link rel=\"stylesheet\" type=\"text/css\" href=\"file://%s\">"
+                        "<script src=\"file://%s\"</script>"
+                        "</head>"
+                        "<body %s>"
+                        "<div class=\"title\">%s: %s</div><div class=\"subtitle\">%s %s</div>"
+                        "<div class=\"content\">%s</div>"
+                        "</body>"
+                        "</html>",
+                        DATADIR "/devhelp/assistant/assistant.css",
+                        DATADIR "/devhelp/assistant/assistant.js",
+                        function,
+                        dh_link_get_type_as_string (link),
+                        dh_link_get_name (link),
+                        _("Book:"),
+                        dh_link_get_book_name (link),
+                        buf);
+                g_free (buf);
+
+                /* We need to set a local base to be able to access
+                 * the stylesheet and javascript, but we also have to
+                 * set something that is not the same as the current
+                 * page, otherwise link clicks won't go through the
+                 * network request handler (which we need so we can
+                 * forward then to a main devhelp window. The reason
+                 * is that page-local anchor links are handled
+                 * internally in webkit.
+                 */
+                tmp = g_path_get_dirname (filename);
+                base = g_strconcat ("file://", tmp, "/fake", NULL);
+                g_free (tmp);
+
+                webkit_web_view_load_html_string (
+                        WEBKIT_WEB_VIEW (priv->web_view),
+                        html,
+                        base);
+
+                g_free (html);
+                g_free (base);
+        } else {
+                webkit_web_view_open (WEBKIT_WEB_VIEW (priv->web_view),
+                                      "about:blank");
+        }
+
+        g_mapped_file_free (file);
+        g_free (filename);
+}
+
+gboolean
+dh_assistant_search (DhAssistant *assistant,
+                     const gchar *str)
+{
+        DhAssistantPriv *priv;
+        GList           *keywords, *l;
+        const gchar     *name;
+        DhLink          *link;
+        DhLink          *exact_link;
+        DhLink          *prefix_link;
+
+        g_return_val_if_fail (DH_IS_ASSISTANT (assistant), FALSE);
+        g_return_val_if_fail (str != NULL, FALSE);
+
+        priv = GET_PRIVATE (assistant);
+
+        /* Filter out very short strings. */
+        if (strlen (str) < 4) {
+                return FALSE;
+        }
+
+        if (priv->current_search && strcmp (priv->current_search, str) == 0) {
+                return FALSE;
+        }
+        g_free (priv->current_search);
+        priv->current_search = g_strdup (str);
+
+        keywords = dh_base_get_keywords (priv->base);
+
+        prefix_link = NULL;
+        exact_link = NULL;
+        for (l = keywords; l && exact_link == NULL; l = l->next) {
+                DhLinkType type;
+
+                link = l->data;
+
+                type = dh_link_get_link_type (link);
+
+                if (type == DH_LINK_TYPE_BOOK ||
+                    type == DH_LINK_TYPE_PAGE ||
+                    type == DH_LINK_TYPE_KEYWORD) {
+                        continue;
+                }
+
+                name = dh_link_get_name (link);
+                if (strcmp (name, str) == 0) {
+                        exact_link = link;
+                }
+                else if (g_str_has_prefix (name, str)) {
+                        /* Prefer shorter prefix matches. */
+                        if (!prefix_link) {
+                                prefix_link = link;
+                        }
+                        else if (strlen (dh_link_get_name (prefix_link)) > strlen (name)) {
+                                prefix_link = link;
+                        }
+                }
+        }
+
+        if (exact_link) {
+                /*g_print ("exact hit: '%s' '%s'\n", exact_link->name, str);*/
+                assistant_set_link (assistant, exact_link);
+        }
+        else if (prefix_link) {
+                /*g_print ("prefix hit: '%s' '%s'\n", prefix_link->name, str);*/
+                assistant_set_link (assistant, prefix_link);
+        } else {
+                /*g_print ("no hit\n");*/
+                /*assistant_set_link (assistant, NULL);*/
+                return FALSE;
+        }
+
+        gtk_widget_show (GTK_WIDGET (assistant));
+
+        return TRUE;
+}

Added: trunk/src/dh-assistant.h
==============================================================================
--- (empty file)
+++ trunk/src/dh-assistant.h	Sun Oct  5 10:26:29 2008
@@ -0,0 +1,50 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __DH_ASSISTANT_H__
+#define __DH_ASSISTANT_H__
+
+#include <gtk/gtk.h>
+#include "dh-base.h"
+
+#define DH_TYPE_ASSISTANT         (dh_assistant_get_type ())
+#define DH_ASSISTANT(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), DH_TYPE_ASSISTANT, DhAssistant))
+#define DH_ASSISTANT_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), DH_TYPE_ASSISTANT, DhAssistantClass))
+#define DH_IS_ASSISTANT(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), DH_TYPE_ASSISTANT))
+#define DH_IS_ASSISTANT_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), DH_TYPE_ASSISTANT))
+#define DH_ASSISTANT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DH_TYPE_ASSISTANT, DhAssistantClass))
+
+typedef struct _DhAssistant      DhAssistant;
+typedef struct _DhAssistantClass DhAssistantClass;
+
+struct _DhAssistant {
+        GtkWindow parent_instance;
+};
+
+struct _DhAssistantClass {
+        GtkWindowClass parent_class;
+};
+
+GType      dh_assistant_get_type  (void) G_GNUC_CONST;
+GtkWidget *dh_assistant_new       (DhBase      *base);
+gboolean   dh_assistant_search    (DhAssistant *assistant,
+                                   const gchar *str);
+
+#endif /* __DH_ASSISTANT_H__ */

Modified: trunk/src/dh-base.c
==============================================================================
--- trunk/src/dh-base.c	(original)
+++ trunk/src/dh-base.c	Sun Oct  5 10:26:29 2008
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2002 CodeFactory AB
  * Copyright (C) 2002 Mikael Hallendal <micke imendio com>
- * Copyright (C) 2004-2006 Imendio AB
+ * Copyright (C) 2004-2008 Imendio AB
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -36,10 +36,12 @@
 #include "dh-link.h"
 #include "dh-parser.h"
 #include "dh-preferences.h"
+#include "dh-assistant.h"
 #include "dh-base.h"
 
 typedef struct {
         GSList      *windows;
+        GSList      *assistants;
         GNode       *book_tree;
         GList       *keywords;
         GHashTable  *books;
@@ -47,7 +49,7 @@
 
 G_DEFINE_TYPE (DhBase, dh_base, G_TYPE_OBJECT);
 
-#define GET_PRIVATE(instance) G_TYPE_INSTANCE_GET_PRIVATE  \
+#define GET_PRIVATE(instance) G_TYPE_INSTANCE_GET_PRIVATE \
   (instance, DH_TYPE_BASE, DhBasePriv);
 
 static void dh_base_init           (DhBase      *base);
@@ -90,9 +92,7 @@
 {
         DhBasePriv *priv = GET_PRIVATE (base);
 
-        priv->windows = NULL;
         priv->book_tree = g_node_new (NULL);
-        priv->keywords = NULL;
         priv->books = g_hash_table_new_full (g_str_hash, g_str_equal,
                                              g_free, g_free);
 
@@ -114,14 +114,15 @@
 }
 
 static void
-base_window_finalized_cb (DhBase   *base,
-                          DhWindow *window)
+base_window_or_assistant_finalized_cb (DhBase   *base,
+                                       gpointer  window_or_assistant)
 {
         DhBasePriv *priv = GET_PRIVATE (base);
 
-        priv->windows = g_slist_remove (priv->windows, window);
+        priv->windows = g_slist_remove (priv->windows, window_or_assistant);
+        priv->assistants = g_slist_remove (priv->assistants, window_or_assistant);
 
-        if (g_slist_length (priv->windows) == 0) {
+        if (priv->windows == NULL && priv->assistants == NULL) {
                 gtk_main_quit ();
         }
 }
@@ -453,26 +454,35 @@
         priv->windows = g_slist_prepend (priv->windows, window);
 
         g_object_weak_ref (G_OBJECT (window),
-                           (GWeakNotify) base_window_finalized_cb,
+                           (GWeakNotify) base_window_or_assistant_finalized_cb,
                            base);
 
         return window;
 }
 
-GNode *
-dh_base_get_book_tree (DhBase *base)
+GtkWidget *
+dh_base_new_assistant (DhBase *base)
 {
         DhBasePriv *priv;
+        GtkWidget  *assistant;
 
         g_return_val_if_fail (DH_IS_BASE (base), NULL);
 
         priv = GET_PRIVATE (base);
 
-        return priv->book_tree;
+        assistant = dh_assistant_new (base);
+
+        priv->assistants = g_slist_prepend (priv->assistants, assistant);
+
+        g_object_weak_ref (G_OBJECT (assistant),
+                           (GWeakNotify) base_window_or_assistant_finalized_cb,
+                           base);
+
+        return assistant;
 }
 
-GList *
-dh_base_get_keywords (DhBase *base)
+GNode *
+dh_base_get_book_tree (DhBase *base)
 {
         DhBasePriv *priv;
 
@@ -480,11 +490,11 @@
 
         priv = GET_PRIVATE (base);
 
-        return priv->keywords;
+        return priv->book_tree;
 }
 
-GSList *
-dh_base_get_windows (DhBase *base)
+GList *
+dh_base_get_keywords (DhBase *base)
 {
         DhBasePriv *priv;
 
@@ -492,7 +502,7 @@
 
         priv = GET_PRIVATE (base);
 
-        return priv->windows;
+        return priv->keywords;
 }
 
 GtkWidget *

Modified: trunk/src/dh-base.h
==============================================================================
--- trunk/src/dh-base.h	(original)
+++ trunk/src/dh-base.h	Sun Oct  5 10:26:29 2008
@@ -47,10 +47,10 @@
 DhBase *     dh_base_get                             (void);
 DhBase *     dh_base_new                             (void);
 GtkWidget *  dh_base_new_window                      (DhBase *base);
+GtkWidget *  dh_base_new_assistant                   (DhBase *base);
 GtkWidget *  dh_base_get_window                      (DhBase *base);
 GtkWidget *  dh_base_get_window_on_current_workspace (DhBase *base);
 GNode *      dh_base_get_book_tree                   (DhBase *base);
 GList *      dh_base_get_keywords                    (DhBase *base);
-GSList *     dh_base_get_windows                     (DhBase *base);
 
 #endif /* __DH_BASE_H__ */

Modified: trunk/src/dh-main.c
==============================================================================
--- trunk/src/dh-main.c	(original)
+++ trunk/src/dh-main.c	Sun Oct  5 10:26:29 2008
@@ -1,7 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
 /*
  * Copyright (C) 2001-2003 CodeFactory AB
- * Copyright (C) 2001-2005 Imendio AB
+ * Copyright (C) 2001-2008 Imendio AB
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -24,13 +24,14 @@
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 
-#ifdef HAVE_PLATFORM_X11
+#ifdef GDK_WINDOWING_X11
 #include <gdk/gdkx.h>
 #endif
 
 #include "bacon-message-connection.h"
 #include "dh-base.h"
 #include "dh-window.h"
+#include "dh-assistant.h"
 
 #define COMMAND_QUIT             "quit"
 #define COMMAND_SEARCH           "search"
@@ -93,7 +94,20 @@
 search_assistant (DhBase      *base,
                   const gchar *str)
 {
-        return FALSE;
+        static GtkWidget *assistant;
+
+        if (str[0] == '\0') {
+                return FALSE;
+        }
+
+        if (!assistant) {
+                assistant = dh_base_new_assistant (base);
+                g_signal_connect (assistant, "destroy",
+                                  G_CALLBACK (gtk_widget_destroyed),
+                                  &assistant);
+        }
+
+        return dh_assistant_search (DH_ASSISTANT (assistant), str);
 }
 
 static void
@@ -124,7 +138,7 @@
 		dh_window_focus_search (DH_WINDOW (window));
 	}
 
-#ifdef HAVE_PLATFORM_X11
+#ifdef GDK_WINDOWING_X11
 	timestamp = gdk_x11_get_server_time (window->window);
 #else
 	timestamp = GDK_CURRENT_TIME;
@@ -181,7 +195,7 @@
 			0,
 			G_OPTION_ARG_NONE,
 			&option_focus_search,
-			_("Focus the devhelp window with the search field active"),
+			_("Focus the Devhelp window with the search field active"),
 			NULL
 		},
        		{
@@ -214,7 +228,7 @@
 		return 0;
 	}
 
-	g_set_application_name (_("Devhelp"));
+	g_set_application_name ("Devhelp");
 	gtk_window_set_default_icon_name ("devhelp");
 
 	display = gdk_get_display ();



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]