buf) {
+ name[-1] = '\n';
+ }
+ }
+
+ stylesheet = dh_util_build_data_filename ("devhelp",
+ "assistant",
+ "assistant.css",
+ NULL);
+ javascript = dh_util_build_data_filename ("devhelp",
+ "assistant",
+ "assistant.js",
+ NULL);
+
+ html = g_strdup_printf (
+ ""
+ ""
+ "
"
+ ""
+ ""
+ ""
+ "
"
+ "
%s %s
"
+ "
%s
"
+ ""
+ "",
+ stylesheet,
+ javascript,
+ function,
+ dh_link_get_type_as_string (link),
+ dh_link_get_uri (link),
+ dh_link_get_name (link),
+ _("Book:"),
+ dh_link_get_book_name (link),
+ buf);
+ g_free (buf);
+
+ g_free (stylesheet);
+ g_free (javascript);
+
+ priv->snippet_loaded = FALSE;
+ webkit_web_view_load_string (
+ WEBKIT_WEB_VIEW (view),
+ html,
+ "text/html",
+ NULL,
+ filename);
+
+ g_free (html);
+ } else {
+ webkit_web_view_load_uri (WEBKIT_WEB_VIEW (view), "about:blank");
+ }
+
+#if GLIB_CHECK_VERSION(2,21,3)
+ g_mapped_file_unref (file);
+#else
+ g_mapped_file_free (file);
+#endif
+
+ g_free (filename);
+
+ return TRUE;
+}
+
+gboolean
+dh_assistant_view_search (DhAssistantView *view,
+ const gchar *str)
+{
+ DhAssistantViewPriv *priv;
+ const gchar *name;
+ DhLink *link;
+ DhLink *exact_link;
+ DhLink *prefix_link;
+ DhBookManager *book_manager;
+ GList *books;
+
+ g_return_val_if_fail (DH_IS_ASSISTANT_VIEW (view), FALSE);
+ g_return_val_if_fail (str, FALSE);
+
+ priv = GET_PRIVATE (view);
+
+ /* 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);
+
+ book_manager = dh_base_get_book_manager (dh_assistant_view_get_base (view));
+
+ prefix_link = NULL;
+ exact_link = NULL;
+
+ for (books = dh_book_manager_get_books (book_manager);
+ !exact_link && books;
+ books = g_list_next (books)) {
+ GList *l;
+
+ for (l = dh_book_get_keywords (DH_BOOK (books->data));
+ 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);*/
+ dh_assistant_view_set_link (view, exact_link);
+ }
+ else if (prefix_link) {
+ /*g_print ("prefix hit: '%s' '%s'\n", prefix_link->name, str);*/
+ dh_assistant_view_set_link (view, prefix_link);
+ } else {
+ /*g_print ("no hit\n");*/
+ /*assistant_view_set_link (view, NULL);*/
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+dh_assistant_view_set_base (DhAssistantView *view,
+ DhBase *base)
+{
+ DhAssistantViewPriv *priv;
+
+ g_return_if_fail (DH_IS_ASSISTANT_VIEW (view));
+ g_return_if_fail (DH_IS_BASE (base));
+
+ priv = GET_PRIVATE (view);
+
+ priv->base = g_object_ref (base);
+}
Modified: devhelp/devhelp/dh-assistant-view.h
59 files changed, 59 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Sven Herzberg
+ *
+ * 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_VIEW_H__
+#define __DH_ASSISTANT_VIEW_H__
+
+#include
+#include "dh-base.h"
+#include "dh-link.h"
+
+G_BEGIN_DECLS
+
+#define DH_TYPE_ASSISTANT_VIEW (dh_assistant_view_get_type ())
+#define DH_ASSISTANT_VIEW(i) (G_TYPE_CHECK_INSTANCE_CAST ((i), DH_TYPE_ASSISTANT_VIEW, DhAssistantView))
+#define DH_ASSISTANT_VIEW_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), DH_TYPE_ASSISTANT_VIEW, DhAssistantViewClass))
+#define DH_IS_ASSISTANT_VIEW(i) (G_TYPE_CHECK_INSTANCE_TYPE ((i), DH_TYPE_ASSISTANT_VIEW))
+#define DH_IS_ASSISTANT_VIEW_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), DH_ASSISTANT_VIEW))
+#define DH_ASSISTANT_VIEW_GET_CLASS(i) (G_TYPE_INSTANCE_GET_CLASS ((i), DH_TYPE_ASSISTANT_VIEW, DhAssistantView))
+
+typedef struct _DhAssistantView DhAssistantView;
+typedef struct _DhAssistantViewClass DhAssistantViewClass;
+
+struct _DhAssistantView {
+ WebKitWebView parent_instance;
+};
+
+struct _DhAssistantViewClass {
+ WebKitWebViewClass parent_class;
+};
+
+GType dh_assistant_view_get_type (void) G_GNUC_CONST;
+GtkWidget* dh_assistant_view_new (void);
+gboolean dh_assistant_view_search (DhAssistantView *view,
+ const gchar *str);
+DhBase* dh_assistant_view_get_base (DhAssistantView *view);
+void dh_assistant_view_set_base (DhAssistantView *view,
+ DhBase *base);
+gboolean dh_assistant_view_set_link (DhAssistantView *view,
+ DhLink *link);
+G_END_DECLS
+
+#endif /* __DH_ASSISTANT_VIEW_H__ */
Modified: devhelp/devhelp/dh-assistant.c
130 files changed, 130 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,130 @@
+/* -*- 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
+#include
+#include
+#include
+#include "dh-window.h"
+#include "dh-util.h"
+#include "dh-assistant-view.h"
+#include "dh-assistant.h"
+
+typedef struct {
+ GtkWidget *main_box;
+ GtkWidget *view;
+} 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 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 void
+dh_assistant_class_init (DhAssistantClass *klass)
+{
+ 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);
+
+ /* i18n: Please don't translate "Devhelp". */
+ gtk_window_set_title (GTK_WINDOW (assistant), _("Devhelp ? Assistant"));
+ gtk_window_set_icon_name (GTK_WINDOW (assistant), "devhelp");
+
+ priv->view = dh_assistant_view_new ();
+
+ g_signal_connect (assistant, "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_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+ gtk_container_add (GTK_CONTAINER (scrolled_window), priv->view);
+
+ gtk_widget_show_all (scrolled_window);
+
+ gtk_box_pack_start (GTK_BOX (priv->main_box),
+ scrolled_window, TRUE, TRUE, 0);
+
+ dh_util_state_manage_window (GTK_WINDOW (assistant),
+ "assistant/window");
+}
+
+GtkWidget *
+dh_assistant_new (DhBase *base)
+{
+ GtkWidget *assistant;
+ DhAssistantPriv *priv;
+
+ assistant = g_object_new (DH_TYPE_ASSISTANT, NULL);
+
+ priv = GET_PRIVATE (assistant);
+
+ dh_assistant_view_set_base (DH_ASSISTANT_VIEW (priv->view), base);
+
+ return assistant;
+}
+
+gboolean
+dh_assistant_search (DhAssistant *assistant,
+ const gchar *str)
+{
+ DhAssistantPriv *priv;
+
+ g_return_val_if_fail (DH_IS_ASSISTANT (assistant), FALSE);
+ g_return_val_if_fail (str != NULL, FALSE);
+
+ priv = GET_PRIVATE (assistant);
+
+ if (dh_assistant_view_search (DH_ASSISTANT_VIEW (priv->view), str)) {
+ gtk_widget_show (GTK_WIDGET (assistant));
+ return TRUE;
+ }
+
+ return FALSE;
+}
Modified: devhelp/devhelp/dh-assistant.h
54 files changed, 54 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,54 @@
+/* -*- 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
+#include "dh-base.h"
+
+G_BEGIN_DECLS
+
+#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);
+
+G_END_DECLS
+
+#endif /* __DH_ASSISTANT_H__ */
Modified: devhelp/devhelp/dh-base.c
307 files changed, 307 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,307 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2002 CodeFactory AB
+ * Copyright (C) 2002 Mikael Hallendal
+ * 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
+ * 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
+#include
+
+#ifdef GDK_WINDOWING_X11
+#include
+#include
+#define WNCK_I_KNOW_THIS_IS_UNSTABLE
+#include
+#endif
+
+#include "dh-window.h"
+#include "dh-link.h"
+#include "dh-parser.h"
+#include "dh-preferences.h"
+#include "dh-assistant.h"
+#include "dh-util.h"
+#include "ige-conf.h"
+#include "dh-base.h"
+#include "dh-book-manager.h"
+
+typedef struct {
+ GSList *windows;
+ GSList *assistants;
+ DhBookManager *book_manager;
+} DhBasePriv;
+
+G_DEFINE_TYPE (DhBase, dh_base, G_TYPE_OBJECT);
+
+#define GET_PRIVATE(instance) G_TYPE_INSTANCE_GET_PRIVATE \
+ (instance, DH_TYPE_BASE, DhBasePriv)
+
+static void dh_base_init (DhBase *base);
+static void dh_base_class_init (DhBaseClass *klass);
+
+static DhBase *base_instance;
+
+static void
+base_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (dh_base_parent_class)->finalize (object);
+}
+
+static void
+base_dispose (GObject *object)
+{
+ DhBasePriv *priv;
+
+ priv = GET_PRIVATE (object);
+
+ if (priv->book_manager) {
+ g_object_unref (priv->book_manager);
+ priv->book_manager = NULL;
+ }
+}
+
+
+static void
+dh_base_class_init (DhBaseClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = base_finalize;
+ object_class->dispose = base_dispose;
+
+ g_type_class_add_private (klass, sizeof (DhBasePriv));
+}
+
+static void
+dh_base_init (DhBase *base)
+{
+ DhBasePriv *priv = GET_PRIVATE (base);
+ IgeConf *conf;
+ gchar *path;
+
+ conf = ige_conf_get ();
+ path = dh_util_build_data_filename ("devhelp", "devhelp.defaults", NULL);
+ ige_conf_add_defaults (conf, path);
+ g_free (path);
+
+ priv->book_manager = dh_book_manager_new ();
+ dh_book_manager_populate (priv->book_manager);
+
+#ifdef GDK_WINDOWING_X11
+ {
+ gint n_screens, i;
+
+ /* For some reason, libwnck doesn't seem to update its list of
+ * workspaces etc if we don't do this.
+ */
+ n_screens = gdk_display_get_n_screens (gdk_display_get_default ());
+ for (i = 0; i < n_screens; i++)
+ wnck_screen_get (i);
+ }
+#endif
+}
+
+static void
+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_or_assistant);
+ priv->assistants = g_slist_remove (priv->assistants, window_or_assistant);
+
+ if (priv->windows == NULL && priv->assistants == NULL) {
+ gtk_main_quit ();
+ }
+}
+
+DhBase *
+dh_base_get (void)
+{
+ if (!base_instance) {
+ base_instance = g_object_new (DH_TYPE_BASE, NULL);
+ }
+
+ return base_instance;
+}
+
+DhBase *
+dh_base_new (void)
+{
+ if (base_instance) {
+ g_error ("You can only have one DhBase instance.");
+ }
+
+ return dh_base_get ();
+}
+
+GtkWidget *
+dh_base_new_window (DhBase *base)
+{
+ DhBasePriv *priv;
+ GtkWidget *window;
+
+ g_return_val_if_fail (DH_IS_BASE (base), NULL);
+
+ priv = GET_PRIVATE (base);
+
+ window = dh_window_new (base);
+
+ priv->windows = g_slist_prepend (priv->windows, window);
+
+ g_object_weak_ref (G_OBJECT (window),
+ (GWeakNotify) base_window_or_assistant_finalized_cb,
+ base);
+
+ return window;
+}
+
+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);
+
+ 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;
+}
+
+DhBookManager *
+dh_base_get_book_manager (DhBase *base)
+{
+ DhBasePriv *priv;
+
+ g_return_val_if_fail (DH_IS_BASE (base), NULL);
+
+ priv = GET_PRIVATE (base);
+
+ return priv->book_manager;
+}
+
+GtkWidget *
+dh_base_get_window_on_current_workspace (DhBase *base)
+{
+ DhBasePriv *priv;
+
+ g_return_val_if_fail (DH_IS_BASE (base), NULL);
+
+ priv = GET_PRIVATE (base);
+
+ if (!priv->windows) {
+ return NULL;
+ }
+
+#ifdef GDK_WINDOWING_X11
+ {
+ WnckWorkspace *workspace;
+ WnckScreen *screen;
+ GtkWidget *window;
+ GList *windows, *w;
+ GSList *l;
+ gulong xid;
+ pid_t pid;
+
+ screen = wnck_screen_get (0);
+ if (!screen) {
+ return NULL;
+ }
+
+ workspace = wnck_screen_get_active_workspace (screen);
+ if (!workspace) {
+ return NULL;
+ }
+
+ xid = 0;
+ pid = getpid ();
+
+ /* Use _stacked so we can use the one on top. */
+ windows = wnck_screen_get_windows_stacked (screen);
+ windows = g_list_last (windows);
+
+ for (w = windows; w; w = w->prev) {
+ if (wnck_window_is_on_workspace (w->data, workspace) &&
+ wnck_window_get_pid (w->data) == pid) {
+ xid = wnck_window_get_xid (w->data);
+ break;
+ }
+ }
+
+ if (!xid) {
+ return NULL;
+ }
+
+ /* Return the first matching window we have. */
+ for (l = priv->windows; l; l = l->next) {
+ window = l->data;
+
+#if GTK_CHECK_VERSION (2,14,0)
+ if (GDK_WINDOW_XID (gtk_widget_get_window (window)) == xid) {
+#else
+ if (GDK_WINDOW_XID (window->window) == xid) {
+#endif
+ return window;
+ }
+ }
+ }
+
+ return NULL;
+#else
+ return priv->windows->data;
+#endif
+}
+
+GtkWidget *
+dh_base_get_window (DhBase *base)
+{
+ GtkWidget *window;
+
+ g_return_val_if_fail (DH_IS_BASE (base), NULL);
+
+ window = dh_base_get_window_on_current_workspace (base);
+ if (!window) {
+ window = dh_base_new_window (base);
+ gtk_window_present (GTK_WINDOW (window));
+ }
+
+ return window;
+}
+
+void
+dh_base_quit (DhBase *base)
+{
+ DhBasePriv *priv = GET_PRIVATE (base);
+
+ /* Make sure all of the windows get a chance to release their resources
+ * properly. As they get destroyed,
+ * base_window_or_assistant_finalized_cb() will be called, and when the
+ * last one is removed, we will quit */
+ g_slist_foreach (priv->windows, (GFunc)gtk_widget_destroy, NULL);
+ g_slist_foreach (priv->assistants, (GFunc)gtk_widget_destroy, NULL);
+}
Modified: devhelp/devhelp/dh-base.h
62 files changed, 62 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2002 CodeFactory AB
+ * Copyright (C) 2002 Mikael Hallendal
+ * Copyright (C) 2005-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_BASE_H__
+#define __DH_BASE_H__
+
+#include
+
+#include "dh-book-manager.h"
+
+G_BEGIN_DECLS
+
+typedef struct _DhBase DhBase;
+typedef struct _DhBaseClass DhBaseClass;
+
+#define DH_TYPE_BASE (dh_base_get_type ())
+#define DH_BASE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DH_TYPE_BASE, DhBase))
+#define DH_BASE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), DH_TYPE_BASE, DhBaseClass))
+#define DH_IS_BASE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DH_TYPE_BASE))
+#define DH_IS_BASE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DH_TYPE_BASE))
+#define DH_BASE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DH_TYPE_BASE, DhBaseClass))
+
+struct _DhBase {
+ GObject parent_instance;
+};
+
+struct _DhBaseClass {
+ GObjectClass parent_class;
+};
+
+GType dh_base_get_type (void) G_GNUC_CONST;
+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);
+DhBookManager *dh_base_get_book_manager (DhBase *base);
+void dh_base_quit (DhBase *base);
+
+G_END_DECLS
+
+#endif /* __DH_BASE_H__ */
Modified: devhelp/devhelp/dh-book-manager.c
408 files changed, 408 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,408 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2002 CodeFactory AB
+ * Copyright (C) 2002 Mikael Hallendal
+ * Copyright (C) 2004-2008 Imendio AB
+ * Copyright (C) 2010 Lanedo GmbH
+ *
+ * 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
+
+#include "dh-link.h"
+#include "dh-util.h"
+#include "dh-book.h"
+#include "dh-book-manager.h"
+#include "dh-marshal.h"
+
+typedef struct {
+ /* The list of all DhBooks found in the system */
+ GList *books;
+} DhBookManagerPriv;
+
+enum {
+ DISABLED_BOOK_LIST_UPDATED,
+ LAST_SIGNAL
+};
+
+static gint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (DhBookManager, dh_book_manager, G_TYPE_OBJECT);
+
+#define GET_PRIVATE(instance) G_TYPE_INSTANCE_GET_PRIVATE \
+ (instance, DH_TYPE_BOOK_MANAGER, DhBookManagerPriv)
+
+static void dh_book_manager_init (DhBookManager *book_manager);
+static void dh_book_manager_class_init (DhBookManagerClass *klass);
+
+static void book_manager_add_from_filepath (DhBookManager *book_manager,
+ const gchar *book_path);
+static void book_manager_add_from_dir (DhBookManager *book_manager,
+ const gchar *dir_path);
+
+#ifdef GDK_WINDOWING_QUARTZ
+static void book_manager_add_from_xcode_docset (DhBookManager *book_manager,
+ const gchar *dir_path);
+#endif
+
+static void
+book_manager_finalize (GObject *object)
+{
+ DhBookManagerPriv *priv;
+ GList *l;
+
+ priv = GET_PRIVATE (object);
+
+ /* Destroy all books */
+ for (l = priv->books; l; l = g_list_next (l)) {
+ g_object_unref (l->data);
+ }
+ g_list_free (priv->books);
+
+ G_OBJECT_CLASS (dh_book_manager_parent_class)->finalize (object);
+}
+
+static void
+dh_book_manager_class_init (DhBookManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = book_manager_finalize;
+
+ signals[DISABLED_BOOK_LIST_UPDATED] =
+ g_signal_new ("disabled-book-list-updated",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (DhBookManagerClass, disabled_book_list_updated),
+ NULL, NULL,
+ _dh_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ g_type_class_add_private (klass, sizeof (DhBookManagerPriv));
+}
+
+static void
+dh_book_manager_init (DhBookManager *book_manager)
+{
+ DhBookManagerPriv *priv = GET_PRIVATE (book_manager);
+
+ priv->books = NULL;
+}
+
+static void
+book_manager_clean_list_of_books_disabled (GSList *books_disabled)
+{
+ GSList *sl;
+
+ for (sl = books_disabled; sl; sl = g_slist_next (sl)) {
+ g_free (sl->data);
+ }
+ g_slist_free (sl);
+}
+
+static void
+book_manager_check_status_from_conf (DhBookManager *book_manager)
+{
+ GSList *books_disabled, *sl;
+
+ books_disabled = dh_util_state_load_books_disabled ();
+
+ for (sl = books_disabled; sl; sl = g_slist_next (sl)) {
+ DhBook *book;
+
+ book = dh_book_manager_get_book_by_name (book_manager,
+ (const gchar *)sl->data);
+ if (book) {
+ dh_book_set_enabled (book, FALSE);
+ }
+ }
+
+ book_manager_clean_list_of_books_disabled (books_disabled);
+}
+
+static void
+book_manager_add_books_in_data_dir (DhBookManager *book_manager,
+ const gchar *data_dir)
+{
+ gchar *dir;
+
+ dir = g_build_filename (data_dir, "gtk-doc", "html", NULL);
+ book_manager_add_from_dir (book_manager, dir);
+ g_free (dir);
+
+ dir = g_build_filename (data_dir, "devhelp", "books", NULL);
+ book_manager_add_from_dir (book_manager, dir);
+ g_free (dir);
+}
+
+void
+dh_book_manager_populate (DhBookManager *book_manager)
+{
+ const gchar * const * system_dirs;
+
+ book_manager_add_books_in_data_dir (book_manager,
+ g_get_user_data_dir ());
+
+ system_dirs = g_get_system_data_dirs ();
+ while (*system_dirs) {
+ book_manager_add_books_in_data_dir (book_manager,
+ *system_dirs);
+ system_dirs++;
+ }
+
+#ifdef GDK_WINDOWING_QUARTZ
+ book_manager_add_from_xcode_docset (
+ book_manager,
+ "/Library/Developer/Shared/Documentation/DocSets");
+#endif
+
+ /* Once all books are loaded, check enabled status from conf */
+ book_manager_check_status_from_conf (book_manager);
+}
+
+static gchar *
+book_manager_get_book_path (const gchar *base_path,
+ const gchar *name)
+{
+ static const gchar *suffixes[] = {
+ "devhelp2",
+ "devhelp2.gz",
+ "devhelp",
+ "devhelp.gz",
+ NULL
+ };
+ gchar *tmp;
+ gchar *book_path;
+ guint i;
+
+ for (i = 0; suffixes[i]; i++) {
+ tmp = g_build_filename (base_path, name, name, NULL);
+ book_path = g_strconcat (tmp, ".", suffixes[i], NULL);
+ g_free (tmp);
+
+ if (g_file_test (book_path, G_FILE_TEST_EXISTS)) {
+ return book_path;;
+ }
+ g_free (book_path);
+ }
+ return NULL;
+}
+
+static void
+book_manager_add_from_dir (DhBookManager *book_manager,
+ const gchar *dir_path)
+{
+ GDir *dir;
+ const gchar *name;
+
+ g_return_if_fail (book_manager);
+ g_return_if_fail (dir_path);
+
+ /* Open directory */
+ dir = g_dir_open (dir_path, 0, NULL);
+ if (!dir) {
+ return;
+ }
+
+ /* And iterate it */
+ while ((name = g_dir_read_name (dir)) != NULL) {
+ gchar *book_path;
+
+ book_path = book_manager_get_book_path (dir_path, name);
+ if (book_path) {
+ /* Add book from filepath */
+ book_manager_add_from_filepath (book_manager,
+ book_path);
+ g_free (book_path);
+ }
+ }
+
+ g_dir_close (dir);
+}
+
+#ifdef GDK_WINDOWING_QUARTZ
+static gboolean
+seems_docset_dir (const gchar *path)
+{
+ gchar *tmp;
+ gboolean seems_like_devhelp = FALSE;
+
+ g_return_val_if_fail (path, FALSE);
+
+ /* Do some sanity checking on the directory first so we don't have
+ * to go through several hundreds of files in every docset.
+ */
+ tmp = g_build_filename (path, "style.css", NULL);
+ if (g_file_test (tmp, G_FILE_TEST_EXISTS)) {
+ gchar *tmp;
+
+ tmp = g_build_filename (path, "index.sgml", NULL);
+ if (g_file_test (tmp, G_FILE_TEST_EXISTS)) {
+ seems_like_devhelp = TRUE;
+ }
+ g_free (tmp);
+ }
+ g_free (tmp);
+
+ return seems_like_devhelp;
+}
+
+static void
+book_manager_add_from_xcode_docset (DhBookManager *book_manager,
+ const gchar *dir_path)
+{
+ GDir *dir;
+ const gchar *name;
+
+ g_return_if_fail (book_manager);
+ g_return_if_fail (dir_path);
+
+ if (!seems_docset_dir (dir_path)) {
+ return;
+ }
+
+ /* Open directory */
+ dir = g_dir_open (dir_path, 0, NULL);
+ if (!dir) {
+ return;
+ }
+
+ /* And iterate it, looking for files ending with .devhelp2 */
+ while ((name = g_dir_read_name (dir)) != NULL) {
+ if (g_strcmp0 (strrchr (name, '.'),
+ ".devhelp2") == 0) {
+ gchar *book_path;
+
+ book_path = g_build_filename (path, name, NULL);
+ /* Add book from filepath */
+ book_manager_add_from_filepath (book_manager,
+ book_path);
+ g_free (book_path);
+ }
+ }
+
+ g_dir_close (dir);
+}
+#endif
+
+static void
+book_manager_add_from_filepath (DhBookManager *book_manager,
+ const gchar *book_path)
+{
+ DhBookManagerPriv *priv;
+ DhBook *book;
+
+ g_return_if_fail (book_manager);
+ g_return_if_fail (book_path);
+
+ priv = GET_PRIVATE (book_manager);
+
+ /* Allocate new book struct */
+ book = dh_book_new (book_path);
+
+ /* Check if book with same path was already loaded in the manager */
+ if (g_list_find_custom (priv->books,
+ book,
+ (GCompareFunc)dh_book_cmp_by_path)) {
+ g_object_unref (book);
+ return;
+ }
+
+ /* Check if book with same bookname was already loaded in the manager
+ * (we need to force unique book names) */
+ if (g_list_find_custom (priv->books,
+ book,
+ (GCompareFunc)dh_book_cmp_by_name)) {
+ g_object_unref (book);
+ return;
+ }
+
+ /* Add the book to the book list */
+ priv->books = g_list_insert_sorted (priv->books,
+ book,
+ (GCompareFunc)dh_book_cmp_by_title);
+}
+
+GList *
+dh_book_manager_get_books (DhBookManager *book_manager)
+{
+ g_return_val_if_fail (book_manager, NULL);
+
+ return GET_PRIVATE (book_manager)->books;
+}
+
+DhBook *
+dh_book_manager_get_book_by_name (DhBookManager *book_manager,
+ const gchar *name)
+{
+ DhBook *book = NULL;
+ GList *l;
+
+ g_return_val_if_fail (book_manager, NULL);
+
+ for (l = GET_PRIVATE (book_manager)->books;
+ l && !book;
+ l = g_list_next (l)) {
+ if (g_strcmp0 (name,
+ dh_book_get_name (DH_BOOK (l->data))) == 0) {
+ book = l->data;
+ }
+ }
+
+ return book;
+}
+
+void
+dh_book_manager_update (DhBookManager *book_manager)
+{
+ DhBookManagerPriv *priv;
+ GSList *books_disabled = NULL;
+ GList *l;
+
+ g_return_if_fail (book_manager);
+
+ priv = GET_PRIVATE (book_manager);
+
+ /* Create list of disabled books */
+ for (l = priv->books; l; l = g_list_next (l)) {
+ DhBook *book = DH_BOOK (l->data);
+
+ if (!dh_book_get_enabled (book)) {
+ books_disabled = g_slist_append (books_disabled,
+ g_strdup (dh_book_get_name (book)));
+ }
+ }
+
+ /* Store in conf */
+ dh_util_state_store_books_disabled (books_disabled);
+
+ /* Emit signal to notify others */
+ g_signal_emit (book_manager,
+ signals[DISABLED_BOOK_LIST_UPDATED],
+ 0);
+
+ book_manager_clean_list_of_books_disabled (books_disabled);
+}
+
+DhBookManager *
+dh_book_manager_new (void)
+{
+ return g_object_new (DH_TYPE_BOOK_MANAGER, NULL);
+}
+
Modified: devhelp/devhelp/dh-book-manager.h
61 files changed, 61 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2010 Lanedo GmbH
+ *
+ * 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_BOOK_MANAGER_H__
+#define __DH_BOOK_MANAGER_H__
+
+#include
+
+#include "dh-book.h"
+
+G_BEGIN_DECLS
+
+typedef struct _DhBookManager DhBookManager;
+typedef struct _DhBookManagerClass DhBookManagerClass;
+
+#define DH_TYPE_BOOK_MANAGER (dh_book_manager_get_type ())
+#define DH_BOOK_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DH_TYPE_BOOK_MANAGER, DhBookManager))
+#define DH_BOOK_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), DH_TYPE_BOOK_MANAGER, DhBookManagerClass))
+#define DH_IS_BOOK_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DH_TYPE_BOOK_MANAGER))
+#define DH_IS_BOOK_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DH_TYPE_BOOK_MANAGER))
+#define DH_BOOK_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DH_TYPE_BOOK_MANAGER, DhBookManagerClass))
+
+struct _DhBookManager {
+ GObject parent_instance;
+};
+
+struct _DhBookManagerClass {
+ GObjectClass parent_class;
+
+ /* Signals */
+ void (* disabled_book_list_updated) (DhBookManager *book_manager);
+};
+
+GType dh_book_manager_get_type (void) G_GNUC_CONST;
+DhBookManager *dh_book_manager_new (void);
+void dh_book_manager_populate (DhBookManager *book_manager);
+GList *dh_book_manager_get_books (DhBookManager *book_manager);
+DhBook *dh_book_manager_get_book_by_name (DhBookManager *book_manager,
+ const gchar *name);
+void dh_book_manager_update (DhBookManager *book_manager);
+
+G_END_DECLS
+
+#endif /* __DH_BOOK_MANAGER_H__ */
Modified: devhelp/devhelp/dh-book-tree.c
385 files changed, 385 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,385 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2001-2003 Mikael Hallendal
+ * Copyright (C) 2003 CodeFactory AB
+ * 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
+#include
+#include
+
+#include "dh-marshal.h"
+#include "dh-book-tree.h"
+#include "dh-book.h"
+
+typedef struct {
+ const gchar *uri;
+ gboolean found;
+ GtkTreeIter iter;
+ GtkTreePath *path;
+} FindURIData;
+
+typedef struct {
+ GtkTreeStore *store;
+ DhBookManager *book_manager;
+ DhLink *selected_link;
+} DhBookTreePriv;
+
+static void dh_book_tree_class_init (DhBookTreeClass *klass);
+static void dh_book_tree_init (DhBookTree *tree);
+static void book_tree_add_columns (DhBookTree *tree);
+static void book_tree_setup_selection (DhBookTree *tree);
+static void book_tree_populate_tree (DhBookTree *tree);
+static void book_tree_insert_node (DhBookTree *tree,
+ GNode *node,
+ GtkTreeIter *parent_iter);
+static void book_tree_selection_changed_cb (GtkTreeSelection *selection,
+ DhBookTree *tree);
+
+enum {
+ LINK_SELECTED,
+ LAST_SIGNAL
+};
+
+enum {
+ COL_TITLE,
+ COL_LINK,
+ COL_WEIGHT,
+ N_COLUMNS
+};
+
+G_DEFINE_TYPE (DhBookTree, dh_book_tree, GTK_TYPE_TREE_VIEW);
+
+#define GET_PRIVATE(instance) G_TYPE_INSTANCE_GET_PRIVATE \
+ (instance, DH_TYPE_BOOK_TREE, DhBookTreePriv);
+
+static gint signals[LAST_SIGNAL] = { 0 };
+
+static void
+book_tree_finalize (GObject *object)
+{
+ DhBookTreePriv *priv = GET_PRIVATE (object);
+
+ g_object_unref (priv->store);
+ g_object_unref (priv->book_manager);
+
+ G_OBJECT_CLASS (dh_book_tree_parent_class)->finalize (object);
+}
+
+static void
+dh_book_tree_class_init (DhBookTreeClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = book_tree_finalize;
+
+ signals[LINK_SELECTED] =
+ g_signal_new ("link-selected",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ _dh_marshal_VOID__POINTER,
+ G_TYPE_NONE,
+ 1, G_TYPE_POINTER);
+
+ g_type_class_add_private (klass, sizeof (DhBookTreePriv));
+}
+
+static void
+dh_book_tree_init (DhBookTree *tree)
+{
+ DhBookTreePriv *priv;
+
+ priv = GET_PRIVATE (tree);
+
+ priv->store = gtk_tree_store_new (N_COLUMNS,
+ G_TYPE_STRING,
+ G_TYPE_POINTER,
+ PANGO_TYPE_WEIGHT);
+ priv->selected_link = NULL;
+ gtk_tree_view_set_model (GTK_TREE_VIEW (tree),
+ GTK_TREE_MODEL (priv->store));
+
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree), FALSE);
+
+ book_tree_add_columns (tree);
+
+ book_tree_setup_selection (tree);
+}
+
+static void
+book_tree_add_columns (DhBookTree *tree)
+{
+ GtkCellRenderer *cell;
+ GtkTreeViewColumn *column;
+
+ column = gtk_tree_view_column_new ();
+
+ cell = gtk_cell_renderer_text_new ();
+ g_object_set (cell,
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ NULL);
+ gtk_tree_view_column_pack_start (column, cell, TRUE);
+ gtk_tree_view_column_set_attributes (column, cell,
+ "text", COL_TITLE,
+ "weight", COL_WEIGHT,
+ NULL);
+
+ gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
+}
+
+static void
+book_tree_setup_selection (DhBookTree *tree)
+{
+ GtkTreeSelection *selection;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
+
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
+
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (book_tree_selection_changed_cb),
+ tree);
+}
+
+static void
+book_tree_populate_tree (DhBookTree *tree)
+{
+ DhBookTreePriv *priv = GET_PRIVATE (tree);
+ GList *l;
+
+ gtk_tree_store_clear (priv->store);
+
+ for (l = dh_book_manager_get_books (priv->book_manager);
+ l;
+ l = g_list_next (l)) {
+ DhBook *book = DH_BOOK (l->data);
+ GNode *node;
+
+ node = dh_book_get_tree (book);
+ while(node) {
+ book_tree_insert_node (tree, node, NULL);
+ node = g_node_next_sibling (node);
+ }
+ }
+}
+
+static void
+book_manager_disabled_book_list_changed_cb (DhBookManager *book_manager,
+ gpointer user_data)
+{
+ DhBookTree *tree = user_data;
+ book_tree_populate_tree (tree);
+}
+
+static void
+book_tree_insert_node (DhBookTree *tree,
+ GNode *node,
+ GtkTreeIter *parent_iter)
+
+{
+ DhBookTreePriv *priv = GET_PRIVATE (tree);
+ DhLink *link;
+ GtkTreeIter iter;
+ PangoWeight weight;
+ GNode *child;
+
+ link = node->data;
+
+ gtk_tree_store_append (priv->store, &iter, parent_iter);
+
+ if (dh_link_get_link_type (link) == DH_LINK_TYPE_BOOK) {
+ weight = PANGO_WEIGHT_BOLD;
+ } else {
+ weight = PANGO_WEIGHT_NORMAL;
+ }
+
+ gtk_tree_store_set (priv->store, &iter,
+ COL_TITLE, dh_link_get_name (link),
+ COL_LINK, link,
+ COL_WEIGHT, weight,
+ -1);
+
+ for (child = g_node_first_child (node);
+ child;
+ child = g_node_next_sibling (child)) {
+ book_tree_insert_node (tree, child, &iter);
+ }
+}
+
+static void
+book_tree_selection_changed_cb (GtkTreeSelection *selection,
+ DhBookTree *tree)
+{
+ DhBookTreePriv *priv = GET_PRIVATE (tree);
+ GtkTreeIter iter;
+
+ if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
+ DhLink *link;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (priv->store),
+ &iter,
+ COL_LINK, &link,
+ -1);
+ if (link != priv->selected_link) {
+ g_signal_emit (tree, signals[LINK_SELECTED], 0, link);
+ }
+ priv->selected_link = link;
+ }
+}
+
+GtkWidget *
+dh_book_tree_new (DhBookManager *book_manager)
+{
+ DhBookTree *tree;
+ DhBookTreePriv *priv;
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ DhLink *link;
+
+ tree = g_object_new (DH_TYPE_BOOK_TREE, NULL);
+ priv = GET_PRIVATE (tree);
+
+ priv->book_manager = g_object_ref (book_manager);
+ g_signal_connect (priv->book_manager,
+ "disabled-book-list-updated",
+ G_CALLBACK (book_manager_disabled_book_list_changed_cb),
+ tree);
+
+ book_tree_populate_tree (tree);
+
+ /* Mark the first item as selected, or it would get automatically
+ * selected when the treeview will get focus; but that's not even
+ * enough as a selection changed would still be emitted when there
+ * is no change, hence the manual tracking of selection in
+ * selected_link.
+ * https://bugzilla.gnome.org/show_bug.cgi?id=492206
+ */
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
+ g_signal_handlers_block_by_func (selection,
+ book_tree_selection_changed_cb,
+ tree);
+ gtk_tree_model_get_iter_first ( GTK_TREE_MODEL (priv->store), &iter);
+ gtk_tree_model_get (GTK_TREE_MODEL (priv->store),
+ &iter, COL_LINK, &link, -1);
+ priv->selected_link = link;
+ gtk_tree_selection_select_iter (selection, &iter);
+ g_signal_handlers_unblock_by_func (selection,
+ book_tree_selection_changed_cb,
+ tree);
+
+ return GTK_WIDGET (tree);
+}
+
+static gboolean
+book_tree_find_uri_foreach (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ FindURIData *data)
+{
+ DhLink *link;
+ gchar *link_uri;
+
+ gtk_tree_model_get (model, iter,
+ COL_LINK, &link,
+ -1);
+
+ link_uri = dh_link_get_uri (link);
+ if (g_str_has_prefix (data->uri, link_uri)) {
+ data->found = TRUE;
+ data->iter = *iter;
+ data->path = gtk_tree_path_copy (path);
+ }
+ g_free (link_uri);
+
+ return data->found;
+}
+
+void
+dh_book_tree_select_uri (DhBookTree *tree,
+ const gchar *uri)
+{
+ DhBookTreePriv *priv = GET_PRIVATE (tree);
+ GtkTreeSelection *selection;
+ FindURIData data;
+
+ data.found = FALSE;
+ data.uri = uri;
+
+ gtk_tree_model_foreach (GTK_TREE_MODEL (priv->store),
+ (GtkTreeModelForeachFunc) book_tree_find_uri_foreach,
+ &data);
+
+ if (!data.found) {
+ return;
+ }
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
+
+ g_signal_handlers_block_by_func (selection,
+ book_tree_selection_changed_cb,
+ tree);
+
+ gtk_tree_view_expand_to_path (GTK_TREE_VIEW (tree), data.path);
+ gtk_tree_selection_select_iter (selection, &data.iter);
+ gtk_tree_view_set_cursor (GTK_TREE_VIEW (tree), data.path, NULL, 0);
+
+ g_signal_handlers_unblock_by_func (selection,
+ book_tree_selection_changed_cb,
+ tree);
+
+ gtk_tree_path_free (data.path);
+}
+
+const gchar *
+dh_book_tree_get_selected_book_title (DhBookTree *tree)
+{
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ DhLink *link;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ return NULL;
+ }
+
+ path = gtk_tree_model_get_path (model, &iter);
+
+ /* Get the book node for this link. */
+ while (1) {
+ if (gtk_tree_path_get_depth (path) <= 1) {
+ break;
+ }
+
+ gtk_tree_path_up (path);
+ }
+
+ gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_path_free (path);
+
+ gtk_tree_model_get (model, &iter,
+ COL_LINK, &link,
+ -1);
+
+ return dh_link_get_name (link);
+}
Modified: devhelp/devhelp/dh-book-tree.h
55 files changed, 55 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2001 Mikael Hallendal
+ *
+ * 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_BOOK_TREE_H__
+#define __DH_BOOK_TREE_H__
+
+#include
+#include "dh-link.h"
+#include "dh-book-manager.h"
+
+G_BEGIN_DECLS
+
+#define DH_TYPE_BOOK_TREE (dh_book_tree_get_type ())
+#define DH_BOOK_TREE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DH_TYPE_BOOK_TREE, DhBookTree))
+#define DH_BOOK_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DH_TYPE_BOOK_TREE, DhBookTreeClass))
+#define DH_IS_BOOK_TREE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DH_TYPE_BOOK_TREE))
+#define DH_IS_BOOK_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), DH_TYPE_BOOK_TREE))
+
+typedef struct _DhBookTree DhBookTree;
+typedef struct _DhBookTreeClass DhBookTreeClass;
+
+struct _DhBookTree {
+ GtkTreeView parent_instance;
+};
+
+struct _DhBookTreeClass {
+ GtkTreeViewClass parent_class;
+};
+
+GType dh_book_tree_get_type (void) G_GNUC_CONST;
+GtkWidget * dh_book_tree_new (DhBookManager *book_manager);
+void dh_book_tree_select_uri (DhBookTree *book_tree,
+ const gchar *uri);
+const gchar *dh_book_tree_get_selected_book_title (DhBookTree *tree);
+
+G_END_DECLS
+
+#endif /* __DH_BOOK_TREE_H__ */
Modified: devhelp/devhelp/dh-book.c
246 files changed, 246 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,246 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2002 CodeFactory AB
+ * Copyright (C) 2002 Mikael Hallendal
+ * Copyright (C) 2004-2008 Imendio AB
+ * Copyright (C) 2010 Lanedo GmbH
+ *
+ * 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
+
+#include "dh-link.h"
+#include "dh-parser.h"
+#include "dh-book.h"
+
+/* Structure defining basic contents to store about every book */
+typedef struct {
+ /* File path of the book */
+ gchar *path;
+ /* Enable or disabled? */
+ gboolean enabled;
+ /* Book name */
+ gchar *name;
+ /* Book title */
+ gchar *title;
+ /* Generated book tree */
+ GNode *tree;
+ /* Generated list of keywords in the book */
+ GList *keywords;
+} DhBookPriv;
+
+G_DEFINE_TYPE (DhBook, dh_book, G_TYPE_OBJECT);
+
+#define GET_PRIVATE(instance) G_TYPE_INSTANCE_GET_PRIVATE \
+ (instance, DH_TYPE_BOOK, DhBookPriv)
+
+static void dh_book_init (DhBook *book);
+static void dh_book_class_init (DhBookClass *klass);
+
+static void unref_node_link (GNode *node,
+ gpointer data);
+
+static void
+book_finalize (GObject *object)
+{
+ DhBookPriv *priv;
+
+ priv = GET_PRIVATE (object);
+
+ if (priv->tree) {
+ g_node_traverse (priv->tree,
+ G_IN_ORDER,
+ G_TRAVERSE_ALL,
+ -1,
+ (GNodeTraverseFunc)unref_node_link,
+ NULL);
+ g_node_destroy (priv->tree);
+ }
+
+ if (priv->keywords) {
+ g_list_foreach (priv->keywords, (GFunc)dh_link_unref, NULL);
+ g_list_free (priv->keywords);
+ }
+
+ g_free (priv->title);
+
+ g_free (priv->path);
+
+ G_OBJECT_CLASS (dh_book_parent_class)->finalize (object);
+}
+
+static void
+dh_book_class_init (DhBookClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = book_finalize;
+
+ g_type_class_add_private (klass, sizeof (DhBookPriv));
+}
+
+static void
+dh_book_init (DhBook *book)
+{
+ DhBookPriv *priv = GET_PRIVATE (book);
+
+ priv->name = NULL;
+ priv->path = NULL;
+ priv->title = NULL;
+ priv->enabled = TRUE;
+ priv->tree = NULL;
+ priv->keywords = NULL;
+}
+
+static void
+unref_node_link (GNode *node,
+ gpointer data)
+{
+ dh_link_unref (node->data);
+}
+
+DhBook *
+dh_book_new (const gchar *book_path)
+{
+ DhBookPriv *priv;
+ DhBook *book;
+ GError *error = NULL;
+
+ g_return_val_if_fail (book_path, NULL);
+
+ book = g_object_new (DH_TYPE_BOOK, NULL);
+ priv = GET_PRIVATE (book);
+
+ /* Parse file storing contents in the book struct */
+ if (!dh_parser_read_file (book_path,
+ &priv->tree,
+ &priv->keywords,
+ &error)) {
+ g_warning ("Failed to read '%s': %s",
+ priv->path, error->message);
+ g_error_free (error);
+
+ /* Deallocate the book, as we are not going to add it
+ * in the manager */
+ g_object_unref (book);
+ return NULL;
+ }
+
+ /* Store path */
+ priv->path = g_strdup (book_path);
+
+ /* Setup title */
+ priv->title = g_strdup (dh_link_get_name ((DhLink *)priv->tree->data));
+
+ /* Setup name */
+ priv->name = g_strdup (dh_link_get_book_id ((DhLink *)priv->tree->data));
+
+ return book;
+}
+
+GList *
+dh_book_get_keywords (DhBook *book)
+{
+ DhBookPriv *priv;
+
+ g_return_val_if_fail (DH_IS_BOOK (book), NULL);
+
+ priv = GET_PRIVATE (book);
+
+ return priv->enabled ? priv->keywords : NULL;
+}
+
+GNode *
+dh_book_get_tree (DhBook *book)
+{
+ DhBookPriv *priv;
+
+ g_return_val_if_fail (DH_IS_BOOK (book), NULL);
+
+ priv = GET_PRIVATE (book);
+
+ return priv->enabled ? priv->tree : NULL;
+}
+
+const gchar *
+dh_book_get_name (DhBook *book)
+{
+ DhBookPriv *priv;
+
+ g_return_val_if_fail (DH_IS_BOOK (book), NULL);
+
+ priv = GET_PRIVATE (book);
+
+ return priv->name;
+}
+
+const gchar *
+dh_book_get_title (DhBook *book)
+{
+ DhBookPriv *priv;
+
+ g_return_val_if_fail (DH_IS_BOOK (book), NULL);
+
+ priv = GET_PRIVATE (book);
+
+ return priv->title;
+}
+
+gboolean
+dh_book_get_enabled (DhBook *book)
+{
+ g_return_val_if_fail (DH_IS_BOOK (book), FALSE);
+
+ return GET_PRIVATE (book)->enabled;
+}
+
+void
+dh_book_set_enabled (DhBook *book,
+ gboolean enabled)
+{
+ g_return_if_fail (DH_IS_BOOK (book));
+
+ GET_PRIVATE (book)->enabled = enabled;
+}
+
+gint
+dh_book_cmp_by_path (const DhBook *a,
+ const DhBook *b)
+{
+ return ((a && b) ?
+ g_strcmp0 (GET_PRIVATE (a)->path, GET_PRIVATE (b)->path) :
+ -1);
+}
+
+gint
+dh_book_cmp_by_name (const DhBook *a,
+ const DhBook *b)
+{
+ return ((a && b) ?
+ g_ascii_strcasecmp (GET_PRIVATE (a)->name, GET_PRIVATE (b)->name) :
+ -1);
+}
+
+gint
+dh_book_cmp_by_title (const DhBook *a,
+ const DhBook *b)
+{
+ return ((a && b) ?
+ g_utf8_collate (GET_PRIVATE (a)->title, GET_PRIVATE (b)->title) :
+ -1);
+}
Modified: devhelp/devhelp/dh-book.h
67 files changed, 67 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2002 CodeFactory AB
+ * Copyright (C) 2002 Mikael Hallendal
+ * Copyright (C) 2005-2008 Imendio AB
+ * Copyright (C) 2010 Lanedo GmbH
+ *
+ * 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_BOOK_H_
+#define _DH_BOOK_H_
+
+#include
+
+G_BEGIN_DECLS
+
+typedef struct _DhBook DhBook;
+typedef struct _DhBookClass DhBookClass;
+
+#define DH_TYPE_BOOK (dh_book_get_type ())
+#define DH_BOOK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DH_TYPE_BOOK, DhBook))
+#define DH_BOOK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), DH_TYPE_BOOK, DhBookClass))
+#define DH_IS_BOOK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DH_TYPE_BOOK))
+#define DH_IS_BOOK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DH_TYPE_BOOK))
+#define DH_BOOK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DH_TYPE_BOOK, DhBookClass))
+
+struct _DhBook {
+ GObject parent_instance;
+};
+
+struct _DhBookClass {
+ GObjectClass parent_class;
+};
+
+GType dh_book_get_type (void) G_GNUC_CONST;
+DhBook *dh_book_new (const gchar *book_path);
+GList *dh_book_get_keywords (DhBook *book);
+GNode *dh_book_get_tree (DhBook *book);
+const gchar *dh_book_get_name (DhBook *book);
+const gchar *dh_book_get_title (DhBook *book);
+gboolean dh_book_get_enabled (DhBook *book);
+void dh_book_set_enabled (DhBook *book,
+ gboolean enabled);
+gint dh_book_cmp_by_path (const DhBook *a,
+ const DhBook *b);
+gint dh_book_cmp_by_name (const DhBook *a,
+ const DhBook *b);
+gint dh_book_cmp_by_title (const DhBook *a,
+ const DhBook *b);
+
+G_END_DECLS
+
+#endif /* _DH_BOOK_H_ */
Modified: devhelp/devhelp/dh-enum-types.c
137 files changed, 137 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,137 @@
+
+/* Generated data (by glib-mkenums) */
+
+#include "dh-enum-types.h"
+#include "dh-assistant.h"
+#include "dh-assistant-view.h"
+#include "dh-base.h"
+#include "dh-book-manager.h"
+#include "dh-book.h"
+#include "dh-book-tree.h"
+#include "dh-error.h"
+#include "dh-keyword-model.h"
+#include "dh-link.h"
+#include "dh-search.h"
+#include "dh-window.h"
+
+GType
+dh_error_get_type (void)
+{
+ static GType the_type = 0;
+
+ if (the_type == 0)
+ {
+ static const GEnumValue values[] = {
+ { DH_ERROR_FILE_NOT_FOUND,
+ "DH_ERROR_FILE_NOT_FOUND",
+ "file-not-found" },
+ { DH_ERROR_MALFORMED_BOOK,
+ "DH_ERROR_MALFORMED_BOOK",
+ "malformed-book" },
+ { DH_ERROR_INVALID_BOOK_TYPE,
+ "DH_ERROR_INVALID_BOOK_TYPE",
+ "invalid-book-type" },
+ { DH_ERROR_INTERNAL_ERROR,
+ "DH_ERROR_INTERNAL_ERROR",
+ "internal-error" },
+ { 0, NULL, NULL }
+ };
+ the_type = g_enum_register_static (
+ g_intern_static_string ("DhError"),
+ values);
+ }
+ return the_type;
+}
+
+
+GType
+dh_link_type_get_type (void)
+{
+ static GType the_type = 0;
+
+ if (the_type == 0)
+ {
+ static const GEnumValue values[] = {
+ { DH_LINK_TYPE_BOOK,
+ "DH_LINK_TYPE_BOOK",
+ "book" },
+ { DH_LINK_TYPE_PAGE,
+ "DH_LINK_TYPE_PAGE",
+ "page" },
+ { DH_LINK_TYPE_KEYWORD,
+ "DH_LINK_TYPE_KEYWORD",
+ "keyword" },
+ { DH_LINK_TYPE_FUNCTION,
+ "DH_LINK_TYPE_FUNCTION",
+ "function" },
+ { DH_LINK_TYPE_STRUCT,
+ "DH_LINK_TYPE_STRUCT",
+ "struct" },
+ { DH_LINK_TYPE_MACRO,
+ "DH_LINK_TYPE_MACRO",
+ "macro" },
+ { DH_LINK_TYPE_ENUM,
+ "DH_LINK_TYPE_ENUM",
+ "enum" },
+ { DH_LINK_TYPE_TYPEDEF,
+ "DH_LINK_TYPE_TYPEDEF",
+ "typedef" },
+ { 0, NULL, NULL }
+ };
+ the_type = g_enum_register_static (
+ g_intern_static_string ("DhLinkType"),
+ values);
+ }
+ return the_type;
+}
+
+GType
+dh_link_flags_get_type (void)
+{
+ static GType the_type = 0;
+
+ if (the_type == 0)
+ {
+ static const GFlagsValue values[] = {
+ { DH_LINK_FLAGS_NONE,
+ "DH_LINK_FLAGS_NONE",
+ "none" },
+ { DH_LINK_FLAGS_DEPRECATED,
+ "DH_LINK_FLAGS_DEPRECATED",
+ "deprecated" },
+ { 0, NULL, NULL }
+ };
+ the_type = g_flags_register_static (
+ g_intern_static_string ("DhLinkFlags"),
+ values);
+ }
+ return the_type;
+}
+
+
+GType
+dh_open_link_flags_get_type (void)
+{
+ static GType the_type = 0;
+
+ if (the_type == 0)
+ {
+ static const GFlagsValue values[] = {
+ { DH_OPEN_LINK_NEW_WINDOW,
+ "DH_OPEN_LINK_NEW_WINDOW",
+ "window" },
+ { DH_OPEN_LINK_NEW_TAB,
+ "DH_OPEN_LINK_NEW_TAB",
+ "tab" },
+ { 0, NULL, NULL }
+ };
+ the_type = g_flags_register_static (
+ g_intern_static_string ("DhOpenLinkFlags"),
+ values);
+ }
+ return the_type;
+}
+
+
+/* Generated data ends here */
+
Modified: devhelp/devhelp/dh-enum-types.c.template
47 files changed, 47 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,47 @@
+/*** BEGIN file-header ***/
+#include "dh-enum-types.h"
+#include "dh-assistant.h"
+#include "dh-assistant-view.h"
+#include "dh-base.h"
+#include "dh-book-manager.h"
+#include "dh-book.h"
+#include "dh-book-tree.h"
+#include "dh-error.h"
+#include "dh-keyword-model.h"
+#include "dh-link.h"
+#include "dh-search.h"
+#include "dh-window.h"
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType
+ at enum_name@_get_type (void)
+{
+ static GType the_type = 0;
+
+ if (the_type == 0)
+ {
+ static const G at Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+ { @VALUENAME@,
+ "@VALUENAME@",
+ "@valuenick@" },
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+ { 0, NULL, NULL }
+ };
+ the_type = g_ at type@_register_static (
+ g_intern_static_string ("@EnumName@"),
+ values);
+ }
+ return the_type;
+}
+
+/*** END value-tail ***/
Modified: devhelp/devhelp/dh-enum-types.h
34 files changed, 34 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,34 @@
+
+/* Generated data (by glib-mkenums) */
+
+#ifndef __DH_ENUM_TYPES_H__
+#define __DH_ENUM_TYPES_H__
+
+#include
+
+G_BEGIN_DECLS
+
+/* Enumerations from "dh-error.h" */
+
+#define DH_TYPE_ERROR (dh_error_get_type())
+GType dh_error_get_type (void) G_GNUC_CONST;
+
+/* Enumerations from "dh-link.h" */
+
+#define DH_TYPE_LINK_TYPE (dh_link_type_get_type())
+GType dh_link_type_get_type (void) G_GNUC_CONST;
+
+#define DH_TYPE_LINK_FLAGS (dh_link_flags_get_type())
+GType dh_link_flags_get_type (void) G_GNUC_CONST;
+
+/* Enumerations from "dh-window.h" */
+
+#define DH_TYPE_OPEN_LINK_FLAGS (dh_open_link_flags_get_type())
+GType dh_open_link_flags_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __DH_ENUM_TYPES_H__ */
+
+/* Generated data ends here */
+
Modified: devhelp/devhelp/dh-enum-types.h.template
27 files changed, 27 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,27 @@
+/*** BEGIN file-header ***/
+#ifndef __DH_ENUM_TYPES_H__
+#define __DH_ENUM_TYPES_H__
+
+#include
+
+G_BEGIN_DECLS
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+/* Enumerations from "@filename@" */
+
+/*** END file-production ***/
+
+/*** BEGIN enumeration-production ***/
+#define DH_TYPE_ at ENUMSHORT@ (@enum_name at _get_type())
+GType @enum_name at _get_type (void) G_GNUC_CONST;
+
+/*** END enumeration-production ***/
+
+/*** BEGIN file-tail ***/
+G_END_DECLS
+
+#endif /* __DH_ENUM_TYPES_H__ */
+/*** END file-tail ***/
+
Modified: devhelp/devhelp/dh-error.c
35 files changed, 35 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2002 CodeFactory AB
+ * Copyright (C) 2002 Mikael Hallendal
+ *
+ * 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 "dh-error.h"
+
+GQuark
+dh_error_quark (void)
+{
+ static GQuark q = 0;
+
+ if (q == 0) {
+ q = g_quark_from_static_string ("dh-error-quark");
+ }
+
+ return q;
+}
Modified: devhelp/devhelp/dh-error.h
42 files changed, 42 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,42 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2002 CodeFactory AB
+ * Copyright (C) 2002 Mikael Hallendal
+ *
+ * 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_ERROR_H__
+#define __DH_ERROR_H__
+
+#include
+
+G_BEGIN_DECLS
+
+#define DH_ERROR dh_error_quark ()
+
+typedef enum {
+ DH_ERROR_FILE_NOT_FOUND,
+ DH_ERROR_MALFORMED_BOOK,
+ DH_ERROR_INVALID_BOOK_TYPE,
+ DH_ERROR_INTERNAL_ERROR
+} DhError;
+
+GQuark dh_error_quark (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __DH_ERROR_H__ */
Modified: devhelp/devhelp/dh-keyword-model.c
545 files changed, 545 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,545 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2002 CodeFactory AB
+ * Copyright (C) 2002 Mikael Hallendal
+ * 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
+#include
+
+#include "dh-link.h"
+#include "dh-book.h"
+#include "dh-keyword-model.h"
+
+struct _DhKeywordModelPriv {
+ DhBookManager *book_manager;
+
+ GList *keyword_words;
+ gint keyword_words_length;
+
+ gint stamp;
+};
+
+#define G_LIST(x) ((GList *) x)
+#define MAX_HITS 100
+
+static void dh_keyword_model_init (DhKeywordModel *list_store);
+static void dh_keyword_model_class_init (DhKeywordModelClass *class);
+static void dh_keyword_model_tree_model_init (GtkTreeModelIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (DhKeywordModel, dh_keyword_model, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
+ dh_keyword_model_tree_model_init));
+
+static void
+keyword_model_dispose (GObject *object)
+{
+ DhKeywordModel *model = DH_KEYWORD_MODEL (object);
+ DhKeywordModelPriv *priv = model->priv;
+
+ if (priv->book_manager) {
+ g_object_unref (priv->book_manager);
+ priv->book_manager = NULL;
+ }
+
+ G_OBJECT_CLASS (dh_keyword_model_parent_class)->dispose (object);
+}
+
+static void
+keyword_model_finalize (GObject *object)
+{
+ DhKeywordModel *model = DH_KEYWORD_MODEL (object);
+ DhKeywordModelPriv *priv = model->priv;
+
+ g_list_free (priv->keyword_words);
+
+ g_free (model->priv);
+
+ G_OBJECT_CLASS (dh_keyword_model_parent_class)->finalize (object);
+}
+
+static void
+dh_keyword_model_class_init (DhKeywordModelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);;
+
+ object_class->finalize = keyword_model_finalize;
+ object_class->dispose = keyword_model_dispose;
+}
+
+static void
+dh_keyword_model_init (DhKeywordModel *model)
+{
+ DhKeywordModelPriv *priv;
+
+ priv = g_new0 (DhKeywordModelPriv, 1);
+ model->priv = priv;
+
+ do {
+ priv->stamp = g_random_int ();
+ } while (priv->stamp == 0);
+}
+
+static GtkTreeModelFlags
+keyword_model_get_flags (GtkTreeModel *tree_model)
+{
+ return GTK_TREE_MODEL_ITERS_PERSIST | GTK_TREE_MODEL_LIST_ONLY;
+}
+
+static gint
+keyword_model_get_n_columns (GtkTreeModel *tree_model)
+{
+ return DH_KEYWORD_MODEL_NUM_COLS;
+}
+
+static GType
+keyword_model_get_column_type (GtkTreeModel *tree_model,
+ gint column)
+{
+ switch (column) {
+ case DH_KEYWORD_MODEL_COL_NAME:
+ return G_TYPE_STRING;
+ break;
+ case DH_KEYWORD_MODEL_COL_LINK:
+ return G_TYPE_POINTER;
+ default:
+ return G_TYPE_INVALID;
+ }
+}
+
+static gboolean
+keyword_model_get_iter (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreePath *path)
+{
+ DhKeywordModel *model;
+ DhKeywordModelPriv *priv;
+ GList *node;
+ const gint *indices;
+
+ model = DH_KEYWORD_MODEL (tree_model);
+ priv = model->priv;
+
+ indices = gtk_tree_path_get_indices (path);
+
+ if (indices == NULL) {
+ return FALSE;
+ }
+
+ if (indices[0] >= priv->keyword_words_length) {
+ return FALSE;
+ }
+
+ node = g_list_nth (priv->keyword_words, indices[0]);
+
+ iter->stamp = priv->stamp;
+ iter->user_data = node;
+
+ return TRUE;
+}
+
+static GtkTreePath *
+keyword_model_get_path (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ DhKeywordModel *model = DH_KEYWORD_MODEL (tree_model);
+ DhKeywordModelPriv *priv;
+ GtkTreePath *path;
+ gint i = 0;
+
+ g_return_val_if_fail (iter->stamp == model->priv->stamp, NULL);
+
+ priv = model->priv;
+
+ i = g_list_position (priv->keyword_words, iter->user_data);
+ if (i < 0) {
+ return NULL;
+ }
+
+ path = gtk_tree_path_new ();
+ gtk_tree_path_append_index (path, i);
+
+ return path;
+}
+
+static void
+keyword_model_get_value (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gint column,
+ GValue *value)
+{
+ DhLink *link;
+
+ link = G_LIST (iter->user_data)->data;
+
+ switch (column) {
+ case DH_KEYWORD_MODEL_COL_NAME:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, dh_link_get_name (link));
+ break;
+ case DH_KEYWORD_MODEL_COL_LINK:
+ g_value_init (value, G_TYPE_POINTER);
+ g_value_set_pointer (value, link);
+ break;
+ default:
+ g_warning ("Bad column %d requested", column);
+ }
+}
+
+static gboolean
+keyword_model_iter_next (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ DhKeywordModel *model = DH_KEYWORD_MODEL (tree_model);
+
+ g_return_val_if_fail (model->priv->stamp == iter->stamp, FALSE);
+
+ iter->user_data = G_LIST (iter->user_data)->next;
+
+ return (iter->user_data != NULL);
+}
+
+static gboolean
+keyword_model_iter_children (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent)
+{
+ DhKeywordModelPriv *priv;
+
+ priv = DH_KEYWORD_MODEL (tree_model)->priv;
+
+ /* This is a list, nodes have no children. */
+ if (parent) {
+ return FALSE;
+ }
+
+ /* But if parent == NULL we return the list itself as children of
+ * the "root".
+ */
+ if (priv->keyword_words) {
+ iter->stamp = priv->stamp;
+ iter->user_data = priv->keyword_words;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+keyword_model_iter_has_child (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ return FALSE;
+}
+
+static gint
+keyword_model_iter_n_children (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ DhKeywordModelPriv *priv;
+
+ priv = DH_KEYWORD_MODEL (tree_model)->priv;
+
+ if (iter == NULL) {
+ return priv->keyword_words_length;
+ }
+
+ g_return_val_if_fail (priv->stamp == iter->stamp, -1);
+
+ return 0;
+}
+
+static gboolean
+keyword_model_iter_nth_child (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent,
+ gint n)
+{
+ DhKeywordModelPriv *priv;
+ GList *child;
+
+ priv = DH_KEYWORD_MODEL (tree_model)->priv;
+
+ if (parent) {
+ return FALSE;
+ }
+
+ child = g_list_nth (priv->keyword_words, n);
+
+ if (child) {
+ iter->stamp = priv->stamp;
+ iter->user_data = child;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+keyword_model_iter_parent (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *child)
+{
+ return FALSE;
+}
+
+static void
+dh_keyword_model_tree_model_init (GtkTreeModelIface *iface)
+{
+ iface->get_flags = keyword_model_get_flags;
+ iface->get_n_columns = keyword_model_get_n_columns;
+ iface->get_column_type = keyword_model_get_column_type;
+ iface->get_iter = keyword_model_get_iter;
+ iface->get_path = keyword_model_get_path;
+ iface->get_value = keyword_model_get_value;
+ iface->iter_next = keyword_model_iter_next;
+ iface->iter_children = keyword_model_iter_children;
+ iface->iter_has_child = keyword_model_iter_has_child;
+ iface->iter_n_children = keyword_model_iter_n_children;
+ iface->iter_nth_child = keyword_model_iter_nth_child;
+ iface->iter_parent = keyword_model_iter_parent;
+}
+
+DhKeywordModel *
+dh_keyword_model_new (void)
+{
+ DhKeywordModel *model;
+
+ model = g_object_new (DH_TYPE_KEYWORD_MODEL, NULL);
+
+ return model;
+}
+
+void
+dh_keyword_model_set_words (DhKeywordModel *model,
+ DhBookManager *book_manager)
+{
+ g_return_if_fail (DH_IS_KEYWORD_MODEL (model));
+
+ model->priv->book_manager = g_object_ref (book_manager);
+}
+
+static GList *
+keyword_model_search (DhKeywordModel *model,
+ const gchar *string,
+ gchar **stringv,
+ const gchar *book_id,
+ gboolean case_sensitive,
+ DhLink **exact_link)
+{
+ DhKeywordModelPriv *priv;
+ GList *new_list = NULL, *b;
+ gint hits = 0;
+ gchar *page_id = NULL;
+ gchar *page_filename_prefix = NULL;
+
+ priv = model->priv;
+
+ /* The search string may be prefixed by a page:foobar qualifier, it
+ * will be matched against the filenames of the hits to limit the
+ * search to pages whose filename is prefixed by "foobar.
+ */
+ if (stringv && g_str_has_prefix(stringv[0], "page:")) {
+ page_id = stringv[0] + 5;
+ page_filename_prefix = g_strdup_printf("%s.", page_id);
+ stringv++;
+ }
+
+ for (b = dh_book_manager_get_books (priv->book_manager);
+ b && hits < MAX_HITS;
+ b = g_list_next (b)) {
+ DhBook *book;
+ GList *l;
+
+ book = DH_BOOK (b->data);
+
+ for (l = dh_book_get_keywords (book);
+ l && hits < MAX_HITS;
+ l = g_list_next (l)) {
+ DhLink *link;
+ gboolean found;
+ gchar *name;
+
+ link = l->data;
+ found = FALSE;
+
+ if (book_id &&
+ dh_link_get_book_id (link) &&
+ strcmp (dh_link_get_book_id (link), book_id) != 0) {
+ continue;
+ }
+
+ if (page_id &&
+ (dh_link_get_link_type (link) != DH_LINK_TYPE_PAGE &&
+ !g_str_has_prefix (dh_link_get_file_name (link), page_filename_prefix))) {
+ continue;
+ }
+
+ if (!case_sensitive) {
+ name = g_ascii_strdown (dh_link_get_name (link), -1);
+ } else {
+ name = g_strdup (dh_link_get_name (link));
+ }
+
+ if (!found) {
+ gint i;
+
+ if (stringv[0] == NULL) {
+ /* means only a page was specified, no keyword */
+ if (g_strrstr (dh_link_get_name(link), page_id))
+ found = TRUE;
+ } else {
+ found = TRUE;
+ for (i = 0; stringv[i] != NULL; i++) {
+ if (!g_strrstr (name, stringv[i])) {
+ found = FALSE;
+ break;
+ }
+ }
+ }
+ }
+
+ g_free (name);
+
+ if (found) {
+ /* Include in the new list. */
+ new_list = g_list_prepend (new_list, link);
+ hits++;
+
+ if (!*exact_link &&
+ dh_link_get_name (link) && (
+ (dh_link_get_link_type (link) == DH_LINK_TYPE_PAGE &&
+ page_id && strcmp (dh_link_get_name (link), page_id) == 0) ||
+ (strcmp (dh_link_get_name (link), string) == 0))) {
+ *exact_link = link;
+ }
+ }
+ }
+ }
+
+ g_free (page_filename_prefix);
+
+ return g_list_sort (new_list, dh_link_compare);
+}
+
+DhLink *
+dh_keyword_model_filter (DhKeywordModel *model,
+ const gchar *string,
+ const gchar *book_id)
+{
+ DhKeywordModelPriv *priv;
+ GList *new_list = NULL;
+ gint old_length;
+ DhLink *exact_link = NULL;
+ gint hits;
+ gint i;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+
+ g_return_val_if_fail (DH_IS_KEYWORD_MODEL (model), NULL);
+ g_return_val_if_fail (string != NULL, NULL);
+
+ priv = model->priv;
+
+ /* Do the minimum amount of work: call update on all rows that are
+ * kept and remove the rest.
+ */
+ old_length = priv->keyword_words_length;
+ new_list = NULL;
+ hits = 0;
+
+ if (string[0] != '\0') {
+ gchar **stringv;
+ gboolean case_sensitive;
+
+ stringv = g_strsplit (string, " ", -1);
+
+ case_sensitive = FALSE;
+
+ /* Search for any parameters and position search cursor to
+ * the next element in the search string.
+ */
+ for (i = 0; stringv[i] != NULL; i++) {
+ gchar *lower;
+
+ /* Searches are case sensitive when any uppercase
+ * letter is used in the search terms, matching vim
+ * smartcase behaviour.
+ */
+ lower = g_ascii_strdown (stringv[i], -1);
+ if (strcmp (lower, stringv[i]) != 0) {
+ case_sensitive = TRUE;
+ g_free (lower);
+ break;
+ }
+ g_free (lower);
+ }
+
+ new_list = keyword_model_search (model,
+ string,
+ stringv,
+ book_id,
+ case_sensitive,
+ &exact_link);
+ hits = g_list_length (new_list);
+
+ g_strfreev (stringv);
+ }
+
+ /* Update the list of hits. */
+ g_list_free (priv->keyword_words);
+ priv->keyword_words = new_list;
+ priv->keyword_words_length = hits;
+
+ /* Update model: rows 0 -> hits. */
+ for (i = 0; i < hits; ++i) {
+ path = gtk_tree_path_new ();
+ gtk_tree_path_append_index (path, i);
+ keyword_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
+ gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter);
+ gtk_tree_path_free (path);
+ }
+
+ if (old_length > hits) {
+ /* Update model: remove rows hits -> old_length. */
+ for (i = old_length - 1; i >= hits; i--) {
+ path = gtk_tree_path_new ();
+ gtk_tree_path_append_index (path, i);
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
+ gtk_tree_path_free (path);
+ }
+ }
+ else if (old_length < hits) {
+ /* Update model: add rows old_length -> hits. */
+ for (i = old_length; i < hits; i++) {
+ path = gtk_tree_path_new ();
+ gtk_tree_path_append_index (path, i);
+ keyword_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
+ gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
+ gtk_tree_path_free (path);
+ }
+ }
+
+ if (hits == 1) {
+ return priv->keyword_words->data;
+ }
+
+ return exact_link;
+}
Modified: devhelp/devhelp/dh-keyword-model.h
69 files changed, 69 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,69 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2002 CodeFactory AB
+ * Copyright (C) 2002 Mikael Hallendal
+ *
+ * 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_KEYWORD_MODEL_H__
+#define __DH_KEYWORD_MODEL_H__
+
+#include
+#include "dh-link.h"
+#include "dh-book-manager.h"
+
+G_BEGIN_DECLS
+
+#define DH_TYPE_KEYWORD_MODEL (dh_keyword_model_get_type ())
+#define DH_KEYWORD_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DH_TYPE_KEYWORD_MODEL, DhKeywordModel))
+#define DH_KEYWORD_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DH_TYPE_KEYWORD_MODEL, DhKeywordModelClass))
+#define DH_IS_KEYWORD_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DH_TYPE_KEYWORD_MODEL))
+#define DH_IS_KEYWORD_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DH_TYPE_KEYWORD_MODEL))
+#define DH_KEYWORD_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DH_TYPE_KEYWORD_MODEL, DhKeywordModelClass))
+
+typedef struct _DhKeywordModel DhKeywordModel;
+typedef struct _DhKeywordModelClass DhKeywordModelClass;
+typedef struct _DhKeywordModelPriv DhKeywordModelPriv;
+
+struct _DhKeywordModel
+{
+ GObject parent_instance;
+ DhKeywordModelPriv *priv;
+};
+
+struct _DhKeywordModelClass
+{
+ GObjectClass parent_class;
+};
+
+enum {
+ DH_KEYWORD_MODEL_COL_NAME,
+ DH_KEYWORD_MODEL_COL_LINK,
+ DH_KEYWORD_MODEL_NUM_COLS
+};
+
+GType dh_keyword_model_get_type (void);
+DhKeywordModel *dh_keyword_model_new (void);
+void dh_keyword_model_set_words (DhKeywordModel *model,
+ DhBookManager *book_manager);
+DhLink * dh_keyword_model_filter (DhKeywordModel *model,
+ const gchar *string,
+ const gchar *book_id);
+
+G_END_DECLS
+
+#endif /* __DH_KEYWORD_MODEL_H__ */
Modified: devhelp/devhelp/dh-link.c
291 files changed, 291 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,291 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2001-2002 Mikael Hallendal
+ * 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
+#include
+#include
+#include "dh-link.h"
+
+struct _DhLink {
+ /* FIXME: Those two could exist only for book to save some
+ * memory.
+ */
+ gchar *id;
+ gchar *base;
+
+ gchar *name;
+ gchar *filename;
+
+ DhLink *book;
+ DhLink *page;
+
+ guint ref_count;
+
+ DhLinkType type : 8;
+ DhLinkFlags flags : 8;
+};
+
+GType
+dh_link_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ type = g_boxed_type_register_static (
+ "DhLink",
+ (GBoxedCopyFunc) dh_link_ref,
+ (GBoxedFreeFunc) dh_link_unref);
+ }
+ return type;
+}
+
+static void
+link_free (DhLink *link)
+{
+ g_free (link->base);
+ g_free (link->id);
+ g_free (link->name);
+ g_free (link->filename);
+
+ if (link->book) {
+ dh_link_unref (link->book);
+ }
+ if (link->page) {
+ dh_link_unref (link->page);
+ }
+
+ g_slice_free (DhLink, link);
+}
+
+DhLink *
+dh_link_new (DhLinkType type,
+ const gchar *base,
+ const gchar *id,
+ const gchar *name,
+ DhLink *book,
+ DhLink *page,
+ const gchar *filename)
+{
+ DhLink *link;
+
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ if (type == DH_LINK_TYPE_BOOK) {
+ g_return_val_if_fail (base != NULL, NULL);
+ g_return_val_if_fail (id != NULL, NULL);
+ }
+ if (type != DH_LINK_TYPE_BOOK && type != DH_LINK_TYPE_PAGE) {
+ g_return_val_if_fail (book != NULL, NULL);
+ g_return_val_if_fail (page != NULL, NULL);
+ }
+
+ link = g_slice_new0 (DhLink);
+
+ link->ref_count = 1;
+ link->type = type;
+
+ if (type == DH_LINK_TYPE_BOOK) {
+ link->base = g_strdup (base);
+ link->id = g_strdup (id);
+ }
+
+ link->name = g_strdup (name);
+ link->filename = g_strdup (filename);
+
+ if (book) {
+ link->book = dh_link_ref (book);
+ }
+ if (page) {
+ link->page = dh_link_ref (page);
+ }
+
+ return link;
+}
+
+gint
+dh_link_compare (gconstpointer a,
+ gconstpointer b)
+{
+ DhLink *la = (DhLink *) a;
+ DhLink *lb = (DhLink *) b;
+ gint flags_diff;
+
+ /* Sort deprecated hits last. */
+ flags_diff = (la->flags & DH_LINK_FLAGS_DEPRECATED) -
+ (lb->flags & DH_LINK_FLAGS_DEPRECATED);
+ if (flags_diff != 0) {
+ return flags_diff;
+ }
+
+ return strcmp (la->name, lb->name);
+}
+
+DhLink *
+dh_link_ref (DhLink *link)
+{
+ g_return_val_if_fail (link != NULL, NULL);
+
+ link->ref_count++;
+
+ return link;
+}
+
+void
+dh_link_unref (DhLink *link)
+{
+ g_return_if_fail (link != NULL);
+
+ link->ref_count--;
+
+ if (link->ref_count == 0) {
+ link_free (link);
+ }
+}
+
+const gchar *
+dh_link_get_name (DhLink *link)
+{
+ return link->name;
+}
+
+const gchar *
+dh_link_get_book_name (DhLink *link)
+{
+ if (link->book) {
+ return link->book->name;
+ }
+
+ return "";
+}
+
+const gchar *
+dh_link_get_page_name (DhLink *link)
+{
+ if (link->page) {
+ return link->page->name;
+ }
+
+ return "";
+}
+
+const gchar *
+dh_link_get_file_name (DhLink *link)
+{
+ if (link->page) {
+ return link->filename;
+ }
+
+ return "";
+}
+
+const gchar *
+dh_link_get_book_id (DhLink *link)
+{
+ if (link->type == DH_LINK_TYPE_BOOK) {
+ return link->id;
+ }
+
+ if (link->book) {
+ return link->book->id;
+ }
+
+ return "";
+}
+
+gchar *
+dh_link_get_uri (DhLink *link)
+{
+ gchar *base, *uri;
+
+ if (link->type == DH_LINK_TYPE_BOOK)
+ base = link->base;
+ else
+ base = link->book->base;
+
+ uri = g_strconcat ("file://", base, "/", link->filename, NULL, NULL);
+
+ return uri;
+}
+
+DhLinkType
+dh_link_get_link_type (DhLink *link)
+{
+ return link->type;
+}
+
+DhLinkFlags
+dh_link_get_flags (DhLink *link)
+{
+ return link->flags;
+}
+
+void
+dh_link_set_flags (DhLink *link,
+ DhLinkFlags flags)
+{
+ link->flags = flags;
+}
+
+const gchar *
+dh_link_get_type_as_string (DhLink *link)
+{
+ switch (link->type) {
+ case DH_LINK_TYPE_BOOK:
+ /* i18n: a documentation book */
+ return _("Book");
+ case DH_LINK_TYPE_PAGE:
+ /* i18n: a "page" in a documentation book */
+ return _("Page");
+ case DH_LINK_TYPE_KEYWORD:
+ /* i18n: a search hit in the documentation, could be a
+ * function, macro, struct, etc */
+ return _("Keyword");
+ case DH_LINK_TYPE_FUNCTION:
+ /* i18n: in the programming language context, if you don't
+ * have an ESTABLISHED term for it, leave it
+ * untranslated. */
+ return _("Function");
+ case DH_LINK_TYPE_STRUCT:
+ /* i18n: in the programming language context, if you don't
+ * have an ESTABLISHED term for it, leave it
+ * untranslated. */
+ return _("Struct");
+ case DH_LINK_TYPE_MACRO:
+ /* i18n: in the programming language context, if you don't
+ * have an ESTABLISHED term for it, leave it
+ * untranslated. */
+ return _("Macro");
+ case DH_LINK_TYPE_ENUM:
+ /* i18n: in the programming language context, if you don't
+ * have an ESTABLISHED term for it, leave it
+ * untranslated. */
+ return _("Enum");
+ case DH_LINK_TYPE_TYPEDEF:
+ /* i18n: in the programming language context, if you don't
+ * have an ESTABLISHED term for it, leave it
+ * untranslated. */
+ return _("Type");
+ }
+
+ return "";
+}
Modified: devhelp/devhelp/dh-link.h
72 files changed, 72 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,72 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2002 Mikael Hallendal
+ * 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_LINK_H__
+#define __DH_LINK_H__
+
+#include
+
+typedef enum {
+ DH_LINK_TYPE_BOOK,
+ DH_LINK_TYPE_PAGE,
+ DH_LINK_TYPE_KEYWORD,
+ DH_LINK_TYPE_FUNCTION,
+ DH_LINK_TYPE_STRUCT,
+ DH_LINK_TYPE_MACRO,
+ DH_LINK_TYPE_ENUM,
+ DH_LINK_TYPE_TYPEDEF
+} DhLinkType;
+
+typedef enum {
+ DH_LINK_FLAGS_NONE = 0,
+ DH_LINK_FLAGS_DEPRECATED = 1 << 0
+} DhLinkFlags;
+
+typedef struct _DhLink DhLink;
+
+#define DH_TYPE_LINK (dh_link_get_type ())
+
+GType dh_link_get_type (void);
+DhLink * dh_link_new (DhLinkType type,
+ const gchar *base,
+ const gchar *id,
+ const gchar *name,
+ DhLink *book,
+ DhLink *page,
+ const gchar *filename);
+void dh_link_free (DhLink *link);
+gint dh_link_compare (gconstpointer a,
+ gconstpointer b);
+DhLink * dh_link_ref (DhLink *link);
+void dh_link_unref (DhLink *link);
+const gchar *dh_link_get_name (DhLink *link);
+const gchar *dh_link_get_book_name (DhLink *link);
+const gchar *dh_link_get_page_name (DhLink *link);
+const gchar *dh_link_get_file_name (DhLink *link);
+const gchar *dh_link_get_book_id (DhLink *link);
+gchar *dh_link_get_uri (DhLink *link);
+DhLinkFlags dh_link_get_flags (DhLink *link);
+void dh_link_set_flags (DhLink *link,
+ DhLinkFlags flags);
+DhLinkType dh_link_get_link_type (DhLink *link);
+const gchar *dh_link_get_type_as_string (DhLink *link);
+
+#endif /* __DH_LINK_H__ */
Modified: devhelp/devhelp/dh-marshal.c
148 files changed, 148 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,148 @@
+#include "dh-marshal.h"
+
+#include
+
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v) g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v) g_value_get_int (v)
+#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
+#define g_marshal_value_peek_long(v) g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
+#define g_marshal_value_peek_float(v) g_value_get_float (v)
+#define g_marshal_value_peek_double(v) g_value_get_double (v)
+#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v) g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v) g_value_get_object (v)
+#define g_marshal_value_peek_variant(v) g_value_get_variant (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ * Do not access GValues directly in your code. Instead, use the
+ * g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
+#define g_marshal_value_peek_char(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v) (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v) (v)->data[0].v_float
+#define g_marshal_value_peek_double(v) (v)->data[0].v_double
+#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* VOID:BOOLEAN (dh-marshal.list:1) */
+
+/* VOID:POINTER (dh-marshal.list:2) */
+
+/* VOID:STRING (dh-marshal.list:3) */
+
+/* VOID:VOID (dh-marshal.list:4) */
+
+/* BOOLEAN:STRING (dh-marshal.list:5) */
+void
+_dh_marshal_BOOLEAN__STRING (GClosure *closure,
+ GValue *return_value G_GNUC_UNUSED,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint G_GNUC_UNUSED,
+ gpointer marshal_data)
+{
+ typedef gboolean (*GMarshalFunc_BOOLEAN__STRING) (gpointer data1,
+ gpointer arg_1,
+ gpointer data2);
+ register GMarshalFunc_BOOLEAN__STRING callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+ gboolean v_return;
+
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 2);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_BOOLEAN__STRING) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ g_marshal_value_peek_string (param_values + 1),
+ data2);
+
+ g_value_set_boolean (return_value, v_return);
+}
+
+/* VOID:STRING,FLAGS (dh-marshal.list:6) */
+void
+_dh_marshal_VOID__STRING_FLAGS (GClosure *closure,
+ GValue *return_value G_GNUC_UNUSED,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint G_GNUC_UNUSED,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__STRING_FLAGS) (gpointer data1,
+ gpointer arg_1,
+ guint arg_2,
+ gpointer data2);
+ register GMarshalFunc_VOID__STRING_FLAGS callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__STRING_FLAGS) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_string (param_values + 1),
+ g_marshal_value_peek_flags (param_values + 2),
+ data2);
+}
+
+/* VOID:BOOLEAN (dh-marshal.list:1) */
+
+/* VOID:POINTER (dh-marshal.list:2) */
+
+/* VOID:STRING (dh-marshal.list:3) */
+
+/* VOID:VOID (dh-marshal.list:4) */
+
+/* BOOLEAN:STRING (dh-marshal.list:5) */
+
+/* VOID:STRING,FLAGS (dh-marshal.list:6) */
+
Modified: devhelp/devhelp/dh-marshal.h
52 files changed, 52 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,52 @@
+
+#ifndef ___dh_marshal_MARSHAL_H__
+#define ___dh_marshal_MARSHAL_H__
+
+#include
+
+G_BEGIN_DECLS
+
+/* VOID:BOOLEAN (dh-marshal.list:1) */
+#define _dh_marshal_VOID__BOOLEAN g_cclosure_marshal_VOID__BOOLEAN
+
+/* VOID:POINTER (dh-marshal.list:2) */
+#define _dh_marshal_VOID__POINTER g_cclosure_marshal_VOID__POINTER
+
+/* VOID:STRING (dh-marshal.list:3) */
+#define _dh_marshal_VOID__STRING g_cclosure_marshal_VOID__STRING
+
+/* VOID:VOID (dh-marshal.list:4) */
+#define _dh_marshal_VOID__VOID g_cclosure_marshal_VOID__VOID
+
+/* BOOLEAN:STRING (dh-marshal.list:5) */
+extern void _dh_marshal_BOOLEAN__STRING (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* VOID:STRING,FLAGS (dh-marshal.list:6) */
+extern void _dh_marshal_VOID__STRING_FLAGS (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* VOID:BOOLEAN (dh-marshal.list:1) */
+
+/* VOID:POINTER (dh-marshal.list:2) */
+
+/* VOID:STRING (dh-marshal.list:3) */
+
+/* VOID:VOID (dh-marshal.list:4) */
+
+/* BOOLEAN:STRING (dh-marshal.list:5) */
+
+/* VOID:STRING,FLAGS (dh-marshal.list:6) */
+
+G_END_DECLS
+
+#endif /* ___dh_marshal_MARSHAL_H__ */
+
Modified: devhelp/devhelp/dh-marshal.list
6 files changed, 6 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,6 @@
+VOID:BOOLEAN
+VOID:POINTER
+VOID:STRING
+VOID:VOID
+BOOLEAN:STRING
+VOID:STRING,FLAGS
Modified: devhelp/devhelp/dh-parser.c
611 files changed, 611 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,611 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (c) 2002-2003 Mikael Hallendal
+ * Copyright (c) 2002-2003 CodeFactory AB
+ * Copyright (C) 2005,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
+#include
+#include
+#include
+
+#include "dh-error.h"
+#include "dh-link.h"
+#include "dh-parser.h"
+
+#define NAMESPACE "http://www.devhelp.net/book"
+#define BYTES_PER_READ 4096
+
+typedef struct {
+ GMarkupParser *m_parser;
+ GMarkupParseContext *context;
+
+ const gchar *path;
+
+ /* Top node of book */
+ GNode *book_node;
+
+ /* Current sub section node */
+ GNode *parent;
+
+ gboolean parsing_chapters;
+ gboolean parsing_keywords;
+
+ GNode **book_tree;
+ GList **keywords;
+
+ /* Version 2 uses instead of . */
+ gint version;
+} DhParser;
+
+static void
+dh_parser_free (DhParser *parser)
+{
+ // NOTE: priv->book_tree and priv->keywords do not need to be freed
+ // because they're only used to store the locations for the return
+ // params of dh_parser_read_file()
+
+ g_markup_parse_context_free (parser->context);
+ g_free (parser->m_parser);
+ g_free (parser);
+}
+
+static void
+parser_start_node_book (DhParser *parser,
+ GMarkupParseContext *context,
+ const gchar *node_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ GError **error)
+{
+ gint i, j;
+ gint line, col;
+ gchar *title = NULL;
+ gchar *base = NULL;
+ const gchar *name = NULL;
+ const gchar *uri = NULL;
+ DhLink *link;
+
+ if (g_ascii_strcasecmp (node_name, "book") != 0) {
+ g_markup_parse_context_get_position (context, &line, &col);
+ g_set_error (error,
+ DH_ERROR,
+ DH_ERROR_MALFORMED_BOOK,
+ _("Expected '%s', got '%s' at line %d, column %d"),
+ "book", node_name, line, col);
+ return;
+ }
+
+ for (i = 0; attribute_names[i]; ++i) {
+ const gchar *xmlns;
+
+ if (g_ascii_strcasecmp (attribute_names[i], "xmlns") == 0) {
+ xmlns = attribute_values[i];
+ if (g_ascii_strcasecmp (xmlns, NAMESPACE) != 0) {
+ g_markup_parse_context_get_position (context,
+ &line,
+ &col);
+ g_set_error (error,
+ DH_ERROR,
+ DH_ERROR_MALFORMED_BOOK,
+ _("Invalid namespace '%s' at"
+ " line %d, column %d"),
+ xmlns, line, col);
+ return;
+ }
+ }
+ else if (g_ascii_strcasecmp (attribute_names[i], "name") == 0) {
+ name = attribute_values[i];
+ }
+ else if (g_ascii_strcasecmp (attribute_names[i], "title") == 0) {
+ title = g_strdup(attribute_values[i]);
+ for (j = 0; title[j]; j++) {
+ if (title[j] == '\n') title[j] = ' ';
+ }
+ }
+ else if (g_ascii_strcasecmp (attribute_names[i], "base") == 0) {
+ base = g_strdup (attribute_values[i]);
+ }
+ else if (g_ascii_strcasecmp (attribute_names[i], "link") == 0) {
+ uri = attribute_values[i];
+ }
+ }
+
+ if (!title || !name || !uri) {
+ g_markup_parse_context_get_position (context, &line, &col);
+ g_set_error (error,
+ DH_ERROR,
+ DH_ERROR_MALFORMED_BOOK,
+ _("\"title\", \"name\" and \"link\" elements are "
+ "required at line %d, column %d"),
+ line, col);
+ g_free (title);
+ return;
+ }
+
+ if (!base) {
+ base = g_path_get_dirname (parser->path);
+ }
+
+ link = dh_link_new (DH_LINK_TYPE_BOOK,
+ base,
+ name,
+ title,
+ NULL,
+ NULL,
+ uri);
+ g_free (base);
+
+ *parser->keywords = g_list_prepend (*parser->keywords, dh_link_ref (link));
+
+ parser->book_node = g_node_new (dh_link_ref (link));
+ *parser->book_tree = parser->book_node;
+ parser->parent = parser->book_node;
+ g_free (title);
+ dh_link_unref (link);
+}
+
+static void
+parser_start_node_chapter (DhParser *parser,
+ GMarkupParseContext *context,
+ const gchar *node_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ GError **error)
+{
+ gint i;
+ gint line, col;
+ const gchar *name = NULL;
+ const gchar *uri = NULL;
+ DhLink *link;
+ GNode *node;
+
+ if (g_ascii_strcasecmp (node_name, "sub") != 0) {
+ g_markup_parse_context_get_position (context, &line, &col);
+ g_set_error (error,
+ DH_ERROR,
+ DH_ERROR_MALFORMED_BOOK,
+ _("Expected '%s', got '%s' at line %d, column %d"),
+ "sub", node_name, line, col);
+ return;
+ }
+
+ for (i = 0; attribute_names[i]; ++i) {
+ if (g_ascii_strcasecmp (attribute_names[i], "name") == 0) {
+ name = attribute_values[i];
+ }
+ else if (g_ascii_strcasecmp (attribute_names[i], "link") == 0) {
+ uri = attribute_values[i];
+ }
+ }
+
+ if (!name || !uri) {
+ g_markup_parse_context_get_position (context, &line, &col);
+ g_set_error (error,
+ DH_ERROR,
+ DH_ERROR_MALFORMED_BOOK,
+ _("\"name\" and \"link\" elements are required "
+ "inside on line %d, column %d"),
+ line, col);
+ return;
+ }
+
+ link = dh_link_new (DH_LINK_TYPE_PAGE,
+ NULL,
+ NULL,
+ name,
+ parser->book_node->data,
+ NULL,
+ uri);
+
+ *parser->keywords = g_list_prepend (*parser->keywords, link);
+
+ node = g_node_new (link);
+ g_node_prepend (parser->parent, node);
+ parser->parent = node;
+}
+
+static void
+parser_start_node_keyword (DhParser *parser,
+ GMarkupParseContext *context,
+ const gchar *node_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ GError **error)
+{
+ gint i;
+ gint line, col;
+ const gchar *name = NULL;
+ const gchar *uri = NULL;
+ const gchar *type = NULL;
+ const gchar *deprecated = NULL;
+ DhLinkType link_type;
+ DhLink *link;
+ gchar *tmp;
+
+ if (parser->version == 2 &&
+ g_ascii_strcasecmp (node_name, "keyword") != 0) {
+ g_markup_parse_context_get_position (context, &line, &col);
+ g_set_error (error,
+ DH_ERROR,
+ DH_ERROR_MALFORMED_BOOK,
+ _("Expected '%s', got '%s' at line %d, column %d"),
+ "keyword", node_name, line, col);
+ return;
+ }
+ else if (parser->version == 1 &&
+ g_ascii_strcasecmp (node_name, "function") != 0) {
+ g_markup_parse_context_get_position (context, &line, &col);
+ g_set_error (error,
+ DH_ERROR,
+ DH_ERROR_MALFORMED_BOOK,
+ _("Expected '%s', got '%s' at line %d, column %d"),
+ "function", node_name, line, col);
+ return;
+ }
+
+ for (i = 0; attribute_names[i]; ++i) {
+ if (g_ascii_strcasecmp (attribute_names[i], "type") == 0) {
+ type = attribute_values[i];
+ }
+ else if (g_ascii_strcasecmp (attribute_names[i], "name") == 0) {
+ name = attribute_values[i];
+ }
+ else if (g_ascii_strcasecmp (attribute_names[i], "link") == 0) {
+ uri = attribute_values[i];
+ }
+ else if (g_ascii_strcasecmp (attribute_names[i], "deprecated") == 0) {
+ deprecated = attribute_values[i];
+ }
+ }
+
+ if (!name || !uri) {
+ g_markup_parse_context_get_position (context, &line, &col);
+ g_set_error (error,
+ DH_ERROR,
+ DH_ERROR_MALFORMED_BOOK,
+ _("\"name\" and \"link\" elements are required "
+ "inside '%s' on line %d, column %d"),
+ parser->version == 2 ? "keyword" : "function",
+ line, col);
+ return;
+ }
+
+ if (parser->version == 2 && !type) {
+ /* Required */
+ g_markup_parse_context_get_position (context, &line, &col);
+ g_set_error (error,
+ DH_ERROR,
+ DH_ERROR_MALFORMED_BOOK,
+ _("\"type\" element is required "
+ "inside on line %d, column %d"),
+ line, col);
+ return;
+ }
+
+ if (parser->version == 2) {
+ if (strcmp (type, "function") == 0) {
+ link_type = DH_LINK_TYPE_FUNCTION;
+ }
+ else if (strcmp (type, "struct") == 0) {
+ link_type = DH_LINK_TYPE_STRUCT;
+ }
+ else if (strcmp (type, "macro") == 0) {
+ link_type = DH_LINK_TYPE_MACRO;
+ }
+ else if (strcmp (type, "enum") == 0) {
+ link_type = DH_LINK_TYPE_ENUM;
+ }
+ else if (strcmp (type, "typedef") == 0) {
+ link_type = DH_LINK_TYPE_TYPEDEF;
+ } else {
+ link_type = DH_LINK_TYPE_KEYWORD;
+ }
+ } else {
+ link_type = DH_LINK_TYPE_KEYWORD;
+ }
+
+ /* Strip out trailing " () or "()". */
+ if (g_str_has_suffix (name, " ()")) {
+ tmp = g_strndup (name, strlen (name) - 3);
+
+ if (link_type == DH_LINK_TYPE_KEYWORD) {
+ link_type = DH_LINK_TYPE_FUNCTION;
+ }
+ name = tmp;
+ }
+ else if (g_str_has_suffix (name, "()")) {
+ tmp = g_strndup (name, strlen (name) - 2);
+
+ /* With old devhelp format, take a guess that this is a
+ * macro.
+ */
+ if (link_type == DH_LINK_TYPE_KEYWORD) {
+ link_type = DH_LINK_TYPE_MACRO;
+ }
+ name = tmp;
+ } else {
+ tmp = NULL;
+ }
+
+ /* Strip out prefixing "struct", "union", "enum", to make searching
+ * easier. Also fix up the link type (only applies for old devhelp
+ * format).
+ */
+ if (g_str_has_prefix (name, "struct ")) {
+ name = name + 7;
+ if (link_type == DH_LINK_TYPE_KEYWORD) {
+ link_type = DH_LINK_TYPE_STRUCT;
+ }
+ }
+ else if (g_str_has_prefix (name, "union ")) {
+ name = name + 6;
+ if (link_type == DH_LINK_TYPE_KEYWORD) {
+ link_type = DH_LINK_TYPE_STRUCT;
+ }
+ }
+ else if (g_str_has_prefix (name, "enum ")) {
+ name = name + 5;
+ if (link_type == DH_LINK_TYPE_KEYWORD) {
+ link_type = DH_LINK_TYPE_ENUM;
+ }
+ }
+
+ link = dh_link_new (link_type,
+ NULL,
+ NULL,
+ name,
+ parser->book_node->data,
+ parser->parent->data,
+ uri);
+
+ g_free (tmp);
+
+ if (deprecated) {
+ dh_link_set_flags (
+ link,
+ dh_link_get_flags (link) | DH_LINK_FLAGS_DEPRECATED);
+ }
+
+ *parser->keywords = g_list_prepend (*parser->keywords, link);
+}
+
+static void
+parser_start_node_cb (GMarkupParseContext *context,
+ const gchar *node_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data,
+ GError **error)
+{
+ DhParser *parser = user_data;
+
+ if (parser->parsing_keywords) {
+ parser_start_node_keyword (parser,
+ context,
+ node_name,
+ attribute_names,
+ attribute_values,
+ error);
+ return;
+ }
+ else if (parser->parsing_chapters) {
+ parser_start_node_chapter (parser,
+ context,
+ node_name,
+ attribute_names,
+ attribute_values,
+ error);
+ return;
+ }
+ else if (g_ascii_strcasecmp (node_name, "functions") == 0) {
+ parser->parsing_keywords = TRUE;
+ }
+ else if (g_ascii_strcasecmp (node_name, "chapters") == 0) {
+ parser->parsing_chapters = TRUE;
+ }
+ if (!parser->book_node) {
+ parser_start_node_book (parser,
+ context,
+ node_name,
+ attribute_names,
+ attribute_values,
+ error);
+ return;
+ }
+}
+
+static void
+parser_end_node_cb (GMarkupParseContext *context,
+ const gchar *node_name,
+ gpointer user_data,
+ GError **error)
+{
+ DhParser *parser = user_data;
+
+ if (parser->parsing_keywords) {
+ if (g_ascii_strcasecmp (node_name, "functions") == 0) {
+ parser->parsing_keywords = FALSE;
+ }
+ }
+ else if (parser->parsing_chapters) {
+ g_node_reverse_children (parser->parent);
+ if (g_ascii_strcasecmp (node_name, "sub") == 0) {
+ parser->parent = parser->parent->parent;
+ /* Move up in the tree */
+ }
+ else if (g_ascii_strcasecmp (node_name, "chapters") == 0) {
+ parser->parsing_chapters = FALSE;
+ }
+ }
+}
+
+static void
+parser_error_cb (GMarkupParseContext *context,
+ GError *error,
+ gpointer user_data)
+{
+ DhParser *parser = user_data;
+
+ g_markup_parse_context_free (parser->context);
+ parser->context = NULL;
+}
+
+static gboolean
+parser_read_gz_file (DhParser *parser,
+ const gchar *path,
+ GError **error)
+{
+ gchar buf[BYTES_PER_READ];
+ gzFile file;
+
+ file = gzopen (path, "r");
+ if (!file) {
+ g_set_error (error,
+ DH_ERROR,
+ DH_ERROR_FILE_NOT_FOUND,
+ "%s", g_strerror (errno));
+ return FALSE;
+ }
+
+ while (TRUE) {
+ gssize bytes_read;
+
+ bytes_read = gzread (file, buf, BYTES_PER_READ);
+ if (bytes_read == -1) {
+ gint err;
+ const gchar *message;
+
+ message = gzerror (file, &err);
+ g_set_error (error,
+ DH_ERROR,
+ DH_ERROR_INTERNAL_ERROR,
+ _("Cannot uncompress book '%s': %s"),
+ path, message);
+ return FALSE;
+ }
+
+ g_markup_parse_context_parse (parser->context, buf,
+ bytes_read, error);
+ if (error != NULL && *error != NULL) {
+ return FALSE;
+ }
+ if (bytes_read < BYTES_PER_READ) {
+ break;
+ }
+ }
+
+ gzclose (file);
+
+ return TRUE;
+}
+
+gboolean
+dh_parser_read_file (const gchar *path,
+ GNode **book_tree,
+ GList **keywords,
+ GError **error)
+{
+ DhParser *parser;
+ gboolean gz;
+ GIOChannel *io = NULL;
+ gchar buf[BYTES_PER_READ];
+ gboolean result = TRUE;
+
+ parser = g_new0 (DhParser, 1);
+
+ if (g_str_has_suffix (path, ".devhelp2")) {
+ parser->version = 2;
+ gz = FALSE;
+ }
+ else if (g_str_has_suffix (path, ".devhelp")) {
+ parser->version = 1;
+ gz = FALSE;
+ }
+ else if (g_str_has_suffix (path, ".devhelp2.gz")) {
+ parser->version = 2;
+ gz = TRUE;
+ } else {
+ parser->version = 1;
+ gz = TRUE;
+ }
+
+ parser->m_parser = g_new0 (GMarkupParser, 1);
+
+ parser->m_parser->start_element = parser_start_node_cb;
+ parser->m_parser->end_element = parser_end_node_cb;
+ parser->m_parser->error = parser_error_cb;
+
+ parser->context = g_markup_parse_context_new (parser->m_parser, 0,
+ parser, NULL);
+
+ parser->path = path;
+ parser->book_tree = book_tree;
+ parser->keywords = keywords;
+
+ if (gz) {
+ if (!parser_read_gz_file (parser,
+ path,
+ error)) {
+ result = FALSE;
+ }
+ goto exit;
+ } else {
+ io = g_io_channel_new_file (path, "r", error);
+ if (!io) {
+ result = FALSE;
+ goto exit;
+ }
+
+ while (TRUE) {
+ GIOStatus io_status;
+ gsize bytes_read;
+
+ io_status = g_io_channel_read_chars (io, buf, BYTES_PER_READ,
+ &bytes_read, error);
+ if (io_status == G_IO_STATUS_ERROR) {
+ result = FALSE;
+ goto exit;
+ }
+ if (io_status != G_IO_STATUS_NORMAL) {
+ break;
+ }
+
+ g_markup_parse_context_parse (parser->context, buf,
+ bytes_read, error);
+ if (error != NULL && *error != NULL) {
+ result = FALSE;
+ goto exit;
+ }
+
+ if (bytes_read < BYTES_PER_READ) {
+ break;
+ }
+ }
+ }
+
+ exit:
+ if (io) {
+ g_io_channel_unref (io);
+ }
+ dh_parser_free (parser);
+
+ return result;
+}
Modified: devhelp/devhelp/dh-parser.h
36 files changed, 36 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2003 CodeFactory AB
+ * Copyright (C) 2003 Mikael Hallendal
+ *
+ * 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_PARSER_H__
+#define __DH_PARSER_H__
+
+#include
+
+G_BEGIN_DECLS
+
+gboolean dh_parser_read_file (const gchar *path,
+ GNode **book_tree,
+ GList **keywords,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __DH_PARSER_H__ */
Modified: devhelp/devhelp/dh-preferences.c
417 files changed, 417 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,417 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2004-2008 Imendio AB
+ * Copyright (C) 2010 Lanedo GmbH
+ *
+ * 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
+#include
+#include "dh-util.h"
+#include "dh-preferences.h"
+#include "ige-conf.h"
+#include "dh-base.h"
+
+typedef struct {
+ GtkWidget *dialog;
+
+ /* Fonts tab */
+ GtkWidget *system_fonts_button;
+ GtkWidget *fonts_table;
+ GtkWidget *variable_font_button;
+ GtkWidget *fixed_font_button;
+ guint use_system_fonts_id;
+ guint system_var_id;
+ guint system_fixed_id;
+ guint var_id;
+ guint fixed_id;
+
+ /* Book Shelf tab */
+ DhBookManager *book_manager;
+ GtkTreeView *booklist_treeview;
+ GtkListStore *booklist_store;
+} DhPreferences;
+
+/* Fonts-tab related */
+static void preferences_fonts_font_set_cb (GtkFontButton *button,
+ gpointer user_data);
+static void preferences_fonts_system_fonts_toggled_cb (GtkToggleButton *button,
+ gpointer user_data);
+#if 0
+static void preferences_fonts_var_font_notify_cb (IgeConf *client,
+ const gchar *path,
+ gpointer user_data);
+static void preferences_fonts_fixed_font_notify_cb (IgeConf *client,
+ const gchar *path,
+ gpointer user_data);
+static void preferences_fonts_use_system_font_notify_cb (IgeConf *client,
+ const gchar *path,
+ gpointer user_data);
+static void preferences_connect_conf_listeners (void);
+#endif
+static void preferences_fonts_get_font_names (gboolean use_system_fonts,
+ gchar **variable,
+ gchar **fixed);
+
+/* Bookshelf-tab related */
+static void preferences_bookshelf_tree_selection_toggled_cb (GtkCellRendererToggle *cell_renderer,
+ gchar *path,
+ gpointer user_data);
+static void preferences_bookshelf_populate_store (void);
+
+/* Common */
+static void preferences_close_cb (GtkButton *button,
+ gpointer user_data);
+
+#define DH_CONF_PATH "/apps/devhelp"
+#define DH_CONF_USE_SYSTEM_FONTS DH_CONF_PATH "/ui/use_system_fonts"
+#define DH_CONF_VARIABLE_FONT DH_CONF_PATH "/ui/variable_font"
+#define DH_CONF_FIXED_FONT DH_CONF_PATH "/ui/fixed_font"
+#define DH_CONF_SYSTEM_VARIABLE_FONT "/desktop/gnome/interface/font_name"
+#define DH_CONF_SYSTEM_FIXED_FONT "/desktop/gnome/interface/monospace_font_name"
+
+/* Book list store columns... */
+#define LTCOLUMN_ENABLED 0
+#define LTCOLUMN_TITLE 1
+#define LTCOLUMN_BOOK 2
+
+static DhPreferences *prefs;
+
+static void
+preferences_init (void)
+{
+ if (!prefs) {
+ prefs = g_new0 (DhPreferences, 1);
+ prefs->book_manager = dh_base_get_book_manager (dh_base_get ());
+ }
+}
+
+static void
+preferences_close_cb (GtkButton *button, gpointer user_data)
+{
+ DhPreferences *prefs = user_data;
+
+ gtk_widget_destroy (GTK_WIDGET (prefs->dialog));
+ prefs->dialog = NULL;
+
+ prefs->system_fonts_button = NULL;
+ prefs->fonts_table = NULL;
+ prefs->variable_font_button = NULL;
+ prefs->fixed_font_button = NULL;
+
+ prefs->booklist_treeview = NULL;
+ prefs->booklist_store = NULL;
+}
+
+static void
+preferences_fonts_font_set_cb (GtkFontButton *button,
+ gpointer user_data)
+{
+ DhPreferences *prefs = user_data;
+ const gchar *font_name;
+ const gchar *key;
+
+ font_name = gtk_font_button_get_font_name (button);
+
+ if (GTK_WIDGET (button) == prefs->variable_font_button) {
+ key = DH_CONF_VARIABLE_FONT;
+ } else {
+ key = DH_CONF_FIXED_FONT;
+ }
+
+ ige_conf_set_string (ige_conf_get (), key, font_name);
+}
+
+static void
+preferences_fonts_system_fonts_toggled_cb (GtkToggleButton *button,
+ gpointer user_data)
+{
+ DhPreferences *prefs = user_data;
+ gboolean active;
+
+ active = gtk_toggle_button_get_active (button);
+
+ ige_conf_set_bool (ige_conf_get (),
+ DH_CONF_USE_SYSTEM_FONTS,
+ active);
+
+ gtk_widget_set_sensitive (prefs->fonts_table, !active);
+}
+
+#if 0
+static void
+preferences_fonts_var_font_notify_cb (IgeConf *client,
+ const gchar *path,
+ gpointer user_data)
+{
+ DhPreferences *prefs = user_data;
+ gboolean use_system_fonts;
+ gchar *font_name;
+
+ ige_conf_get_bool (ige_conf_get (),
+ DH_CONF_USE_SYSTEM_FONTS,
+ &use_system_fonts);
+
+ if (prefs->variable_font_button) {
+ ige_conf_get_string (ige_conf_get (), path, &font_name);
+ gtk_font_button_set_font_name (GTK_FONT_BUTTON (prefs->variable_font_button),
+ font_name);
+ g_free (font_name);
+ }
+}
+
+static void
+preferences_fonts_fixed_font_notify_cb (IgeConf *client,
+ const gchar *path,
+ gpointer user_data)
+{
+ DhPreferences *prefs = user_data;
+ gboolean use_system_fonts;
+ gchar *font_name;
+
+ ige_conf_get_bool (ige_conf_get (),
+ DH_CONF_USE_SYSTEM_FONTS,
+ &use_system_fonts);
+
+ if (prefs->fixed_font_button) {
+ ige_conf_get_string (ige_conf_get (), path, &font_name);
+ gtk_font_button_set_font_name (GTK_FONT_BUTTON (prefs->fixed_font_button),
+ font_name);
+ g_free (font_name);
+ }
+}
+
+static void
+preferences_fonts_use_system_font_notify_cb (IgeConf *client,
+ const gchar *path,
+ gpointer user_data)
+{
+ DhPreferences *prefs = user_data;
+ gboolean use_system_fonts;
+
+ ige_conf_get_bool (ige_conf_get (), path, &use_system_fonts);
+
+ if (prefs->system_fonts_button) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (prefs->system_fonts_button),
+ use_system_fonts);
+ }
+
+ if (prefs->fonts_table) {
+ gtk_widget_set_sensitive (prefs->fonts_table, !use_system_fonts);
+ }
+}
+
+/* FIXME: This is not hooked up yet (to update the dialog if the values are
+ * changed outside of devhelp).
+ */
+static void
+preferences_connect_conf_listeners (void)
+{
+ IgeConf *conf;
+
+ conf = ige_conf_get ();
+
+ prefs->use_system_fonts_id =
+ ige_conf_notify_add (conf,
+ DH_CONF_USE_SYSTEM_FONTS,
+ preferences_use_system_font_notify_cb,
+ prefs);
+ prefs->system_var_id =
+ ige_conf_notify_add (conf,
+ DH_CONF_SYSTEM_VARIABLE_FONT,
+ preferences_var_font_notify_cb,
+ prefs);
+ prefs->system_fixed_id =
+ ige_conf_notify_add (conf,
+ DH_CONF_SYSTEM_FIXED_FONT,
+ preferences_fixed_font_notify_cb,
+ prefs);
+ prefs->var_id =
+ ige_conf_notify_add (conf,
+ DH_CONF_VARIABLE_FONT,
+ preferences_var_font_notify_cb,
+ prefs);
+ prefs->fixed_id =
+ ige_conf_notify_add (conf,
+ DH_CONF_FIXED_FONT,
+ preferences_fixed_font_notify_cb,
+ prefs);
+}
+#endif
+
+/* FIXME: Use the functions in dh-util.c for this. */
+static void
+preferences_fonts_get_font_names (gboolean use_system_fonts,
+ gchar **variable,
+ gchar **fixed)
+{
+ gchar *var_font_name, *fixed_font_name;
+ IgeConf *conf;
+
+ conf = ige_conf_get ();
+
+ if (use_system_fonts) {
+#ifdef GDK_WINDOWING_QUARTZ
+ var_font_name = g_strdup ("Lucida Grande 14");
+ fixed_font_name = g_strdup ("Monaco 14");
+#else
+ ige_conf_get_string (conf,
+ DH_CONF_SYSTEM_VARIABLE_FONT,
+ &var_font_name);
+ ige_conf_get_string (conf,
+ DH_CONF_SYSTEM_FIXED_FONT,
+ &fixed_font_name);
+#endif
+ } else {
+ ige_conf_get_string (conf,
+ DH_CONF_VARIABLE_FONT,
+ &var_font_name);
+ ige_conf_get_string (conf,
+ DH_CONF_FIXED_FONT,
+ &fixed_font_name);
+ }
+
+ *variable = var_font_name;
+ *fixed = fixed_font_name;
+}
+
+static void
+preferences_bookshelf_tree_selection_toggled_cb (GtkCellRendererToggle *cell_renderer,
+ gchar *path,
+ gpointer user_data)
+{
+ GtkTreeIter iter;
+
+ if (gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (prefs->booklist_store),
+ &iter,
+ path))
+ {
+ gpointer book = NULL;
+ gboolean enabled;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (prefs->booklist_store),
+ &iter,
+ LTCOLUMN_BOOK, &book,
+ LTCOLUMN_ENABLED, &enabled,
+ -1);
+
+ if (book) {
+ /* Update book conf */
+ dh_book_set_enabled (book, !enabled);
+
+ gtk_list_store_set (prefs->booklist_store, &iter,
+ LTCOLUMN_ENABLED, !enabled,
+ -1);
+
+ dh_book_manager_update (prefs->book_manager);
+ }
+ }
+}
+
+static void
+preferences_bookshelf_populate_store (void)
+{
+ GList *l;
+
+ for (l = dh_book_manager_get_books (prefs->book_manager);
+ l;
+ l = g_list_next (l)) {
+ GtkTreeIter iter;
+ DhBook *book;
+
+ book = DH_BOOK (l->data);
+
+ gtk_list_store_append (prefs->booklist_store, &iter);
+ gtk_list_store_set (prefs->booklist_store, &iter,
+ LTCOLUMN_ENABLED, dh_book_get_enabled (book),
+ LTCOLUMN_TITLE, dh_book_get_title (book),
+ LTCOLUMN_BOOK, book,
+ -1);
+ }
+}
+
+void
+dh_preferences_show_dialog (GtkWindow *parent)
+{
+ gchar *path;
+ GtkBuilder *builder;
+ gboolean use_system_fonts;
+ gchar *var_font_name, *fixed_font_name;
+
+ preferences_init ();
+
+ if (prefs->dialog != NULL) {
+ gtk_window_present (GTK_WINDOW (prefs->dialog));
+ return;
+ }
+
+ path = dh_util_build_data_filename ("devhelp", "ui",
+ "devhelp.builder",
+ NULL);
+ builder = dh_util_builder_get_file (
+ path,
+ "preferences_dialog",
+ NULL,
+ "preferences_dialog", &prefs->dialog,
+ "fonts_table", &prefs->fonts_table,
+ "system_fonts_button", &prefs->system_fonts_button,
+ "variable_font_button", &prefs->variable_font_button,
+ "fixed_font_button", &prefs->fixed_font_button,
+ "book_manager_store", &prefs->booklist_store,
+ "book_manager_treeview", &prefs->booklist_treeview,
+ NULL);
+ g_free (path);
+
+ dh_util_builder_connect (
+ builder,
+ prefs,
+ "variable_font_button", "font_set", preferences_fonts_font_set_cb,
+ "fixed_font_button", "font_set", preferences_fonts_font_set_cb,
+ "system_fonts_button", "toggled", preferences_fonts_system_fonts_toggled_cb,
+ "book_manager_toggle", "toggled", preferences_bookshelf_tree_selection_toggled_cb,
+ "preferences_close_button", "clicked", preferences_close_cb,
+ NULL);
+
+ ige_conf_get_bool (ige_conf_get (),
+ DH_CONF_USE_SYSTEM_FONTS,
+ &use_system_fonts);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (prefs->system_fonts_button),
+ use_system_fonts);
+ gtk_widget_set_sensitive (prefs->fonts_table, !use_system_fonts);
+
+ preferences_fonts_get_font_names (FALSE, &var_font_name, &fixed_font_name);
+
+ if (var_font_name) {
+ gtk_font_button_set_font_name (GTK_FONT_BUTTON (prefs->variable_font_button),
+ var_font_name);
+ g_free (var_font_name);
+ }
+
+ if (fixed_font_name) {
+ gtk_font_button_set_font_name (GTK_FONT_BUTTON (prefs->fixed_font_button),
+ fixed_font_name);
+ g_free (fixed_font_name);
+ }
+
+ preferences_bookshelf_populate_store ();
+
+ g_object_unref (builder);
+
+ gtk_window_set_transient_for (GTK_WINDOW (prefs->dialog), parent);
+ gtk_widget_show_all (prefs->dialog);
+}
Modified: devhelp/devhelp/dh-preferences.h
34 files changed, 34 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2004-2008 Imendio AB
+ * Copyright (C) 2010 Lanedo GmbH
+ *
+ * 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_PREFERENCES_H__
+#define __DH_PREFERENCES_H__
+
+#include
+
+G_BEGIN_DECLS
+
+void dh_preferences_show_dialog (GtkWindow *parent);
+
+G_END_DECLS
+
+#endif /* __DH_PREFERENCES_H__ */
+
Modified: devhelp/devhelp/dh-search.c
725 files changed, 725 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,725 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2001-2003 CodeFactory AB
+ * Copyright (C) 2001-2003 Mikael Hallendal
+ * Copyright (C) 2005-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
+#include
+#include
+#include
+#include "dh-marshal.h"
+#include "dh-keyword-model.h"
+#include "dh-search.h"
+#include "dh-preferences.h"
+#include "dh-base.h"
+#include "dh-util.h"
+#include "dh-book-manager.h"
+#include "dh-book.h"
+
+typedef struct {
+ DhKeywordModel *model;
+
+ DhBookManager *book_manager;
+
+ DhLink *selected_link;
+
+ GtkWidget *book_combo;
+ GtkWidget *entry;
+ GtkWidget *hitlist;
+
+ GCompletion *completion;
+
+ guint idle_complete;
+ guint idle_filter;
+} DhSearchPriv;
+
+static void dh_search_init (DhSearch *search);
+static void dh_search_class_init (DhSearchClass *klass);
+static void search_grab_focus (GtkWidget *widget);
+static void search_selection_changed_cb (GtkTreeSelection *selection,
+ DhSearch *content);
+static gboolean search_tree_button_press_cb (GtkTreeView *view,
+ GdkEventButton *event,
+ DhSearch *search);
+static gboolean search_entry_key_press_event_cb (GtkEntry *entry,
+ GdkEventKey *event,
+ DhSearch *search);
+static void search_combo_changed_cb (GtkComboBox *combo,
+ DhSearch *search);
+static void search_entry_changed_cb (GtkEntry *entry,
+ DhSearch *search);
+static void search_entry_activated_cb (GtkEntry *entry,
+ DhSearch *search);
+static void search_entry_text_inserted_cb (GtkEntry *entry,
+ const gchar *text,
+ gint length,
+ gint *position,
+ DhSearch *search);
+static gboolean search_complete_idle (DhSearch *search);
+static gboolean search_filter_idle (DhSearch *search);
+static const gchar *search_complete_func (DhLink *link);
+
+enum {
+ LINK_SELECTED,
+ LAST_SIGNAL
+};
+
+G_DEFINE_TYPE (DhSearch, dh_search, GTK_TYPE_VBOX);
+
+#define GET_PRIVATE(instance) G_TYPE_INSTANCE_GET_PRIVATE \
+ (instance, DH_TYPE_SEARCH, DhSearchPriv);
+
+static gint signals[LAST_SIGNAL] = { 0 };
+
+static void
+search_finalize (GObject *object)
+{
+ DhSearchPriv *priv;
+
+ priv = GET_PRIVATE (object);
+
+ g_completion_free (priv->completion);
+ g_object_unref (priv->book_manager);
+
+ G_OBJECT_CLASS (dh_search_parent_class)->finalize (object);
+}
+
+static void
+dh_search_class_init (DhSearchClass *klass)
+{
+ GObjectClass *object_class = (GObjectClass *) klass;;
+ GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;;
+
+ object_class->finalize = search_finalize;
+
+ widget_class->grab_focus = search_grab_focus;
+
+ signals[LINK_SELECTED] =
+ g_signal_new ("link_selected",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (DhSearchClass, link_selected),
+ NULL, NULL,
+ _dh_marshal_VOID__POINTER,
+ G_TYPE_NONE,
+ 1, G_TYPE_POINTER);
+
+ g_type_class_add_private (klass, sizeof (DhSearchPriv));
+}
+
+static void
+dh_search_init (DhSearch *search)
+{
+ DhSearchPriv *priv = GET_PRIVATE (search);
+
+ priv->completion = g_completion_new (
+ (GCompletionFunc) search_complete_func);
+
+ priv->hitlist = gtk_tree_view_new ();
+ priv->model = dh_keyword_model_new ();
+
+ gtk_tree_view_set_model (GTK_TREE_VIEW (priv->hitlist),
+ GTK_TREE_MODEL (priv->model));
+
+ gtk_tree_view_set_enable_search (GTK_TREE_VIEW (priv->hitlist), FALSE);
+
+ gtk_box_set_spacing (GTK_BOX (search), 4);
+}
+
+static void
+search_grab_focus (GtkWidget *widget)
+{
+ DhSearchPriv *priv = GET_PRIVATE (widget);
+
+ gtk_widget_grab_focus (priv->entry);
+}
+
+static void
+search_selection_changed_cb (GtkTreeSelection *selection,
+ DhSearch *search)
+{
+ DhSearchPriv *priv;
+ GtkTreeIter iter;
+
+ priv = GET_PRIVATE (search);
+
+ if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
+ DhLink *link;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (priv->model), &iter,
+ DH_KEYWORD_MODEL_COL_LINK, &link,
+ -1);
+
+ if (link != priv->selected_link) {
+ priv->selected_link = link;
+ g_signal_emit (search, signals[LINK_SELECTED], 0, link);
+ }
+ }
+}
+
+/* Make it possible to jump back to the currently selected item, useful when the
+ * html view has been scrolled away.
+ */
+static gboolean
+search_tree_button_press_cb (GtkTreeView *view,
+ GdkEventButton *event,
+ DhSearch *search)
+{
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ DhSearchPriv *priv;
+ DhLink *link;
+
+ priv = GET_PRIVATE (search);
+
+ gtk_tree_view_get_path_at_pos (view, event->x, event->y, &path,
+ NULL, NULL, NULL);
+ if (!path) {
+ return FALSE;
+ }
+
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->model), &iter, path);
+ gtk_tree_path_free (path);
+
+ gtk_tree_model_get (GTK_TREE_MODEL (priv->model),
+ &iter,
+ DH_KEYWORD_MODEL_COL_LINK, &link,
+ -1);
+
+ priv->selected_link = link;
+
+ g_signal_emit (search, signals[LINK_SELECTED], 0, link);
+
+ /* Always return FALSE so the tree view gets the event and can update
+ * the selection etc.
+ */
+ return FALSE;
+}
+
+static gboolean
+search_entry_key_press_event_cb (GtkEntry *entry,
+ GdkEventKey *event,
+ DhSearch *search)
+{
+ DhSearchPriv *priv = GET_PRIVATE (search);
+
+ if (event->keyval == GDK_Tab) {
+ if (event->state & GDK_CONTROL_MASK) {
+ gtk_widget_grab_focus (priv->hitlist);
+ } else {
+ gtk_editable_set_position (GTK_EDITABLE (entry), -1);
+ gtk_editable_select_region (GTK_EDITABLE (entry), -1, -1);
+ }
+ return TRUE;
+ }
+
+ if (event->keyval == GDK_Return ||
+ event->keyval == GDK_KP_Enter) {
+ GtkTreeIter iter;
+ DhLink *link;
+ gchar *name;
+
+ /* Get the first entry found. */
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->model), &iter)) {
+ gtk_tree_model_get (GTK_TREE_MODEL (priv->model),
+ &iter,
+ DH_KEYWORD_MODEL_COL_LINK, &link,
+ DH_KEYWORD_MODEL_COL_NAME, &name,
+ -1);
+
+ gtk_entry_set_text (GTK_ENTRY (entry), name);
+ g_free (name);
+
+ gtk_editable_set_position (GTK_EDITABLE (entry), -1);
+ gtk_editable_select_region (GTK_EDITABLE (entry), -1, -1);
+
+ g_signal_emit (search, signals[LINK_SELECTED], 0, link);
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+search_combo_set_active_id (DhSearch *search,
+ const gchar *book_id)
+{
+ DhSearchPriv *priv = GET_PRIVATE (search);
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ gboolean has_next;
+
+ g_signal_handlers_block_by_func (priv->book_combo,
+ search_combo_changed_cb,
+ search);
+
+ if (book_id != NULL) {
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (priv->book_combo));
+
+ has_next = gtk_tree_model_get_iter_first (model, &iter);
+ while (has_next) {
+ gchar *id;
+
+ gtk_tree_model_get (model, &iter,
+ 1, &id,
+ -1);
+
+ if (id && strcmp (book_id, id) == 0) {
+ g_free (id);
+
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->book_combo),
+ &iter);
+ break;
+ }
+
+ g_free (id);
+
+ has_next = gtk_tree_model_iter_next (model, &iter);
+ }
+ } else {
+ gtk_combo_box_set_active (GTK_COMBO_BOX (priv->book_combo), 0);
+ }
+
+ g_signal_handlers_unblock_by_func (priv->book_combo,
+ search_combo_changed_cb,
+ search);
+}
+
+static gchar *
+search_combo_get_active_id (DhSearch *search)
+{
+ DhSearchPriv *priv = GET_PRIVATE (search);
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ gchar *id;
+
+ if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->book_combo),
+ &iter)) {
+ return NULL;
+ }
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (priv->book_combo));
+
+ gtk_tree_model_get (model, &iter,
+ 1, &id,
+ -1);
+
+ return id;
+}
+
+static void
+search_combo_changed_cb (GtkComboBox *combo,
+ DhSearch *search)
+{
+ DhSearchPriv *priv = GET_PRIVATE (search);
+
+ if (!priv->idle_filter) {
+ priv->idle_filter =
+ g_idle_add ((GSourceFunc) search_filter_idle, search);
+ }
+}
+
+static void
+search_entry_changed_cb (GtkEntry *entry,
+ DhSearch *search)
+{
+ DhSearchPriv *priv = GET_PRIVATE (search);
+
+ if (!priv->idle_filter) {
+ priv->idle_filter =
+ g_idle_add ((GSourceFunc) search_filter_idle, search);
+ }
+}
+
+static void
+search_entry_activated_cb (GtkEntry *entry,
+ DhSearch *search)
+{
+ DhSearchPriv *priv = GET_PRIVATE (search);
+ gchar *id;
+ const gchar *str;
+
+ id = search_combo_get_active_id (search);
+ str = gtk_entry_get_text (GTK_ENTRY (priv->entry));
+ dh_keyword_model_filter (priv->model, str, id);
+ g_free (id);
+}
+
+static void
+search_entry_text_inserted_cb (GtkEntry *entry,
+ const gchar *text,
+ gint length,
+ gint *position,
+ DhSearch *search)
+{
+ DhSearchPriv *priv = GET_PRIVATE (search);
+
+ if (!priv->idle_complete) {
+ priv->idle_complete =
+ g_idle_add ((GSourceFunc) search_complete_idle,
+ search);
+ }
+}
+
+static gboolean
+search_complete_idle (DhSearch *search)
+{
+ DhSearchPriv *priv = GET_PRIVATE (search);
+ const gchar *str;
+ gchar *completed = NULL;
+ gsize length;
+
+ str = gtk_entry_get_text (GTK_ENTRY (priv->entry));
+
+ g_completion_complete (priv->completion, str, &completed);
+ if (completed) {
+ length = strlen (str);
+
+ gtk_entry_set_text (GTK_ENTRY (priv->entry), completed);
+ gtk_editable_set_position (GTK_EDITABLE (priv->entry), length);
+ gtk_editable_select_region (GTK_EDITABLE (priv->entry),
+ length, -1);
+ g_free (completed);
+ }
+
+ priv->idle_complete = 0;
+
+ return FALSE;
+}
+
+static gboolean
+search_filter_idle (DhSearch *search)
+{
+ DhSearchPriv *priv = GET_PRIVATE (search);
+ const gchar *str;
+ gchar *id;
+ DhLink *link;
+
+ str = gtk_entry_get_text (GTK_ENTRY (priv->entry));
+ id = search_combo_get_active_id (search);
+ link = dh_keyword_model_filter (priv->model, str, id);
+ g_free (id);
+
+ priv->idle_filter = 0;
+
+ if (link) {
+ g_signal_emit (search, signals[LINK_SELECTED], 0, link);
+ }
+
+ return FALSE;
+}
+
+static const gchar *
+search_complete_func (DhLink *link)
+{
+ return dh_link_get_name (link);
+}
+
+static void
+search_cell_data_func (GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ DhLink *link;
+ PangoStyle style;
+
+ gtk_tree_model_get (tree_model, iter,
+ DH_KEYWORD_MODEL_COL_LINK, &link,
+ -1);
+
+ style = PANGO_STYLE_NORMAL;
+
+ if (dh_link_get_flags (link) & DH_LINK_FLAGS_DEPRECATED) {
+ style |= PANGO_STYLE_ITALIC;
+ }
+
+ g_object_set (cell,
+ "text", dh_link_get_name (link),
+ "style", style,
+ NULL);
+}
+
+static gboolean
+search_combo_row_separator_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ char *label;
+ char *link;
+ gboolean result;
+
+ gtk_tree_model_get (model, iter, 0, &label, 1, &link, -1);
+
+ result = (link == NULL && label == NULL);
+ g_free (label);
+ g_free (link);
+
+ return result;
+}
+
+static void
+search_combo_populate (DhSearch *search)
+{
+ DhSearchPriv *priv;
+ GtkListStore *store;
+ GtkTreeIter iter;
+ GList *l;
+
+ priv = GET_PRIVATE (search);
+
+ store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (priv->book_combo)));
+
+ gtk_list_store_clear (store);
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ 0, _("All books"),
+ 1, NULL,
+ -1);
+
+ /* Add a separator */
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ 0, NULL,
+ 1, NULL,
+ -1);
+
+ for (l = dh_book_manager_get_books (priv->book_manager);
+ l;
+ l = g_list_next (l)) {
+ DhBook *book = DH_BOOK (l->data);
+ GNode *node;
+
+ node = dh_book_get_tree (book);
+ if (node) {
+ DhLink *link;
+
+ link = node->data;
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ 0, dh_link_get_name (link),
+ 1, dh_link_get_book_id (link),
+ -1);
+ }
+ }
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (priv->book_combo), 0);
+}
+
+
+static void
+search_combo_create (DhSearch *search)
+{
+ GtkListStore *store;
+ GtkCellRenderer *cell;
+ DhSearchPriv *priv;
+
+ priv = GET_PRIVATE (search);
+
+ store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+ priv->book_combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
+ g_object_unref (store);
+
+ search_combo_populate (search);
+
+ gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (priv->book_combo),
+ search_combo_row_separator_func,
+ NULL, NULL);
+
+ cell = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->book_combo),
+ cell,
+ TRUE);
+ gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (priv->book_combo),
+ cell,
+ "text", 0);
+}
+
+static void
+completion_add_items (DhSearch *search)
+{
+ DhSearchPriv *priv;
+ GList *l;
+
+ priv = GET_PRIVATE (search);
+
+ for (l = dh_book_manager_get_books (priv->book_manager);
+ l;
+ l = g_list_next (l)) {
+ DhBook *book = DH_BOOK (l->data);
+ GList *keywords;
+
+ keywords = dh_book_get_keywords(book);
+
+ if (keywords) {
+ g_completion_add_items (priv->completion,
+ keywords);
+ }
+ }
+}
+
+static void
+book_manager_disabled_book_list_changed_cb (DhBookManager *book_manager,
+ gpointer user_data)
+{
+ DhSearch *search = user_data;
+ search_combo_populate (search);
+}
+
+GtkWidget *
+dh_search_new (DhBookManager *book_manager)
+{
+ DhSearch *search;
+ DhSearchPriv *priv;
+ GtkTreeSelection *selection;
+ GtkWidget *list_sw;
+ GtkWidget *hbox;
+ GtkWidget *book_label;
+ GtkCellRenderer *cell;
+
+ search = g_object_new (DH_TYPE_SEARCH, NULL);
+
+ priv = GET_PRIVATE (search);
+
+ priv->book_manager = g_object_ref (book_manager);
+ g_signal_connect (priv->book_manager,
+ "disabled-book-list-updated",
+ G_CALLBACK (book_manager_disabled_book_list_changed_cb),
+ search);
+
+ gtk_container_set_border_width (GTK_CONTAINER (search), 2);
+
+ search_combo_create (search);
+ g_signal_connect (priv->book_combo, "changed",
+ G_CALLBACK (search_combo_changed_cb),
+ search);
+
+ book_label = gtk_label_new_with_mnemonic (_("Search in:"));
+ gtk_label_set_mnemonic_widget (GTK_LABEL (book_label), priv->book_combo);
+
+ hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (hbox), book_label, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), priv->book_combo, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (search), hbox, FALSE, FALSE, 0);
+
+ /* Setup the keyword box. */
+ priv->entry = gtk_entry_new ();
+ g_signal_connect (priv->entry, "key-press-event",
+ G_CALLBACK (search_entry_key_press_event_cb),
+ search);
+
+ g_signal_connect (priv->hitlist, "button-press-event",
+ G_CALLBACK (search_tree_button_press_cb),
+ search);
+
+ g_signal_connect (priv->entry, "changed",
+ G_CALLBACK (search_entry_changed_cb),
+ search);
+
+ g_signal_connect (priv->entry, "activate",
+ G_CALLBACK (search_entry_activated_cb),
+ search);
+
+ g_signal_connect (priv->entry, "insert-text",
+ G_CALLBACK (search_entry_text_inserted_cb),
+ search);
+
+ gtk_box_pack_start (GTK_BOX (search), priv->entry, FALSE, FALSE, 0);
+
+ /* Setup the hitlist */
+ list_sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (list_sw), GTK_SHADOW_IN);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (list_sw),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
+
+ cell = gtk_cell_renderer_text_new ();
+ g_object_set (cell,
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ NULL);
+
+ gtk_tree_view_insert_column_with_data_func (
+ GTK_TREE_VIEW (priv->hitlist),
+ -1,
+ NULL,
+ cell,
+ search_cell_data_func,
+ search, NULL);
+
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->hitlist),
+ FALSE);
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->hitlist),
+ DH_KEYWORD_MODEL_COL_NAME);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->hitlist));
+
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (search_selection_changed_cb),
+ search);
+
+ gtk_container_add (GTK_CONTAINER (list_sw), priv->hitlist);
+
+ gtk_box_pack_end (GTK_BOX (search), list_sw, TRUE, TRUE, 0);
+
+ completion_add_items (search);
+ dh_keyword_model_set_words (priv->model, book_manager);
+
+ gtk_widget_show_all (GTK_WIDGET (search));
+
+ return GTK_WIDGET (search);
+}
+
+void
+dh_search_set_search_string (DhSearch *search,
+ const gchar *str,
+ const gchar *book_id)
+{
+ DhSearchPriv *priv;
+
+ g_return_if_fail (DH_IS_SEARCH (search));
+
+ priv = GET_PRIVATE (search);
+
+ g_signal_handlers_block_by_func (priv->entry,
+ search_entry_changed_cb,
+ search);
+
+ gtk_entry_set_text (GTK_ENTRY (priv->entry), str);
+
+ gtk_editable_set_position (GTK_EDITABLE (priv->entry), -1);
+ gtk_editable_select_region (GTK_EDITABLE (priv->entry), -1, -1);
+
+ g_signal_handlers_unblock_by_func (priv->entry,
+ search_entry_changed_cb,
+ search);
+
+ search_combo_set_active_id (search, book_id);
+
+ if (!priv->idle_filter) {
+ priv->idle_filter =
+ g_idle_add ((GSourceFunc) search_filter_idle, search);
+ }
+}
Modified: devhelp/devhelp/dh-search.h
60 files changed, 60 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,60 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2001-2002 CodeFactory AB
+ * Copyright (C) 2001-2002 Mikael Hallendal
+ *
+ * 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_SEARCH_H__
+#define __DH_SEARCH_H__
+
+#include
+#include "dh-link.h"
+#include "dh-book-manager.h"
+
+G_BEGIN_DECLS
+
+#define DH_TYPE_SEARCH (dh_search_get_type ())
+#define DH_SEARCH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DH_TYPE_SEARCH, DhSearch))
+#define DH_SEARCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DH_TYPE_SEARCH, DhSearchClass))
+#define DH_IS_SEARCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DH_TYPE_SEARCH))
+#define DH_IS_SEARCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DH_TYPE_SEARCH))
+
+typedef struct _DhSearch DhSearch;
+typedef struct _DhSearchClass DhSearchClass;
+
+struct _DhSearch {
+ GtkVBox parent_instance;
+};
+
+struct _DhSearchClass {
+ GtkVBoxClass parent_class;
+
+ /* Signals */
+ void (*link_selected) (DhSearch *search,
+ DhLink *link);
+};
+
+GType dh_search_get_type (void);
+GtkWidget *dh_search_new (DhBookManager *book_manager);
+void dh_search_set_search_string (DhSearch *search,
+ const gchar *str,
+ const gchar *book_id);
+
+G_END_DECLS
+
+#endif /* __DH_SEARCH_H__ */
Modified: devhelp/devhelp/dh-util.c
812 files changed, 812 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,812 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2001 Mikael Hallendal
+ * 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
+ * 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
+#include
+#include
+#ifdef GDK_WINDOWING_QUARTZ
+#include
+#endif
+#include "ige-conf.h"
+#include "dh-util.h"
+
+static GList *views;
+
+static GtkBuilder *
+get_builder_file (const gchar *filename,
+ const gchar *root,
+ const gchar *domain,
+ const gchar *first_required_widget,
+ va_list args)
+{
+ GtkBuilder *builder;
+ const char *name;
+ GObject **object_ptr;
+
+ builder = gtk_builder_new ();
+ if (!gtk_builder_add_from_file (builder, filename, NULL)) {
+ g_warning ("Couldn't find necessary UI file '%s'", filename);
+ g_object_unref (builder);
+ return NULL;
+ }
+
+ for (name = first_required_widget; name; name = va_arg (args, char *)) {
+ object_ptr = va_arg (args, void *);
+ *object_ptr = gtk_builder_get_object (builder, name);
+
+ if (!*object_ptr) {
+ g_warning ("UI file '%s' is missing widget '%s'.",
+ filename, name);
+ continue;
+ }
+ }
+
+ return builder;
+}
+
+GtkBuilder *
+dh_util_builder_get_file (const gchar *filename,
+ const gchar *root,
+ const gchar *domain,
+ const gchar *first_required_widget,
+ ...)
+{
+ va_list args;
+ GtkBuilder *builder;
+
+ va_start (args, first_required_widget);
+ builder = get_builder_file (filename,
+ root,
+ domain,
+ first_required_widget,
+ args);
+ va_end (args);
+
+ return builder;
+}
+
+void
+dh_util_builder_connect (GtkBuilder *builder,
+ gpointer user_data,
+ gchar *first_widget,
+ ...)
+{
+ va_list args;
+ const gchar *name;
+ const gchar *signal;
+ GObject *object;
+ gpointer *callback;
+
+ va_start (args, first_widget);
+
+ for (name = first_widget; name; name = va_arg (args, char *)) {
+ signal = va_arg (args, void *);
+ callback = va_arg (args, void *);
+
+ object = gtk_builder_get_object (builder, name);
+ if (!object) {
+ g_warning ("UI file is missing widget '%s', aborting",
+ name);
+ continue;
+ }
+
+ g_signal_connect (object,
+ signal,
+ G_CALLBACK (callback),
+ user_data);
+ }
+
+ va_end (args);
+}
+
+#ifdef GDK_WINDOWING_QUARTZ
+static gchar *
+cf_string_to_utf8 (CFStringRef str)
+{
+ CFIndex len;
+ gchar *ret;
+
+ len = CFStringGetMaximumSizeForEncoding (CFStringGetLength (str),
+ kCFStringEncodingUTF8) + 1;
+
+ ret = g_malloc (len);
+ ret[len] = '\0';
+
+ if (CFStringGetCString (str, ret, len, kCFStringEncodingUTF8))
+ return ret;
+
+ g_free (ret);
+ return NULL;
+}
+
+static gchar *
+util_get_mac_data_dir (void)
+{
+ const gchar *env;
+ CFBundleRef cf_bundle;
+ UInt32 type;
+ UInt32 creator;
+ CFURLRef cf_url;
+ CFStringRef cf_string;
+ gchar *ret, *tmp;
+
+ /* The environment variable overrides all. */
+ env = g_getenv ("DEVHELP_DATADIR");
+ if (env) {
+ return g_strdup (env);
+ }
+
+ cf_bundle = CFBundleGetMainBundle ();
+ if (!cf_bundle) {
+ return NULL;
+ }
+
+ /* Only point into the bundle if it's an application. */
+ CFBundleGetPackageInfo (cf_bundle, &type, &creator);
+ if (type != 'APPL') {
+ return NULL;
+ }
+
+ cf_url = CFBundleCopyBundleURL (cf_bundle);
+ cf_string = CFURLCopyFileSystemPath (cf_url, kCFURLPOSIXPathStyle);
+ ret = cf_string_to_utf8 (cf_string);
+ CFRelease (cf_string);
+ CFRelease (cf_url);
+
+ tmp = g_build_filename (ret, "Contents", "Resources", NULL);
+ g_free (ret);
+
+ return tmp;
+}
+#endif
+
+gchar *
+dh_util_build_data_filename (const gchar *first_part,
+ ...)
+{
+ gchar *datadir = NULL;
+ va_list args;
+ const gchar *part;
+ gchar **strv;
+ gint i;
+ gchar *ret;
+
+ va_start (args, first_part);
+
+#ifdef GDK_WINDOWING_QUARTZ
+ datadir = util_get_mac_data_dir ();
+#endif
+
+ if (datadir == NULL) {
+ datadir = g_strdup (DATADIR);
+ }
+
+ /* 2 = 1 initial component + terminating NULL element. */
+ strv = g_malloc (sizeof (gchar *) * 2);
+ strv[0] = (gchar *) datadir;
+
+ i = 1;
+ for (part = first_part; part; part = va_arg (args, char *), i++) {
+ /* +2 = 1 new element + terminating NULL element. */
+ strv = g_realloc (strv, sizeof (gchar*) * (i + 2));
+ strv[i] = (gchar *) part;
+ }
+
+ strv[i] = NULL;
+ ret = g_build_filenamev (strv);
+ g_free (strv);
+
+ g_free (datadir);
+
+ va_end (args);
+
+ return ret;
+}
+
+typedef struct {
+ gchar *name;
+ guint timeout_id;
+} DhUtilStateItem;
+
+static void
+util_state_item_free (DhUtilStateItem *item)
+{
+ g_free (item->name);
+ if (item->timeout_id) {
+ g_source_remove (item->timeout_id);
+ }
+ g_slice_free (DhUtilStateItem, item);
+}
+
+static void
+util_state_setup_widget (GtkWidget *widget,
+ const gchar *name)
+{
+ DhUtilStateItem *item;
+
+ item = g_slice_new0 (DhUtilStateItem);
+ item->name = g_strdup (name);
+
+ g_object_set_data_full (G_OBJECT (widget),
+ "dh-util-state",
+ item,
+ (GDestroyNotify) util_state_item_free);
+}
+
+static gchar *
+util_state_get_key (const gchar *name,
+ const gchar *key)
+{
+ return g_strdup_printf ("/apps/devhelp/state/%s/%s", name, key);
+}
+
+static void
+util_state_schedule_save (GtkWidget *widget,
+ GSourceFunc func)
+
+{
+ DhUtilStateItem *item;
+
+ item = g_object_get_data (G_OBJECT (widget), "dh-util-state");
+ if (item->timeout_id) {
+ g_source_remove (item->timeout_id);
+ }
+
+ item->timeout_id = g_timeout_add (500,
+ func,
+ widget);
+}
+
+static void
+util_state_save_window (GtkWindow *window,
+ const gchar *name)
+{
+ gchar *key;
+ GdkWindowState state;
+ gboolean maximized;
+ gint width, height;
+ gint x, y;
+
+#if GTK_CHECK_VERSION (2,14,0)
+ state = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (window)));
+#else
+ state = gdk_window_get_state (GTK_WIDGET (window)->window);
+#endif
+ if (state & GDK_WINDOW_STATE_MAXIMIZED) {
+ maximized = TRUE;
+ } else {
+ maximized = FALSE;
+ }
+
+ key = util_state_get_key (name, "maximized");
+ ige_conf_set_bool (ige_conf_get (), key, maximized);
+ g_free (key);
+
+ /* If maximized don't save the size and position. */
+ if (maximized) {
+ return;
+ }
+
+ gtk_window_get_size (GTK_WINDOW (window), &width, &height);
+
+ key = util_state_get_key (name, "width");
+ ige_conf_set_int (ige_conf_get (), key, width);
+ g_free (key);
+
+ key = util_state_get_key (name, "height");
+ ige_conf_set_int (ige_conf_get (), key, height);
+ g_free (key);
+
+ gtk_window_get_position (GTK_WINDOW (window), &x, &y);
+
+ key = util_state_get_key (name, "x_position");
+ ige_conf_set_int (ige_conf_get (), key, x);
+ g_free (key);
+
+ key = util_state_get_key (name, "y_position");
+ ige_conf_set_int (ige_conf_get (), key, y);
+ g_free (key);
+}
+
+static void
+util_state_restore_window (GtkWindow *window,
+ const gchar *name)
+{
+ gchar *key;
+ gboolean maximized;
+ gint width, height;
+ gint x, y;
+ GdkScreen *screen;
+ gint max_width, max_height;
+
+ key = util_state_get_key (name, "width");
+ ige_conf_get_int (ige_conf_get (), key, &width);
+ g_free (key);
+
+ key = util_state_get_key (name, "height");
+ ige_conf_get_int (ige_conf_get (), key, &height);
+ g_free (key);
+
+ key = util_state_get_key (name, "x_position");
+ ige_conf_get_int (ige_conf_get (), key, &x);
+ g_free (key);
+
+ key = util_state_get_key (name, "y_position");
+ ige_conf_get_int (ige_conf_get (), key, &y);
+ g_free (key);
+
+ if (width > 1 && height > 1) {
+ screen = gtk_widget_get_screen (GTK_WIDGET (window));
+ max_width = gdk_screen_get_width (screen);
+ max_height = gdk_screen_get_height (screen);
+
+ width = CLAMP (width, 0, max_width);
+ height = CLAMP (height, 0, max_height);
+
+ x = CLAMP (x, 0, max_width - width);
+ y = CLAMP (y, 0, max_height - height);
+
+ gtk_window_set_default_size (window, width, height);
+ }
+
+ gtk_window_move (window, x, y);
+
+ key = util_state_get_key (name, "maximized");
+ ige_conf_get_bool (ige_conf_get (), key, &maximized);
+ g_free (key);
+
+ if (maximized) {
+ gtk_window_maximize (window);
+ }
+}
+
+static gboolean
+util_state_window_timeout_cb (gpointer window)
+{
+ DhUtilStateItem *item;
+
+ item = g_object_get_data (window, "dh-util-state");
+ if (item) {
+ item->timeout_id = 0;
+ util_state_save_window (window, item->name);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+util_state_window_configure_event_cb (GtkWidget *window,
+ GdkEventConfigure *event,
+ gpointer user_data)
+{
+ util_state_schedule_save (window, util_state_window_timeout_cb);
+ return FALSE;
+}
+
+static gboolean
+util_state_paned_timeout_cb (gpointer paned)
+{
+ DhUtilStateItem *item;
+
+ item = g_object_get_data (paned, "dh-util-state");
+ if (item) {
+ gchar *key;
+
+ item->timeout_id = 0;
+
+ key = util_state_get_key (item->name, "position");
+ ige_conf_set_int (ige_conf_get (),
+ key,
+ gtk_paned_get_position (paned));
+ g_free (key);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+util_state_paned_changed_cb (GtkWidget *paned,
+ gpointer user_data)
+{
+ util_state_schedule_save (paned, util_state_paned_timeout_cb);
+ return FALSE;
+}
+
+void
+dh_util_state_manage_window (GtkWindow *window,
+ const gchar *name)
+{
+ util_state_setup_widget (GTK_WIDGET (window), name);
+
+ g_signal_connect (window, "configure-event",
+ G_CALLBACK (util_state_window_configure_event_cb),
+ NULL);
+
+ util_state_restore_window (window, name);
+}
+
+void
+dh_util_state_manage_paned (GtkPaned *paned,
+ const gchar *name)
+{
+ gchar *key;
+ gint position;
+
+ util_state_setup_widget (GTK_WIDGET (paned), name);
+
+ key = util_state_get_key (name, "position");
+ if (ige_conf_get_int (ige_conf_get (), key, &position)) {
+ gtk_paned_set_position (paned, position);
+ }
+ g_free (key);
+
+ g_signal_connect (paned, "notify::position",
+ G_CALLBACK (util_state_paned_changed_cb),
+ NULL);
+}
+
+GSList *
+dh_util_state_load_books_disabled (void)
+{
+ gchar *key;
+ GSList *books_disabled = NULL;
+
+ key = util_state_get_key ("main/contents", "books_disabled");
+ ige_conf_get_string_list (ige_conf_get (), key, &books_disabled);
+ g_free(key);
+
+ return books_disabled;
+}
+
+void
+dh_util_state_store_books_disabled (GSList *books_disabled)
+{
+ gchar *key;
+
+ key = util_state_get_key ("main/contents", "books_disabled");
+ ige_conf_set_string_list (ige_conf_get (), key, books_disabled);
+ g_free(key);
+}
+
+static gboolean
+util_state_notebook_timeout_cb (gpointer notebook)
+{
+ DhUtilStateItem *item;
+
+ item = g_object_get_data (notebook, "dh-util-state");
+ if (item) {
+ GtkWidget *page;
+ const gchar *page_name;
+
+ item->timeout_id = 0;
+
+ page = gtk_notebook_get_nth_page (
+ notebook,
+ gtk_notebook_get_current_page (notebook));
+ page_name = dh_util_state_get_notebook_page_name (page);
+ if (page_name) {
+ gchar *key;
+
+ key = util_state_get_key (item->name, "selected_tab");
+ ige_conf_set_string (ige_conf_get (), key, page_name);
+ g_free (key);
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+util_state_notebook_switch_page_cb (GtkWidget *notebook,
+ gpointer page,
+ guint page_num,
+ gpointer user_data)
+{
+ util_state_schedule_save (notebook, util_state_notebook_timeout_cb);
+}
+
+void
+dh_util_state_set_notebook_page_name (GtkWidget *page,
+ const gchar *page_name)
+{
+ g_object_set_data_full (G_OBJECT (page),
+ "dh-util-state-tab-name",
+ g_strdup (page_name),
+ g_free);
+}
+
+const gchar *
+dh_util_state_get_notebook_page_name (GtkWidget *page)
+{
+ return g_object_get_data (G_OBJECT (page),
+ "dh-util-state-tab-name");
+}
+
+void
+dh_util_state_manage_notebook (GtkNotebook *notebook,
+ const gchar *name,
+ const gchar *default_tab)
+{
+ gchar *key;
+ gchar *tab;
+ gint i;
+
+ util_state_setup_widget (GTK_WIDGET (notebook), name);
+
+ key = util_state_get_key (name, "selected_tab");
+ if (!ige_conf_get_string (ige_conf_get (), key, &tab)) {
+ tab = g_strdup (default_tab);
+ }
+ g_free (key);
+
+ for (i = 0; i < gtk_notebook_get_n_pages (notebook); i++) {
+ GtkWidget *page;
+ const gchar *page_name;
+
+ page = gtk_notebook_get_nth_page (notebook, i);
+ page_name = dh_util_state_get_notebook_page_name (page);
+ if (page_name && strcmp (page_name, tab) == 0) {
+ gtk_notebook_set_current_page (notebook, i);
+ gtk_widget_grab_focus (page);
+ break;
+ }
+ }
+
+ g_free (tab);
+
+ g_signal_connect (notebook, "switch-page",
+ G_CALLBACK (util_state_notebook_switch_page_cb),
+ NULL);
+}
+
+static gboolean
+split_font_string (const gchar *name_and_size,
+ gchar **name,
+ gdouble *size)
+{
+ PangoFontDescription *desc;
+ PangoFontMask mask;
+ gboolean retval = FALSE;
+
+ desc = pango_font_description_from_string (name_and_size);
+ if (!desc) {
+ return FALSE;
+ }
+
+ mask = (PANGO_FONT_MASK_FAMILY | PANGO_FONT_MASK_SIZE);
+ if ((pango_font_description_get_set_fields (desc) & mask) == mask) {
+ *size = PANGO_PIXELS (pango_font_description_get_size (desc));
+ *name = g_strdup (pango_font_description_get_family (desc));
+ retval = TRUE;
+ }
+
+ pango_font_description_free (desc);
+
+ return retval;
+}
+
+#define DH_CONF_PATH "/apps/devhelp"
+#define DH_CONF_USE_SYSTEM_FONTS DH_CONF_PATH "/ui/use_system_fonts"
+#define DH_CONF_VARIABLE_FONT DH_CONF_PATH "/ui/variable_font"
+#define DH_CONF_FIXED_FONT DH_CONF_PATH "/ui/fixed_font"
+#define DH_CONF_SYSTEM_VARIABLE_FONT "/desktop/gnome/interface/font_name"
+#define DH_CONF_SYSTEM_FIXED_FONT "/desktop/gnome/interface/monospace_font_name"
+
+void
+dh_util_font_get_variable (gchar **name,
+ gdouble *size,
+ gboolean use_system_fonts)
+{
+ IgeConf *conf;
+ gchar *name_and_size;
+
+ conf = ige_conf_get ();
+
+ if (use_system_fonts) {
+#ifdef GDK_WINDOWING_QUARTZ
+ name_and_size = g_strdup ("Lucida Grande 14");
+#else
+ ige_conf_get_string (conf,
+ DH_CONF_SYSTEM_VARIABLE_FONT,
+ &name_and_size);
+#endif
+ } else {
+ ige_conf_get_string (conf,
+ DH_CONF_VARIABLE_FONT,
+ &name_and_size);
+ }
+
+ if (!split_font_string (name_and_size, name, size)) {
+ *name = g_strdup ("sans");
+ *size = 12;
+ }
+
+ g_free (name_and_size);
+}
+
+void
+dh_util_font_get_fixed (gchar **name,
+ gdouble *size,
+ gboolean use_system_fonts)
+{
+ IgeConf *conf;
+ gchar *name_and_size;
+
+ conf = ige_conf_get ();
+
+ if (use_system_fonts) {
+#ifdef GDK_WINDOWING_QUARTZ
+ name_and_size = g_strdup ("Monaco 14");
+#else
+ ige_conf_get_string (conf,
+ DH_CONF_SYSTEM_FIXED_FONT,
+ &name_and_size);
+#endif
+ } else {
+ ige_conf_get_string (conf,
+ DH_CONF_FIXED_FONT,
+ &name_and_size);
+ }
+
+ if (!split_font_string (name_and_size, name, size)) {
+ *name = g_strdup ("monospace");
+ *size = 12;
+ }
+
+ g_free (name_and_size);
+}
+
+static void
+view_destroy_cb (GtkWidget *view,
+ gpointer user_data)
+{
+ views = g_list_remove (views, view);
+}
+
+static void
+view_setup_fonts (WebKitWebView *view)
+{
+ IgeConf *conf;
+ WebKitWebSettings *settings;
+ gboolean use_system_fonts;
+ gchar *variable_name;
+ gdouble variable_size;
+ gchar *fixed_name;
+ gdouble fixed_size;
+
+ conf = ige_conf_get ();
+
+ settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW (view));
+
+ ige_conf_get_bool (conf,
+ DH_CONF_USE_SYSTEM_FONTS,
+ &use_system_fonts);
+
+ dh_util_font_get_variable (&variable_name, &variable_size,
+ use_system_fonts);
+ dh_util_font_get_fixed (&fixed_name, &fixed_size,
+ use_system_fonts);
+
+ g_object_set (settings,
+ "monospace-font-family", fixed_name,
+ "default-monospace-font-size", (guint) fixed_size,
+ "sans-serif-font-family", variable_name,
+ "serif-font-family", variable_name,
+ "default-font-size", (guint) variable_size,
+ NULL);
+
+ g_free (variable_name);
+ g_free (fixed_name);
+}
+
+static void
+font_notify_cb (IgeConf *conf,
+ const gchar *path,
+ gpointer user_data)
+{
+ GList *l;
+
+ for (l = views; l; l = l->next) {
+ view_setup_fonts (l->data);
+ }
+}
+
+void
+dh_util_font_add_web_view (WebKitWebView *view)
+{
+ static gboolean setup;
+
+ if (!setup) {
+ IgeConf *conf;
+
+ conf = ige_conf_get ();
+
+ ige_conf_notify_add (conf,
+ DH_CONF_USE_SYSTEM_FONTS,
+ font_notify_cb,
+ NULL);
+ ige_conf_notify_add (conf,
+ DH_CONF_SYSTEM_VARIABLE_FONT,
+ font_notify_cb,
+ NULL);
+ ige_conf_notify_add (conf,
+ DH_CONF_SYSTEM_FIXED_FONT,
+ font_notify_cb,
+ NULL);
+ ige_conf_notify_add (conf,
+ DH_CONF_VARIABLE_FONT,
+ font_notify_cb,
+ NULL);
+ ige_conf_notify_add (conf,
+ DH_CONF_FIXED_FONT,
+ font_notify_cb,
+ NULL);
+
+ setup = TRUE;
+ }
+
+ views = g_list_prepend (views, view);
+
+ g_signal_connect (view, "destroy",
+ G_CALLBACK (view_destroy_cb),
+ NULL);
+
+ view_setup_fonts (view);
+}
+
+gint
+dh_util_cmp_book (DhLink *a, DhLink *b)
+{
+ const gchar *name_a;
+ const gchar *name_b;
+ gchar *name_a_casefold;
+ gchar *name_b_casefold;
+ int rc;
+
+ name_a = dh_link_get_name (a);
+ if (!name_a) {
+ name_a = "";
+ }
+
+ name_b = dh_link_get_name (b);
+ if (!name_b) {
+ name_b = "";
+ }
+
+ if (g_ascii_strncasecmp (name_a, "the ", 4) == 0) {
+ name_a += 4;
+ }
+ if (g_ascii_strncasecmp (name_b, "the ", 4) == 0) {
+ name_b += 4;
+ }
+
+ name_a_casefold = g_utf8_casefold (name_a, -1);
+ name_b_casefold = g_utf8_casefold (name_b, -1);
+
+ rc = strcmp (name_a_casefold, name_b_casefold);
+
+ g_free (name_a_casefold);
+ g_free (name_b_casefold);
+
+ return rc;
+}
+
Modified: devhelp/devhelp/dh-util.h
67 files changed, 67 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2001-2002 Mikael Hallendal