SF.net SVN: geany-plugins:[2082] trunk/geany-plugins/devhelp

codebrainz at users.sourceforge.net codebrainz at xxxxx
Tue May 24 09:04:07 UTC 2011


Revision: 2082
          http://geany-plugins.svn.sourceforge.net/geany-plugins/?rev=2082&view=rev
Author:   codebrainz
Date:     2011-05-24 09:04:06 +0000 (Tue, 24 May 2011)

Log Message:
-----------
More massive re-factoring, cleanup, and renaming.

Modified Paths:
--------------
    trunk/geany-plugins/devhelp/data/devhelp.conf
    trunk/geany-plugins/devhelp/src/Makefile.am
    trunk/geany-plugins/devhelp/wscript_build
    trunk/geany-plugins/devhelp/wscript_configure

Added Paths:
-----------
    trunk/geany-plugins/devhelp/src/dhp-codesearch.c
    trunk/geany-plugins/devhelp/src/dhp-manpages.c
    trunk/geany-plugins/devhelp/src/dhp-object.c
    trunk/geany-plugins/devhelp/src/dhp-plugin.c
    trunk/geany-plugins/devhelp/src/dhp-plugin.h
    trunk/geany-plugins/devhelp/src/dhp-settings.c
    trunk/geany-plugins/devhelp/src/dhp.h

Removed Paths:
-------------
    trunk/geany-plugins/devhelp/src/codesearch.c
    trunk/geany-plugins/devhelp/src/devhelpplugin.c
    trunk/geany-plugins/devhelp/src/devhelpplugin.h
    trunk/geany-plugins/devhelp/src/main-notebook.c
    trunk/geany-plugins/devhelp/src/main-notebook.h
    trunk/geany-plugins/devhelp/src/manpages.c
    trunk/geany-plugins/devhelp/src/plugin.c
    trunk/geany-plugins/devhelp/src/plugin.h

Modified: trunk/geany-plugins/devhelp/data/devhelp.conf
===================================================================
--- trunk/geany-plugins/devhelp/data/devhelp.conf	2011-05-23 11:30:31 UTC (rev 2081)
+++ trunk/geany-plugins/devhelp/data/devhelp.conf	2011-05-24 09:04:06 UTC (rev 2082)
@@ -1,4 +1,67 @@
-[general]
-move_sidebar_tabs_bottom=true
-show_in_message_window=false
+
+[webview]
+# Which notebook gets the webview
+#   0 - None (hidden)
+#   1 - Sidebar
+#   2 - Message Window
+#   3 - A new "Main Notebook"
+location=3
+
+# When a search is triggered through the UI or keybinding, focus the webview
+# (show it's notebook page).
+focus_webview_on_search=true
+
+# If set, it's a URI to show in the webview when the plugin is loaded
+# If left blank, the last URI that was shown is used
+custom_homepage=
+
+# Tracks the last URI shown in the webview.
+# This is set by the plugin automatically on unload.
+# If not set (initial) custom_homepage will be shown if set or a default
+# page otherwise.
 last_uri=
+
+
+[doc_providers]
+# Use the integrated Devhelp widgets/features.
+devhelp=true
+# Use the system's manual pages (if man program is available)
+man_pages=true
+# Search Google Code and put the result page in the webview
+codesearch=true
+
+[devhelp]
+# Use the devhelp sidebar (search and browser UI).
+show_devhelp_sidebar=true
+# When using the devhelp sidebar, move the main sidebar's tabs to the bottom.
+set_sidebar_tabs_bottom=true
+# When searching with Devhelp, show the tab with the Devhelp sidebar in it.
+focus_sidebar_on_search=true
+
+[man_pages]
+# If the manual page program isn't in the path, you can set it's path.
+prog_path=man
+# Value to pass to -P option of man program
+pager_prog=col -b
+# Search manual page sections in this order.  This value is directly passed
+# the man program's -S option.
+section_order=3:2:1:8:5:4:7:6
+
+[codesearch]
+base_uri=http://www.google.com/codesearch
+
+# If Geany's filetype can be mapped to a Google code search language, then
+# specify the language to narrow down the search.
+use_lang_for_search=true
+
+# Other parameteres added to the end of the search URI just before loading
+# the URI in the webview.
+uri_params=
+
+[misc]
+# Where to put the tabs in the "main notebook" if it's being used.
+#   0 - Left
+#   1 - Right
+#   2 - Top
+#   3 - Bottom
+main_notebook_tab_pos=3

Modified: trunk/geany-plugins/devhelp/src/Makefile.am
===================================================================
--- trunk/geany-plugins/devhelp/src/Makefile.am	2011-05-23 11:30:31 UTC (rev 2081)
+++ trunk/geany-plugins/devhelp/src/Makefile.am	2011-05-24 09:04:06 UTC (rev 2082)
@@ -10,16 +10,14 @@
 endif
 
 devhelp_la_SOURCES = \
-	main-notebook.c \
-	devhelpplugin.c \
-	plugin.c \
-	manpages.c \
-	codesearch.c
+	dhp-codesearch.c \
+	dhp-manpages.c \
+	dhp-object.c \
+	dhp-plugin.c
 
 noinst_HEADERS = \
-	plugin.h \
-	devhelpplugin.h \
-	main-notebook.h
+	dhp.h \
+	dhp-plugin.h
 
 devhelp_la_CFLAGS = \
 	$(AM_CFLAGS) \

Deleted: trunk/geany-plugins/devhelp/src/codesearch.c
===================================================================
--- trunk/geany-plugins/devhelp/src/codesearch.c	2011-05-23 11:30:31 UTC (rev 2081)
+++ trunk/geany-plugins/devhelp/src/codesearch.c	2011-05-24 09:04:06 UTC (rev 2082)
@@ -1,96 +0,0 @@
-#include <glib.h>
-#include <webkit/webkitwebview.h>
-
-#include "devhelpplugin.h"
-
-
-struct LangMapEnt
-{
-	const gchar *geany_name;
-	const gchar *google_name;
-};
-
-
-#define GOOGLE_CODE_SEARCH_URI "http://www.google.com/codesearch"
-
-#define LANG_MAP_MAX 33 /* update this with lang_map[] size below */
-
-/* maps Geany language names to Google Code language names */
-static const struct LangMapEnt lang_map[LANG_MAP_MAX] = {
-	{ "ActionScript", "actionscript" },
-	{ "Ada", "ada" },
-	{ "ASM", "assembly" },
-	{ "FreeBasic", "basic" },
-	{ "C", "c" },
-	{ "C++", "c++" },
-	{ "C#", "c#" },
-	{ "COBOL", "cobol" },
-	{ "CSS", "css" },
-	{ "D", "d" },
-	{ "Erlang", "erlang" },
-	{ "Fortran", "fortran" },
-	{ "Haskell", "haskell" },
-	{ "Java", "java" },
-	{ "Javascript", "javascript" },
-	{ "Lisp", "lisp" },
-	{ "Lua", "lua" },
-	{ "Make", "makefile" },
-	{ "Matlab/Octave", "matlab" },
-	{ "CAML", "ocaml" },
-	{ "Pascal", "pascal" },
-	{ "Perl", "perl" },
-	{ "PHP", "php" },
-	{ "Python", "python" },
-	{ "R", "r" },
-	{ "Ruby", "ruby" },
-	{ "Sh", "shell" },
-	{ "SQL", "sql" },
-	{ "Tcl", "tcl" },
-	{ "LaTeX", "tex" },
-	{ "Verilog", "verilog" },
-	{ "VHDL", "vhdl" },
-	{ "None", NULL }
-};
-
-
-void devhelp_plugin_search_code(DevhelpPlugin *self, const gchar *term, const gchar *lang)
-{
-	gint i;
-	gchar *uri, *term_enc, *lang_enc;
-	const gchar *google_lang = NULL;
-
-	g_return_if_fail(self != NULL);
-	g_return_if_fail(term != NULL);
-
-	if (lang != NULL)
-	{
-		for (i = 0; i < LANG_MAP_MAX; i++)
-		{
-			if (g_strcmp0(lang, lang_map[i].geany_name) == 0)
-			{
-				google_lang = lang_map[i].google_name;
-				break;
-			}
-		}
-	}
-
-	if (google_lang != NULL)
-	{
-		lang_enc = g_uri_escape_string(google_lang, NULL, TRUE);
-		term_enc = g_uri_escape_string(term, NULL, TRUE);
-		uri = g_strdup_printf("%s?as_q=%s&as_lang=%s", GOOGLE_CODE_SEARCH_URI, term_enc, lang_enc);
-		g_free(lang_enc);
-		g_free(term_enc);
-	}
-	else
-	{
-		term_enc = g_uri_escape_string(term, NULL, TRUE);
-		uri = g_strdup_printf("%s?as_q=%s", GOOGLE_CODE_SEARCH_URI, term_enc);
-		g_free(term_enc);
-	}
-
-	webkit_web_view_open(devhelp_plugin_get_webview(self), uri);
-	g_free(uri);
-
-	devhelp_plugin_activate_webview_tab(self);
-}

Deleted: trunk/geany-plugins/devhelp/src/devhelpplugin.c
===================================================================
--- trunk/geany-plugins/devhelp/src/devhelpplugin.c	2011-05-23 11:30:31 UTC (rev 2081)
+++ trunk/geany-plugins/devhelp/src/devhelpplugin.c	2011-05-24 09:04:06 UTC (rev 2082)
@@ -1,1019 +0,0 @@
-/*
- * devhelpplugin.c
- *
- * Copyright 2011 Matthew Brush <mbrush at leftclick.ca>
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include <stdlib.h>
-#include <gtk/gtk.h>
-#include <geanyplugin.h>
-
-#include <devhelp/dh-base.h>
-#include <devhelp/dh-book-tree.h>
-#include <devhelp/dh-search.h>
-#include <devhelp/dh-link.h>
-
-#ifdef HAVE_BOOK_MANAGER /* for newer api */
-#include <devhelp/dh-book-manager.h>
-#endif
-
-#include <webkit/webkitwebview.h>
-
-#include "main-notebook.h"
-#include "devhelpplugin.h"
-#include "plugin.h"
-
-
-struct _DevhelpPluginPrivate
-{
-	DhBase*			dhbase;
-    GtkWidget*		book_tree;			/* "Contents" in the sidebar */
-    GtkWidget*		search;				/* "Search" in the sidebar */
-    GtkWidget*		sb_notebook;		/* Notebook that holds contents/search */
-    gint 			sb_notebook_tab;	/* Index of tab where devhelp sidebar is */
-    GtkWidget*		webview;			/* Webkit that shows documentation */
-    gint 			webview_tab;		/* Index of tab that contains the webview */
-    GtkWidget*		main_notebook;		/* Notebook that holds Geany doc notebook and
-										 *   and webkit view */
-    GtkWidget*		doc_notebook;    	/* Geany's document notebook   */
-    GtkWidget*		editor_menu_item;	/* Item in the editor's context menu */
-    GtkWidget*		editor_menu_sep;	/* Separator item above menu item */
-    gboolean		webview_active;		/* Tracks whether webview stuff is shown */
-    gboolean		last_main_tab_id;	/* These track the last id of the tabs */
-    gboolean		last_sb_tab_id;		/*   before toggling */
-    gboolean		tabs_toggled;		/* Tracks state of whether to toggle to
-										 *   Devhelp or back to code */
-    gboolean		created_main_nb;	/* Track whether we created the main notebook */
-
-    GtkPositionType	orig_sb_tab_pos;	/* The tab idx of the initial sidebar tab */
-    gboolean		sidebar_tab_bottom;	/* whether the sidebar tabs are at the bottom */
-    gboolean		in_message_window;	/* whether the webkit stuff is in the msgwin */
-
-    gchar*			last_uri;			/* the last URI loaded before the current */
-    gfloat			zoom_level;			/* the webkit zoom level */
-
-    GtkToolItem*	btn_back;			/* the webkit browser back button in the toolbar */
-    GtkToolItem*	btn_forward;		/* the webkit browser forward button in the toolbar */
-
-    gboolean		have_man;			/* whether or not the 'man' program is available on load */
-
-};
-
-
-G_DEFINE_TYPE(DevhelpPlugin, devhelp_plugin, G_TYPE_OBJECT)
-
-
-static DhBase *dhbase = NULL;
-
-
-/* Internal callbacks */
-static void on_search_help_activate(GtkMenuItem * menuitem, DevhelpPlugin *self);
-static void on_search_help_man_activate(GtkMenuItem * menuitem, DevhelpPlugin *self);
-static void on_search_help_code_activate(GtkMenuItem *menuitem, DevhelpPlugin *self);
-static void on_editor_menu_popup(GtkWidget * widget, DevhelpPlugin *self);
-static void on_link_clicked(GObject * ignored, DhLink * dhlink, DevhelpPlugin *self);
-static void on_back_button_clicked(GtkToolButton * btn, DevhelpPlugin *self);
-static void on_forward_button_clicked(GtkToolButton * btn, DevhelpPlugin *self);
-static void on_zoom_in_button_clicked(GtkToolButton * btn, DevhelpPlugin *self);
-static void on_zoom_out_button_clicked(GtkToolButton *btn, DevhelpPlugin *self);
-static void on_document_load_finished(WebKitWebView *view, WebKitWebFrame *frame, DevhelpPlugin *self);
-static void on_uri_changed_notify(GObject *object, GParamSpec *pspec, DevhelpPlugin *self);
-static void on_load_status_changed_notify(GObject *object, GParamSpec *pspec, DevhelpPlugin *self);
-
-/* Misc internal functions */
-static inline void update_history_buttons(DevhelpPlugin *self);
-
-
-/* Put cleanup code in here */
-static void devhelp_plugin_finalize(GObject * object)
-{
-	DevhelpPlugin *self;
-
-	g_return_if_fail(object != NULL);
-	g_return_if_fail(DEVHELP_IS_PLUGIN(object));
-
-	self = DEVHELP_PLUGIN(object);
-
-	gtk_widget_destroy(self->priv->sb_notebook);
-
-	gtk_notebook_remove_page(GTK_NOTEBOOK(self->priv->main_notebook), self->priv->webview_tab);
-
-	if (!self->priv->in_message_window)
-	{
-		g_debug("Destroying main notebook");
-		main_notebook_destroy();
-	}
-	gtk_widget_destroy(self->priv->editor_menu_sep);
-	gtk_widget_destroy(self->priv->editor_menu_item);
-
-	gtk_notebook_set_tab_pos(GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook),
-		self->priv->orig_sb_tab_pos);
-
-	if (self->priv->last_uri != NULL)
-		g_free(self->priv->last_uri);
-
-	devhelp_plugin_remove_manpages_temp_files();
-
-	G_OBJECT_CLASS(devhelp_plugin_parent_class)->finalize(object);
-}
-
-
-static void devhelp_plugin_class_init(DevhelpPluginClass * klass)
-{
-	GObjectClass *g_object_class;
-
-	g_object_class = G_OBJECT_CLASS(klass);
-	g_object_class->finalize = devhelp_plugin_finalize;
-	g_type_class_add_private((gpointer) klass, sizeof(DevhelpPluginPrivate));
-}
-
-
-/*
- * Initialize the Devhelp library/widgets.
- * The Devhelp API isn't exactly stable, so handle quirks in here.
- */
-static void devhelp_plugin_init_dh(DevhelpPlugin *self)
-{
-#ifdef HAVE_BOOK_MANAGER /* for newer api */
-	DhBookManager *book_manager;
-#else
-	GNode *books;
-	GList *keywords;
-#endif
-
-	if (dhbase == NULL)
-		dhbase = dh_base_new();
-	self->priv->dhbase = dhbase;
-
-#ifdef HAVE_BOOK_MANAGER /* for newer api */
-	book_manager = dh_base_get_book_manager(self->priv->dhbase);
-	self->priv->book_tree = dh_book_tree_new(book_manager);
-	self->priv->search = dh_search_new(book_manager);
-#else
-	books = dh_base_get_book_tree(self->priv->dhbase);
-	keywords = dh_base_get_keywords(self->priv->dhbase);
-	self->priv->book_tree = dh_book_tree_new(books);
-	self->priv->search = dh_search_new(keywords);
-#endif
-
-	gtk_widget_show(self->priv->search);
-
-	g_signal_connect(self->priv->book_tree, "link-selected", G_CALLBACK(on_link_clicked), self);
-	g_signal_connect(self->priv->search, "link-selected", G_CALLBACK(on_link_clicked), self);
-}
-
-
-/* Initialize the stuff in the editor's context menu */
-static void devhelp_plugin_init_edit_menu(DevhelpPlugin *self)
-{
-	GtkWidget *doc_menu, *devhelp_item, *code_item, *man_item;
-	DevhelpPluginPrivate *p;
-
-	g_return_if_fail(self != NULL);
-
-	p = self->priv;
-
-	p->editor_menu_sep = gtk_separator_menu_item_new();
-	p->editor_menu_item = gtk_menu_item_new_with_label(_("Search for 'Tag' Documentation in"));
-	doc_menu = gtk_menu_new();
-
-	devhelp_item = gtk_menu_item_new_with_label(_("Devhelp"));
-	gtk_menu_shell_append(GTK_MENU_SHELL(doc_menu), devhelp_item);
-	g_signal_connect(devhelp_item, "activate", G_CALLBACK(on_search_help_activate), self);
-	gtk_widget_show(devhelp_item);
-
-	if (p->have_man)
-	{
-		man_item = gtk_menu_item_new_with_label(_("Manual Pages"));
-		gtk_menu_shell_append(GTK_MENU_SHELL(doc_menu), man_item);
-		g_signal_connect(man_item, "activate", G_CALLBACK(on_search_help_man_activate), self);
-		gtk_widget_show(man_item);
-	}
-
-	code_item = gtk_menu_item_new_with_label(_("Google Code"));
-	gtk_menu_shell_append(GTK_MENU_SHELL(doc_menu), code_item);
-	g_signal_connect(code_item, "activate", G_CALLBACK(on_search_help_code_activate), self);
-	gtk_widget_show(code_item);
-
-	g_signal_connect(geany->main_widgets->editor_menu, "show", G_CALLBACK(on_editor_menu_popup), self);
-	gtk_menu_item_set_submenu(GTK_MENU_ITEM(p->editor_menu_item), doc_menu);
-	gtk_menu_shell_append(GTK_MENU_SHELL(geany->main_widgets->editor_menu), p->editor_menu_sep);
-	gtk_menu_shell_append(GTK_MENU_SHELL(geany->main_widgets->editor_menu), p->editor_menu_item);
-	gtk_widget_show(p->editor_menu_sep);
-	gtk_widget_show_all(p->editor_menu_item);
-}
-
-
-/* Initialize the WebKit browser and associated widgets */
-static void devhelp_plugin_init_webkit(DevhelpPlugin *self)
-{
-	GtkWidget *vbox, *label, *toolbar;
-	GtkToolItem *btn_zoom_in, *btn_zoom_out, *tb_sep;
-	GtkScrolledWindow *webview_sw;
-	DevhelpPluginPrivate *p;
-
-	g_return_if_fail(self != NULL);
-
-	p = self->priv;
-
-	p->webview = webkit_web_view_new();
-
-	webview_sw = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL));
-	gtk_scrolled_window_set_policy(webview_sw, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-	gtk_scrolled_window_set_shadow_type(webview_sw, GTK_SHADOW_ETCHED_IN);
-	gtk_container_add(GTK_CONTAINER(webview_sw), p->webview);
-
-	gtk_widget_show_all(GTK_WIDGET(webview_sw));
-
-	vbox = gtk_vbox_new(FALSE, 0);
-	toolbar = gtk_toolbar_new();
-
-	p->btn_back = gtk_tool_button_new_from_stock(GTK_STOCK_GO_BACK);
-	p->btn_forward = gtk_tool_button_new_from_stock(GTK_STOCK_GO_FORWARD);
-	btn_zoom_in = gtk_tool_button_new_from_stock(GTK_STOCK_ZOOM_IN);
-	btn_zoom_out = gtk_tool_button_new_from_stock(GTK_STOCK_ZOOM_OUT);
-	tb_sep = gtk_separator_tool_item_new();
-
-	gtk_widget_set_tooltip_text(GTK_WIDGET(p->btn_back), _("Go back one page"));
-	gtk_widget_set_tooltip_text(GTK_WIDGET(p->btn_forward), _("Go forward one page"));
-	gtk_widget_set_tooltip_text(GTK_WIDGET(btn_zoom_in), _("Zoom in"));
-	gtk_widget_set_tooltip_text(GTK_WIDGET(btn_zoom_out), _("Zoom out"));
-
-	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), p->btn_back, -1);
-	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), p->btn_forward, -1);
-	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tb_sep, -1);
-	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), btn_zoom_in, -1);
-	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), btn_zoom_out, -1);
-
-	gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, TRUE, 0);
-	gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(webview_sw), TRUE, TRUE, 0);
-
-	label = gtk_label_new(_("Documentation"));
-	gtk_notebook_append_page(GTK_NOTEBOOK(p->main_notebook), vbox, label);
-
-	p->webview_tab = gtk_notebook_page_num(GTK_NOTEBOOK(p->main_notebook), vbox);
-
-	gtk_widget_show_all(vbox);
-
-	g_signal_connect(p->btn_back, "clicked", G_CALLBACK(on_back_button_clicked), self);
-	g_signal_connect(p->btn_forward, "clicked", G_CALLBACK(on_forward_button_clicked), self);
-	g_signal_connect(btn_zoom_in, "clicked", G_CALLBACK(on_zoom_in_button_clicked), self);
-	g_signal_connect(btn_zoom_out, "clicked", G_CALLBACK(on_zoom_out_button_clicked), self);
-
-	g_signal_connect(WEBKIT_WEB_VIEW(p->webview), "document-load-finished", G_CALLBACK(on_document_load_finished), self);
-	g_signal_connect(WEBKIT_WEB_VIEW(p->webview), "notify::uri", G_CALLBACK(on_uri_changed_notify), self);
-	g_signal_connect(WEBKIT_WEB_VIEW(p->webview), "notify::load-status", G_CALLBACK(on_load_status_changed_notify), self);
-
-	p->last_uri = g_filename_to_uri(DHPLUG_WEBVIEW_HOME_FILE, NULL, NULL);
-	if (p->last_uri != NULL)
-		webkit_web_view_load_uri(WEBKIT_WEB_VIEW(p->webview), p->last_uri);
-}
-
-
-/* Initialize the stuff added to the sidebar. */
-static void devhelp_plugin_init_sidebar(DevhelpPlugin *self)
-{
-	GtkWidget *label;
-	GtkWidget *book_tree_sw;
-	DevhelpPluginPrivate *p;
-
-	g_return_if_fail(self != NULL);
-
-	p = self->priv;
-
-	p->sb_notebook = gtk_notebook_new();
-	p->orig_sb_tab_pos = gtk_notebook_get_tab_pos(GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook));
-
-	book_tree_sw = gtk_scrolled_window_new(NULL, NULL);
-	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(book_tree_sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
-	gtk_container_set_border_width(GTK_CONTAINER(book_tree_sw), 6);
-	gtk_container_add(GTK_CONTAINER(book_tree_sw), p->book_tree);
-	gtk_widget_show(p->book_tree);
-
-	label = gtk_label_new(_("Contents"));
-	gtk_notebook_append_page(GTK_NOTEBOOK(p->sb_notebook), book_tree_sw, label);
-
-	label = gtk_label_new(_("Search"));
-	gtk_notebook_append_page(GTK_NOTEBOOK(p->sb_notebook), p->search, label);
-
-	gtk_notebook_set_current_page(GTK_NOTEBOOK(p->sb_notebook), 0);
-	gtk_widget_show_all(p->sb_notebook);
-
-	label = gtk_label_new(_("Devhelp"));
-	gtk_notebook_append_page(GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook), p->sb_notebook, label);
-
-	p->sb_notebook_tab = gtk_notebook_page_num(GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook), p->sb_notebook);
-}
-
-
-/* Called when a new plugin is being initialized */
-static void devhelp_plugin_init(DevhelpPlugin * self)
-{
-	DevhelpPluginPrivate *p;
-
-	g_return_if_fail(self != NULL);
-
-	self->priv = p = G_TYPE_INSTANCE_GET_PRIVATE(self, DEVHELP_TYPE_PLUGIN, DevhelpPluginPrivate);
-	devhelp_plugin_init_dh(self);
-
-	p->in_message_window = FALSE;
-	p->tabs_toggled = FALSE;
-
-	p->doc_notebook = geany->main_widgets->notebook;
-	p->main_notebook = main_notebook_get(); /* see main-notebook.c */
-	p->have_man = system("man --version") == 0;
-
-	devhelp_plugin_init_edit_menu(self);
-	devhelp_plugin_init_sidebar(self);
-	devhelp_plugin_init_webkit(self);
-
-	p->last_main_tab_id = gtk_notebook_get_current_page(GTK_NOTEBOOK(p->main_notebook));
-	p->last_sb_tab_id = gtk_notebook_get_current_page(GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook));
-}
-
-
-DevhelpPlugin *devhelp_plugin_new(void)
-{
-	return g_object_new(DEVHELP_TYPE_PLUGIN, NULL);
-}
-
-
-void devhelp_plugin_search(DevhelpPlugin *self, const gchar *term)
-{
-	/* todo: fallback on manpages */
-	devhelp_plugin_search_books(self, term);
-}
-
-
-/**
- * Search for a term in Devhelp and activate/show the plugin's UI stuff.
- *
- * @param dhplug	Devhelp plugin
- * @param term		The string to search for
- */
-void devhelp_plugin_search_books(DevhelpPlugin *self, const gchar *term)
-{
-
-	g_return_if_fail(self != NULL);
-	g_return_if_fail(term != NULL);
-
-	dh_search_set_search_string(DH_SEARCH(self->priv->search), term, NULL);
-
-	devhelp_plugin_activate_all_tabs(self);
-}
-
-
-/**
- * Search for a term in Manual Pages and activate/show the plugin's UI stuff.
- *
- * @param dhplug	Devhelp plugin
- * @param term		The string to search for
- */
-void devhelp_plugin_search_manpages(DevhelpPlugin *self, const gchar *term)
-{
-	gchar *man_fn;
-
-	g_return_if_fail(self != NULL);
-	g_return_if_fail(term != NULL);
-
-	man_fn = devhelp_plugin_manpages_search(term, NULL);
-
-	if (man_fn == NULL)
-		return;
-
-	webkit_web_view_open(WEBKIT_WEB_VIEW(self->priv->webview), man_fn);
-
-	g_free(man_fn);
-
-	devhelp_plugin_activate_webview_tab(self);
-}
-
-
-/**
- * Cleans up a word/tag before searching.
- *
- * Replaces non @c GEANY_WORDCHARS in str with spaces and then trims whitespace.
- * This function does not allocate a new string, it modifies @a str in place
- * and returns a pointer to @a str.
- * TODO: make this only remove stuff from the start or end of string.
- *
- * @param	str	String to clean
- *
- * @return Pointer to (cleaned) @a str.
- */
-gchar *devhelp_plugin_clean_word(gchar* str)
-{
-	return g_strstrip(g_strcanon(str, GEANY_WORDCHARS, ' '));
-}
-
-/**
- * Gets either the current selection or the word at the current selection.
- *
- * @return Newly allocated string with current tag or NULL no tag.
- */
-gchar *devhelp_plugin_get_current_tag(void)
-{
-	gint pos;
-	gchar *tag = NULL;
-	GeanyDocument *doc = document_get_current();
-
-	if (sci_has_selection(doc->editor->sci))
-		return
-			devhelp_plugin_clean_word(sci_get_selection_contents(doc->editor->sci));
-
-	pos = sci_get_current_position(doc->editor->sci);
-	tag = editor_get_word_at_pos(doc->editor, pos, GEANY_WORDCHARS);
-
-	if (tag == NULL)
-		return NULL;
-
-	if (tag[0] == '\0') {
-		g_free(tag);
-		return NULL;
-	}
-
-	return devhelp_plugin_clean_word(tag);
-}
-
-
-/**
- * Activate the plugin's tabs in the UI.
- *
- * @param dhplug Devhelp plugin
- * @param search_tabs_shown If TRUE, show the sidebar search tab, otherwise
- * 	show the contents tab.
- */
-void devhelp_plugin_activate_ui(DevhelpPlugin *self, gboolean show_search_tab)
-{
-	g_return_if_fail(self != NULL);
-	devhelp_plugin_set_active(self, TRUE);
-	gtk_notebook_set_current_page(GTK_NOTEBOOK(self->priv->sb_notebook), (show_search_tab) ? 1 : 0);
-}
-
-
-/**
- * Get whether or not the plugin's tabs are shown/active in the UI.
- *
- * @param dhplug Devhelp plugin
- */
-gboolean devhelp_plugin_get_active(DevhelpPlugin *dhplug)
-{
-	return dhplug->priv->tabs_toggled;
-}
-
-
-/**
- * Set whether or not the plugin's tabs are shown/active in the UI.
- *
- * @param dhplug Devhelp plugin
- * @param active Whether to show the plugin's tabs or the previous tabs.
- */
-void devhelp_plugin_set_active(DevhelpPlugin *dhplug, gboolean active)
-{
-	DevhelpPluginPrivate *p;
-	GtkNotebook *main_nb, *sbar_nb;
-
-	g_return_if_fail(dhplug != NULL);
-
-	p = dhplug->priv;
-	main_nb = GTK_NOTEBOOK(p->main_notebook);
-	sbar_nb = GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook);
-
-	/* just return if the active state is already correct */
-	if ((active && p->tabs_toggled) || (!active && !p->tabs_toggled))
-		return;
-
-	if (active)
-	{
-		p->last_main_tab_id = gtk_notebook_get_current_page(main_nb);
-		p->last_sb_tab_id = gtk_notebook_get_current_page(sbar_nb);
-		gtk_notebook_set_current_page(main_nb, p->webview_tab);
-		gtk_notebook_set_current_page(sbar_nb, p->sb_notebook_tab);
-		p->tabs_toggled = TRUE;
-	}
-	else
-	{
-		gtk_notebook_set_current_page(main_nb, p->last_main_tab_id);
-		gtk_notebook_set_current_page(sbar_nb, p->last_sb_tab_id);
-		p->tabs_toggled = FALSE;
-	}
-}
-
-
-/**
- * Gets whether the Geany sidebar tabs are in the bottom or their original position.
- *
- * @param self Devhelp plugin.
- */
-gboolean devhelp_plugin_get_sidebar_tabs_bottom(DevhelpPlugin *self)
-{
-	GtkNotebook *nb;
-	g_return_val_if_fail(self != NULL, FALSE);
-	nb = GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook);
-	return gtk_notebook_get_tab_pos(nb) == GTK_POS_BOTTOM;
-}
-
-
-/**
- * Sets whether the Geany sidebar tabs are at the bottom or in their original position.
- *
- * @param self Devhelp plugin.
- * @param bottom If TRUE, set the sidebar tab position to @c GTK_POS_BOTTOM
- * otherwise set back to original position.
- */
-void devhelp_plugin_set_sidebar_tabs_bottom(DevhelpPlugin *self, gboolean bottom)
-{
-	GtkNotebook *nb;
-	g_return_if_fail(self != NULL);
-	nb = GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook);
-	gtk_notebook_set_tab_pos(nb, bottom ? GTK_POS_BOTTOM : self->priv->orig_sb_tab_pos);
-}
-
-
-/**
- * Gets the last URI loaded in the webview.
- *
- * @param self Devhelp plugin.
- *
- * @return The last URI loaded in the webview.  This is an internal pointer,
- * do not modify or free.
- */
-const gchar *devhelp_plugin_get_last_uri(DevhelpPlugin *self)
-{
-	g_return_val_if_fail(self != NULL, NULL);
-	/* return webkit_web_view_get_uri(WEBKIT_WEB_VIEW(self->priv->webview)); */
-	return (const gchar *)self->priv->last_uri;
-}
-
-
-/**
- * Gets whether the Documentation tab is in a main_notebook or in the
- * message window.
- *
- * @param self Devhelp plugin.
- *
- * @return TRUE if the Documentation tab is in a main_notebok or FALSE if it's
- * in the message window notebook.
- */
-gboolean devhelp_plugin_get_is_in_msgwin(DevhelpPlugin *self)
-{
-	g_return_val_if_fail(self != NULL, FALSE);
-	return self->priv->in_message_window;
-}
-
-
-/**
- * Sets whether the Documentation tab is in the message window notebook or is
- * in a main_notebook.
- *
- * @param self Devhelp plugin.
- * @param in_msgwin TRUE to move the Documentation tab to the message window
- * notebook or FALSE to create a main_notebook and put it there.
- */
-void devhelp_plugin_set_is_in_msgwin(DevhelpPlugin *self, gboolean in_msgwin)
-{
-	GtkWidget *docs_notebook, *parent;
-
-	g_return_if_fail(self != NULL);
-
-	if (self->priv->in_message_window && !in_msgwin)
-	{
-		/* move from message win to main notebook */
-		self->priv->main_notebook = main_notebook_get();
-
-		//gtk_notebook_append_page(GTK_NOTEBOOK(self->priv->main_notebook),
-		//	self
-	}
-	else if (!self->priv->in_message_window && in_msgwin)
-	{
-		/* move from main notebook to message win */
-		gtk_widget_reparent(
-			gtk_notebook_get_nth_page(GTK_NOTEBOOK(self->priv->main_notebook), self->priv->webview_tab),
-			geany->main_widgets->message_window_notebook);
-
-		/* remove the main notebook and put the documents notebook back */
-		parent = gtk_widget_get_parent(self->priv->main_notebook);
-		docs_notebook = gtk_widget_ref(geany->main_widgets->notebook);
-		gtk_container_remove(GTK_CONTAINER(parent), self->priv->main_notebook);
-		main_notebook_destroy();
-		gtk_container_add(GTK_CONTAINER(parent), docs_notebook);
-		gtk_widget_unref(docs_notebook);
-
-		self->priv->main_notebook = geany->main_widgets->message_window_notebook;
-	}
-
-	self->priv->in_message_window = in_msgwin;
-}
-
-
-/**
- * Gets the zoom level of the WebKit WebView.
- *
- * @param self Devhelp plugin.
- *
- * @return The zoom level.
- */
-gfloat devhelp_plugin_get_zoom_level(DevhelpPlugin *self)
-{
-	g_return_val_if_fail(self != NULL, 0.0F);
-	self->priv->zoom_level = webkit_web_view_get_zoom_level(WEBKIT_WEB_VIEW(self->priv->webview));
-	return self->priv->zoom_level;
-}
-
-
-/**
- * Sets the zoom level of the WebKit WebView.
- *
- * @param self Devhelp plugin.
- * @param zoom_level The zoom level to set.
- */
-void devhelp_plugin_set_zoom_level(DevhelpPlugin *self, gfloat zoom_level)
-{
-	g_return_if_fail(self != NULL);
-	self->priv->zoom_level = zoom_level;
-	webkit_web_view_set_zoom_level(WEBKIT_WEB_VIEW(self->priv->webview), zoom_level);
-}
-
-
-/**
- * Get the current URI from the WebKit WebView.
- *
- * @param self Devhelp plugin.
- *
- * @return The URI in the webview.  This is an internal value, do not free or
- * modify it.
- */
-const gchar* devhelp_plugin_get_webview_uri(DevhelpPlugin *self)
-{
-	g_return_val_if_fail(self != NULL, NULL);
-
-	return webkit_web_view_get_uri(WEBKIT_WEB_VIEW(self->priv->webview));
-}
-
-
-/**
- * Loads the specified @a uri in the WebKit WebView.
- *
- * @param self Devhelp plugin.
- * @param uri The URI to load in the webview.
- */
-void devhelp_plugin_set_webview_uri(DevhelpPlugin *self, const gchar *uri)
-{
-	g_return_if_fail(self != NULL);
-	g_return_if_fail(uri != NULL);
-
-	webkit_web_view_open(WEBKIT_WEB_VIEW(self->priv->webview), uri);
-}
-
-
-WebKitWebView* devhelp_plugin_get_webview(DevhelpPlugin *self)
-{
-	g_return_val_if_fail(self != NULL, NULL);
-	return WEBKIT_WEB_VIEW(self->priv->webview);
-}
-
-
-gboolean devhelp_plugin_get_have_man(DevhelpPlugin *self)
-{
-	g_return_val_if_fail(self != NULL, FALSE);
-	return self->priv->have_man;
-}
-
-
-/* Activates (brings to top/makes visible) the Devhelp plugin's sidebar tab. */
-static inline void devhelp_plugin_activate_sidebar_tab(DevhelpPlugin *self)
-{
-	gint current_tab_id;
-
-	g_return_if_fail(self != NULL);
-
-	current_tab_id = gtk_notebook_get_current_page(GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook));
-	if (current_tab_id != self->priv->sb_notebook_tab)
-		self->priv->last_sb_tab_id = current_tab_id;
-
-	gtk_widget_set_visible(self->priv->sb_notebook, TRUE);
-	gtk_notebook_set_current_page(GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook),
-		self->priv->sb_notebook_tab);
-}
-
-
-/**
- * Activates the Devhelp plugin's sidebar tab, and then the internal notebook's
- * Search tab.
- *
- * @param self Devhelp plugin.
- */
-void devhelp_plugin_activate_search_tab(DevhelpPlugin *self)
-{
-	g_return_if_fail(self != NULL);
-	devhelp_plugin_activate_sidebar_tab(self);
-	gtk_notebook_set_current_page(GTK_NOTEBOOK(self->priv->sb_notebook), 1);
-}
-
-
-/**
- * Activates the Devhelp plugin's sidebar tab, and then the internal notebook's
- * Contents tab.
- *
- * @param self Devhelp plugin.
- */
-void devhelp_plugin_activate_contents_tab(DevhelpPlugin *self)
-{
-	g_return_if_fail(self != NULL);
-	devhelp_plugin_activate_sidebar_tab(self);
-	gtk_notebook_set_current_page(GTK_NOTEBOOK(self->priv->sb_notebook), 0);
-}
-
-
-/**
- * Activates the Devhelp plugin's main notebook's Documentation tab.
- *
- * @param self Devhelp plugin.
- */
-void devhelp_plugin_activate_webview_tab(DevhelpPlugin *self)
-{
-	gint current_tab_id;
-
-	g_return_if_fail(self != NULL);
-
-	current_tab_id = gtk_notebook_get_current_page(GTK_NOTEBOOK(self->priv->main_notebook));
-	if (current_tab_id != self->priv->webview_tab)
-		self->priv->last_main_tab_id = current_tab_id;
-
-	gtk_notebook_set_current_page(GTK_NOTEBOOK(self->priv->main_notebook),
-		self->priv->webview_tab);
-}
-
-
-/* Toggles the Devhelp tab in the Geany sidebar notebook. */
-static inline void devhelp_plugin_toggle_sidebar_tab(DevhelpPlugin *self, gint tab)
-{
-	GtkNotebook *sbar_nb;
-	gint current_tab_id;
-
-	g_return_if_fail(self != NULL);
-
-	sbar_nb = GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook);
-	current_tab_id = gtk_notebook_get_current_page(sbar_nb);
-
-	if (current_tab_id == self->priv->sb_notebook_tab)
-		gtk_notebook_set_current_page(sbar_nb, self->priv->last_sb_tab_id);
-	else
-	{
-		if (tab == 0)
-			devhelp_plugin_activate_contents_tab(self);
-		else if (tab == 1)
-			devhelp_plugin_activate_search_tab(self);
-		else
-			g_warning("Can't toggle to unknown tab ID: %d", tab);
-	}
-}
-
-
-/**
- * Toggle's between the Devhelp plugin's search tab and the previous Geany
- * sidebar tab.
- *
- * @param self Devhelp plugin.
- */
-void devhelp_plugin_toggle_search_tab(DevhelpPlugin *self)
-{
-	devhelp_plugin_toggle_sidebar_tab(self, 1);
-}
-
-
-/**
- * Toggle's between the Devhelp plugin's contents tab and the previous Geany
- * sidebar tab.
- *
- * @param self Devhelp plugin.
- */
-void devhelp_plugin_toggle_contents_tab(DevhelpPlugin *self)
-{
-	devhelp_plugin_toggle_sidebar_tab(self, 0);
-}
-
-
-/**
- * Toggle's between the Devhelp plugin's main notebook tab and the previous
- * main notebook tab.
- *
- * @param self Devhelp plugin.
- */
-void devhelp_plugin_toggle_webview_tab(DevhelpPlugin *self)
-{
-	gint current_tab_id;
-
-	g_return_if_fail(self != NULL);
-
-	current_tab_id = gtk_notebook_get_current_page(GTK_NOTEBOOK(self->priv->main_notebook));
-	if (current_tab_id == self->priv->last_main_tab_id)
-	{
-		gtk_notebook_set_current_page(GTK_NOTEBOOK(self->priv->main_notebook),
-			self->priv->last_main_tab_id);
-	}
-	else
-		devhelp_plugin_activate_webview_tab(self);
-}
-
-
-/**
- * Activates/shows all the Devhelp plugins tabs.
- *
- * @param self Devhelp plugin.
- */
-void devhelp_plugin_activate_all_tabs(DevhelpPlugin *self)
-{
-	devhelp_plugin_activate_sidebar_tab(self);
-	devhelp_plugin_activate_webview_tab(self);
-}
-
-
-/* Called when the editor menu item is selected */
-static void on_search_help_activate(GtkMenuItem * menuitem, DevhelpPlugin *self)
-{
-	gchar *current_tag;
-
-	g_return_if_fail(self != NULL);
-
-	if ((current_tag = devhelp_plugin_get_current_tag()) == NULL)
-		return;
-
-	devhelp_plugin_search_books(self, current_tag);
-
-	g_free(current_tag);
-}
-
-
-/* Called when the editor menu item is selected */
-static void on_search_help_man_activate(GtkMenuItem * menuitem, DevhelpPlugin *self)
-{
-	gchar *current_tag;
-
-	g_return_if_fail(self != NULL);
-
-	if ((current_tag = devhelp_plugin_get_current_tag()) == NULL)
-		return;
-
-	devhelp_plugin_search_manpages(self, current_tag);
-
-	g_free(current_tag);
-}
-
-
-static void on_search_help_code_activate(GtkMenuItem *menuitem, DevhelpPlugin *self)
-{
-	gchar *current_tag;
-	const gchar *lang = NULL;
-	GeanyDocument *doc;
-
-	g_return_if_fail(self != NULL);
-
-	if ((current_tag = devhelp_plugin_get_current_tag()) == NULL)
-		return;
-
-	doc = document_get_current();
-	if (doc != NULL && doc->file_type != NULL && doc->file_type->name != NULL)
-		lang = doc->file_type->name;
-
-	devhelp_plugin_search_code(self, current_tag, lang);
-
-	g_free(current_tag);
-}
-
-
-/*
- * Called when the editor context menu is shown so that the devhelp
- * search item can be disabled if there isn't a selected tag.
- */
-static void on_editor_menu_popup(GtkWidget * widget, DevhelpPlugin *self)
-{
-	gchar *label_tag, *curword, *new_label;
-
-	g_return_if_fail(self != NULL);
-
-	curword = devhelp_plugin_get_current_tag();
-
-	if (curword == NULL)
-	{
-		gtk_widget_set_sensitive(self->priv->editor_menu_item, FALSE);
-		return;
-	}
-
-	label_tag = g_strstrip(g_strndup(curword, DHPLUG_MAX_LABEL_TAG));
-	new_label = g_strdup_printf(_("Search for '%s' Documentation in"), label_tag);
-
-	gtk_menu_item_set_label(GTK_MENU_ITEM(self->priv->editor_menu_item), new_label);
-
-	g_free(new_label);
-	g_free(label_tag);
-
-	gtk_widget_set_sensitive(self->priv->editor_menu_item, TRUE);
-
-	g_free(curword);
-}
-
-
-/*
- * Called when a link in either the contents or search areas on the sidebar
- * have a link clicked on, meaning to load that file into the webview.
- */
-static void on_link_clicked(GObject * ignored, DhLink * dhlink, DevhelpPlugin *self)
-{
-	g_return_if_fail(self != NULL);
-
-	if (self->priv->last_uri != NULL)
-		g_free(self->priv->last_uri);
-
-	self->priv->last_uri = dh_link_get_uri(dhlink);
-	webkit_web_view_open(WEBKIT_WEB_VIEW(self->priv->webview), self->priv->last_uri);
-	gtk_notebook_set_current_page(GTK_NOTEBOOK(self->priv->main_notebook), self->priv->webview_tab);
-}
-
-
-static void on_back_button_clicked(GtkToolButton * btn, DevhelpPlugin *self)
-{
-	g_return_if_fail(self != NULL);
-	webkit_web_view_go_back(WEBKIT_WEB_VIEW(self->priv->webview));
-}
-
-
-static void on_forward_button_clicked(GtkToolButton * btn, DevhelpPlugin *self)
-{
-	g_return_if_fail(self != NULL);
-	webkit_web_view_go_forward(WEBKIT_WEB_VIEW(self->priv->webview));
-}
-
-
-static void on_zoom_in_button_clicked(GtkToolButton * btn, DevhelpPlugin *self)
-{
-	WebKitWebView *view;
-
-	g_return_if_fail(self != NULL);
-
-	view = WEBKIT_WEB_VIEW(self->priv->webview);
-	webkit_web_view_zoom_in(view);
-	self->priv->zoom_level = webkit_web_view_get_zoom_level(view);
-}
-
-
-static void on_zoom_out_button_clicked(GtkToolButton *btn, DevhelpPlugin *self)
-{
-	WebKitWebView *view;
-
-	g_return_if_fail(self != NULL);
-
-	view = WEBKIT_WEB_VIEW(self->priv->webview);
-	webkit_web_view_zoom_out(view);
-	self->priv->zoom_level = webkit_web_view_get_zoom_level(view);
-}
-
-
-/* Controls the sensitivity of the back/forward buttons when webkit page changes. */
-static inline void update_history_buttons(DevhelpPlugin *self)
-{
-	WebKitWebView *view;
-
-	g_return_if_fail(self != NULL);
-
-	view = WEBKIT_WEB_VIEW(self->priv->webview);
-
-	gtk_widget_set_sensitive(GTK_WIDGET(self->priv->btn_back),
-		webkit_web_view_can_go_back(view));
-	gtk_widget_set_sensitive(GTK_WIDGET(self->priv->btn_forward),
-		webkit_web_view_can_go_forward(view));
-}
-
-
-static void on_document_load_finished(WebKitWebView *view, WebKitWebFrame *frame, DevhelpPlugin *self)
-{
-	update_history_buttons(self);
-}
-
-
-static void on_uri_changed_notify(GObject *object, GParamSpec *pspec, DevhelpPlugin *self)
-{
-	update_history_buttons(self);
-}
-
-
-static void on_load_status_changed_notify(GObject *object, GParamSpec *pspec, DevhelpPlugin *self)
-{
-	update_history_buttons(self);
-}
-

Deleted: trunk/geany-plugins/devhelp/src/devhelpplugin.h
===================================================================
--- trunk/geany-plugins/devhelp/src/devhelpplugin.h	2011-05-23 11:30:31 UTC (rev 2081)
+++ trunk/geany-plugins/devhelp/src/devhelpplugin.h	2011-05-24 09:04:06 UTC (rev 2082)
@@ -1,116 +0,0 @@
-/*
- * devhelpplugin.h
- *
- * Copyright 2011 Matthew Brush <mbrush at leftclick.ca>
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef DEVHELP_PLUGIN_COMMON_H
-#define DEVHELP_PLUGIN_COMMON_H
-
-#include <gtk/gtk.h>
-#include <webkit/webkitwebview.h>
-
-G_BEGIN_DECLS
-
-
-#ifndef DHPLUG_DATA_DIR
-#define DHPLUG_DATA_DIR "/usr/local/share/geany-devhelp"
-#endif
-
-#define DHPLUG_WEBVIEW_HOME_FILE DHPLUG_DATA_DIR "/home.html"
-#define DHPLUG_MAX_LABEL_TAG 30 /* never search for more than this many chars */
-
-#define DEVHELP_TYPE_PLUGIN				(devhelp_plugin_get_type())
-#define DEVHELP_PLUGIN(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), DEVHELP_TYPE_PLUGIN, DevhelpPlugin))
-#define DEVHELP_PLUGIN_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), DEVHELP_TYPE_PLUGIN, DevhelpPluginClass))
-#define DEVHELP_IS_PLUGIN(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), DEVHELP_TYPE_PLUGIN))
-#define DEVHELP_IS_PLUGIN_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), DEVHELP_TYPE_PLUGIN))
-#define DEVHELP_PLUGIN_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), DEVHELP_TYPE_PLUGIN, DevhelpPluginClass))
-
-
-typedef struct	_DevhelpPlugin			DevhelpPlugin;
-typedef struct	_DevhelpPluginClass		DevhelpPluginClass;
-typedef struct	_DevhelpPluginPrivate	DevhelpPluginPrivate;
-
-
-struct _DevhelpPlugin
-{
-    GObject parent;
-    DevhelpPluginPrivate *priv;
-};
-
-
-struct _DevhelpPluginClass
-{
-    GObjectClass parent_class;
-};
-
-
-GType			devhelp_plugin_get_type				(void);
-DevhelpPlugin*	devhelp_plugin_new					(void);
-
-gchar*			devhelp_plugin_clean_word			(gchar *str);
-gchar*			devhelp_plugin_get_current_tag		(void);
-
-const gchar*	devhelp_plugin_get_webview_uri		(DevhelpPlugin *self);
-void			devhelp_plugin_set_webview_uri		(DevhelpPlugin *self, const gchar *uri);
-
-gboolean		devhelp_plugin_get_sidebar_tabs_bottom	(DevhelpPlugin *self);
-void			devhelp_plugin_set_sidebar_tabs_bottom	(DevhelpPlugin *self, gboolean bottom);
-
-gboolean		devhelp_plugin_get_active			(DevhelpPlugin *self);
-void			devhelp_plugin_set_active			(DevhelpPlugin *self, gboolean active);
-
-gboolean		devhelp_plugin_get_is_in_msgwin		(DevhelpPlugin *self);
-void			devhelp_plugin_set_is_in_msgwin		(DevhelpPlugin *self, gboolean in_msgwin);
-
-void			devhelp_plugin_activate_ui			(DevhelpPlugin *self, gboolean show_search_tab);
-void 			devhelp_plugin_search				(DevhelpPlugin *self, const gchar *term);
-void 			devhelp_plugin_search_books			(DevhelpPlugin *self, const gchar *term);
-void 			devhelp_plugin_search_manpages		(DevhelpPlugin *self, const gchar *term);
-void			devhelp_plugin_search_code			(DevhelpPlugin *self, const gchar *term, const gchar *lang);
-
-const gchar*	devhelp_plugin_get_last_uri			(DevhelpPlugin *self);
-void			devhelp_plugin_set_last_uri			(DevhelpPlugin *self, const gchar *uri);
-
-gfloat			devhelp_plugin_get_zoom_level		(DevhelpPlugin *self);
-void			devhelp_plugin_set_zoom_level		(DevhelpPlugin *self, gfloat zoom_level);
-
-void			devhelp_plugin_activate_search_tab		(DevhelpPlugin *self);
-void			devhelp_plugin_activate_contents_tab	(DevhelpPlugin *self);
-void			devhelp_plugin_activate_webview_tab		(DevhelpPlugin *self);
-void			devhelp_plugin_activate_all_tabs		(DevhelpPlugin *self);
-
-void			devhelp_plugin_toggle_search_tab		(DevhelpPlugin *self);
-void			devhelp_plugin_toggle_contents_tab		(DevhelpPlugin *self);
-void			devhelp_plugin_toggle_webview_tab		(DevhelpPlugin *self);
-
-WebKitWebView*	devhelp_plugin_get_webview				(DevhelpPlugin *self);
-
-gboolean		devhelp_plugin_get_have_man				(DevhelpPlugin *self);
-
-
-gchar *devhelp_plugin_manpages_search(const gchar *term, const gchar *section);
-void devhelp_plugin_remove_manpages_temp_files(void);
-
-
-void devhelp_plugin_search_code(DevhelpPlugin *self, const gchar *term, const gchar *lang);
-
-
-G_END_DECLS
-#endif /* DEVHELP_PLUGIN_H */

Copied: trunk/geany-plugins/devhelp/src/dhp-codesearch.c (from rev 2081, trunk/geany-plugins/devhelp/src/codesearch.c)
===================================================================
--- trunk/geany-plugins/devhelp/src/dhp-codesearch.c	                        (rev 0)
+++ trunk/geany-plugins/devhelp/src/dhp-codesearch.c	2011-05-24 09:04:06 UTC (rev 2082)
@@ -0,0 +1,96 @@
+#include <glib.h>
+#include <webkit/webkitwebview.h>
+
+#include "dhp.h"
+
+
+struct LangMapEnt
+{
+	const gchar *geany_name;
+	const gchar *google_name;
+};
+
+
+#define GOOGLE_CODE_SEARCH_URI "http://www.google.com/codesearch"
+
+#define LANG_MAP_MAX 33 /* update this with lang_map[] size below */
+
+/* maps Geany language names to Google Code language names */
+static const struct LangMapEnt lang_map[LANG_MAP_MAX] = {
+	{ "ActionScript", "actionscript" },
+	{ "Ada", "ada" },
+	{ "ASM", "assembly" },
+	{ "FreeBasic", "basic" },
+	{ "C", "c" },
+	{ "C++", "c++" },
+	{ "C#", "c#" },
+	{ "COBOL", "cobol" },
+	{ "CSS", "css" },
+	{ "D", "d" },
+	{ "Erlang", "erlang" },
+	{ "Fortran", "fortran" },
+	{ "Haskell", "haskell" },
+	{ "Java", "java" },
+	{ "Javascript", "javascript" },
+	{ "Lisp", "lisp" },
+	{ "Lua", "lua" },
+	{ "Make", "makefile" },
+	{ "Matlab/Octave", "matlab" },
+	{ "CAML", "ocaml" },
+	{ "Pascal", "pascal" },
+	{ "Perl", "perl" },
+	{ "PHP", "php" },
+	{ "Python", "python" },
+	{ "R", "r" },
+	{ "Ruby", "ruby" },
+	{ "Sh", "shell" },
+	{ "SQL", "sql" },
+	{ "Tcl", "tcl" },
+	{ "LaTeX", "tex" },
+	{ "Verilog", "verilog" },
+	{ "VHDL", "vhdl" },
+	{ "None", NULL }
+};
+
+
+void devhelp_plugin_search_code(DevhelpPlugin *self, const gchar *term, const gchar *lang)
+{
+	gint i;
+	gchar *uri, *term_enc, *lang_enc;
+	const gchar *google_lang = NULL;
+
+	g_return_if_fail(self != NULL);
+	g_return_if_fail(term != NULL);
+
+	if (lang != NULL)
+	{
+		for (i = 0; i < LANG_MAP_MAX; i++)
+		{
+			if (g_strcmp0(lang, lang_map[i].geany_name) == 0)
+			{
+				google_lang = lang_map[i].google_name;
+				break;
+			}
+		}
+	}
+
+	if (google_lang != NULL)
+	{
+		lang_enc = g_uri_escape_string(google_lang, NULL, TRUE);
+		term_enc = g_uri_escape_string(term, NULL, TRUE);
+		uri = g_strdup_printf("%s?as_q=%s&as_lang=%s", GOOGLE_CODE_SEARCH_URI, term_enc, lang_enc);
+		g_free(lang_enc);
+		g_free(term_enc);
+	}
+	else
+	{
+		term_enc = g_uri_escape_string(term, NULL, TRUE);
+		uri = g_strdup_printf("%s?as_q=%s", GOOGLE_CODE_SEARCH_URI, term_enc);
+		g_free(term_enc);
+	}
+
+	webkit_web_view_open(devhelp_plugin_get_webview(self), uri);
+	g_free(uri);
+
+	devhelp_plugin_activate_webview_tab(self);
+}

Added: trunk/geany-plugins/devhelp/src/dhp-manpages.c
===================================================================
--- trunk/geany-plugins/devhelp/src/dhp-manpages.c	                        (rev 0)
+++ trunk/geany-plugins/devhelp/src/dhp-manpages.c	2011-05-24 09:04:06 UTC (rev 2082)
@@ -0,0 +1,234 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <glib.h>
+
+#include "dhp.h"
+
+
+#define DEVHELP_PLUGIN_MANPAGE_SECTIONS "3:2:1:8:5:4:7:6"
+#define DEVHELP_PLUGIN_MANPAGE_PAGER "col -b"
+
+#define DEVHELP_PLUGIN_MANPAGE_HTML_TEMPLATE \
+	"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd\">\n" \
+	"<html>\n"									\
+	"  <head>\n"								\
+	"    <title>%s</title>\n"					\
+	"    <style type=\"text/css\">\n"			\
+	"      .man_text {\n"						\
+	"        /*font-family: sans;*/\n"			\
+	"      }\n"									\
+	"    </style>\n"							\
+	"  </head>\n"								\
+	"  <body>\n"								\
+	"    <pre class=\"man_text\">%s</pre>\n"	\
+	"  </body>\n"								\
+	"</html>\n"
+
+
+/* Locates the path to the manpage found for the term and section. */
+static gchar *devhelp_plugin_find_manpage_path(DevhelpPlugin *self, const gchar *term, const gchar *section)
+{
+	gint retcode=0;
+	gchar *cmd, *path=NULL;
+	const gchar *man_path;
+
+	g_return_val_if_fail(self != NULL, NULL);
+	g_return_val_if_fail(term != NULL, NULL);
+
+	if ((man_path = devhelp_plugin_get_man_prog_path(self)) == NULL)
+		man_path = "man";
+
+	if (section == NULL)
+	{
+		cmd = g_strdup_printf("%s -S %s --where '%s'", man_path,
+				DEVHELP_PLUGIN_MANPAGE_SECTIONS, term);
+	}
+	else
+		cmd = g_strdup_printf("%s --where %s '%s'", man_path, section, term);
+
+	if (!g_spawn_command_line_sync(cmd, &path, NULL, &retcode, NULL))
+	{
+		g_free(cmd);
+		return NULL;
+	}
+
+	g_free(cmd);
+
+	if (retcode != 0)
+	{
+		g_free(path);
+		return NULL;
+	}
+
+	return g_strstrip(path);
+}
+
+
+/* Read the text output from man or NULL. */
+static gchar *devhelp_plugin_read_man_text(DevhelpPlugin *self, const gchar *filename)
+{
+	gint retcode=0;
+	gchar *cmd, *text=NULL;
+	const gchar *man_path;
+
+	g_return_val_if_fail(self != NULL, NULL);
+	g_return_val_if_fail(filename != NULL, NULL);
+
+	if ((man_path = devhelp_plugin_get_man_prog_path(self)) == NULL)
+		man_path = "man";
+
+	cmd = g_strdup_printf("%s -P\"%s\" \'%s\'", man_path,
+			DEVHELP_PLUGIN_MANPAGE_PAGER, filename);
+
+	if (!g_spawn_command_line_sync(cmd, &text, NULL, &retcode, NULL))
+	{
+		g_free(cmd);
+		return NULL;
+	}
+
+	g_free(cmd);
+
+	if (retcode != 0)
+	{
+		g_free(text);
+		return NULL;
+	}
+
+	return text;
+}
+
+
+/**
+ * Searches for a manual page, and if it finds one, writes its text into a
+ * <pre> section in an HTML file, and returns the URI of the HTML file which
+ * can be loaded into the webview.
+ *
+ * @param self Devhelp plugin.
+ * @param term The search term to look for.
+ * @param section The manual page section to look in or NULL.
+ *
+ * @return The URI to a temporary HTML file containing the man page text or
+ * NULL on error.
+ */
+gchar *devhelp_plugin_manpages_search(DevhelpPlugin *self, const gchar *term, const gchar *section)
+{
+	FILE *fp = NULL;
+	gint fd = -1, len;
+	gchar *man_fn = NULL, *tmp_fn = NULL, *uri = NULL;
+	gchar *text = NULL, *html_text = NULL;
+	const gchar *tmpl = "devhelp_manpage_XXXXXX.html";
+
+	g_return_val_if_fail(self != NULL, NULL);
+	g_return_val_if_fail(term != NULL, NULL);
+
+	if ((man_fn = devhelp_plugin_find_manpage_path(self, term, section)) == NULL)
+		goto error;
+
+	if ((fd = g_file_open_tmp(tmpl, &tmp_fn, NULL)) == -1)
+		goto error;
+
+	if ((fp = fdopen(fd, "w")) == NULL)
+		goto error;
+
+	if ((text = devhelp_plugin_read_man_text(self, man_fn)) == NULL)
+		goto error;
+
+	html_text = g_strdup_printf(DEVHELP_PLUGIN_MANPAGE_HTML_TEMPLATE, term, text);
+
+	len = strlen(html_text);
+	if (fwrite(html_text, sizeof(gchar), len, fp) != len)
+		goto error;
+
+	devhelp_plugin_add_temp_file(self, tmp_fn);
+
+	uri = g_filename_to_uri(tmp_fn, NULL, NULL);
+
+	g_free(man_fn);
+	g_free(tmp_fn);
+	g_free(text);
+	g_free(html_text);
+
+	fclose(fp);
+
+	return uri;
+
+error:
+	g_free(man_fn);
+	g_free(tmp_fn);
+	g_free(text);
+	g_free(html_text);
+	g_free(uri);
+	if (fp != NULL)
+		fclose(fp);
+	return NULL;
+}
+
+
+/**
+ * Removes temporary files made by the plugin and frees the stored filenames
+ * and the list used to hold them.
+ *
+ * @param self Devhelp plugin.
+ */
+void devhelp_plugin_remove_manpages_temp_files(DevhelpPlugin *self)
+{
+	GList *temp_files, *iter;
+
+	g_return_if_fail(self != NULL);
+
+	temp_files = devhelp_plugin_get_temp_files(self);
+
+	if (temp_files == NULL)
+		return;
+
+	for (iter = temp_files; iter != NULL; iter = iter->next)
+	{
+		if (remove(iter->data) == -1)
+			g_warning("Unable to delete temp file: %s", strerror(errno));
+		g_free(iter->data);
+	}
+
+	g_list_free(temp_files);
+}
+
+
+/**
+ * Adds a filename to the list of temp files to be deleted later.
+ *
+ * @param self Devhelp plugin.
+ * @param filename The filename to track for future removal.
+ */
+void devhelp_plugin_add_temp_file(DevhelpPlugin *self, const gchar *filename)
+{
+	GList *temp_files;
+
+	g_return_if_fail(self != NULL);
+
+	temp_files = devhelp_plugin_get_temp_files(self);
+	temp_files = g_list_append(temp_files, g_strdup(filename));
+}
+
+/**
+ * Search for a term in Manual Pages and activate/show the plugin's UI stuff.
+ *
+ * @param dhplug	Devhelp plugin
+ * @param term		The string to search for
+ */
+void devhelp_plugin_search_manpages(DevhelpPlugin *self, const gchar *term)
+{
+	gchar *man_fn;
+
+	g_return_if_fail(self != NULL);
+	g_return_if_fail(term != NULL);
+
+	if ((man_fn = devhelp_plugin_manpages_search(self, term, NULL)) == NULL)
+		return;
+
+	devhelp_plugin_set_webview_uri(self, man_fn);
+
+	g_free(man_fn);
+
+	devhelp_plugin_activate_webview_tab(self);
+}

Copied: trunk/geany-plugins/devhelp/src/dhp-object.c (from rev 2081, trunk/geany-plugins/devhelp/src/devhelpplugin.c)
===================================================================
--- trunk/geany-plugins/devhelp/src/dhp-object.c	                        (rev 0)
+++ trunk/geany-plugins/devhelp/src/dhp-object.c	2011-05-24 09:04:06 UTC (rev 2082)
@@ -0,0 +1,1401 @@
+/*
+ * devhelpplugin.c
+ *
+ * Copyright 2011 Matthew Brush <mbrush at leftclick.ca>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <stdlib.h>
+#include <gtk/gtk.h>
+#include <geanyplugin.h>
+
+#include <devhelp/dh-base.h>
+#include <devhelp/dh-book-tree.h>
+#include <devhelp/dh-search.h>
+#include <devhelp/dh-link.h>
+
+#ifdef HAVE_BOOK_MANAGER /* for newer api */
+#include <devhelp/dh-book-manager.h>
+#endif
+
+#include <webkit/webkitwebview.h>
+
+#include "dhp.h"
+#include "dhp-plugin.h"
+
+
+struct _DevhelpPluginPrivate
+{
+	/* Devhelp stuff */
+	DhBase*			dhbase;
+    GtkWidget*		book_tree;			/* "Contents" in the sidebar */
+    GtkWidget*		search;				/* "Search" in the sidebar */
+    GtkWidget*		sb_notebook;		/* Notebook that holds contents/search */
+
+    /* Webview stuff */
+    GtkWidget*		webview;			/* Webkit that shows documentation */
+    GtkWidget*		webview_tab;		/* The widget that has webview related stuff */
+    GtkToolItem*	btn_back;			/* the webkit browser back button in the toolbar */
+    GtkToolItem*	btn_forward;		/* the webkit browser forward button in the toolbar */
+    DevhelpPluginWebViewLocation location; /* where to pack the webview */
+
+	/* Other widgets */
+    GtkWidget*		main_notebook;		/* Notebook that holds Geany doc notebook and and webkit view */
+    GtkWidget*		editor_menu_item;	/* Item in the editor's context menu */
+    GtkWidget*		editor_menu_sep;	/* Separator item above menu item */
+
+	/* Position/tab number tracking */
+    gboolean		last_main_tab_id;	/* These track the last id of the tabs */
+    gboolean		last_sb_tab_id;		/*   before toggling */
+    gboolean		tabs_toggled;		/* Tracks state of whether to toggle to Devhelp or back to code */
+    GtkPositionType	orig_sb_tab_pos;	/* The tab idx of the initial sidebar tab */
+    gboolean		in_message_window;	/* whether the webkit stuff is in the msgwin */
+
+    GList*			temp_files;			/* Tracks temp files made by the plugin to delete later. */
+
+	GKeyFile*	kf;
+	gboolean	focus_webview_on_search;
+	gboolean	focus_sidebar_on_search;
+	gchar*		custom_homepage;
+	gboolean	use_devhelp;
+	gboolean	use_man;
+	gboolean	use_codesearch;
+
+	gchar*		man_prog_path;
+	gchar*		man_pager_prog;
+	gchar*		man_section_order;
+
+	gchar*		codesearch_base_uri;
+	gchar*		codesearch_params;
+	gboolean	codesearch_use_lang;
+
+    GtkPositionType main_nb_tab_pos;
+};
+
+
+G_DEFINE_TYPE(DevhelpPlugin, devhelp_plugin, G_TYPE_OBJECT)
+
+
+enum
+{
+	PROP_0,
+	PROP_CURRENT_WORD,
+	PROP_WEBVIEW_URI,
+	PROP_SIDEBAR_TABS_BOTTOM,
+	PROP_UI_ACTIVE,
+	PROP_IN_MESSAGE_WINDOW,
+	PROP_ZOOM_LEVEL,
+	PROP_WEBVIEW,
+	PROP_TEMP_FILES,
+	PROP_MAN_PROG_PATH,
+	PROP_HAVE_MAN_PROG,
+	PROP_LAST
+};
+
+
+/* Causes problems if it gets re-initialized so leave global for now */
+static DhBase *dhbase = NULL;
+
+
+/* Internal callbacks */
+static void on_search_help_activate(GtkMenuItem * menuitem, DevhelpPlugin *self);
+static void on_search_help_man_activate(GtkMenuItem * menuitem, DevhelpPlugin *self);
+static void on_search_help_code_activate(GtkMenuItem *menuitem, DevhelpPlugin *self);
+static void on_editor_menu_popup(GtkWidget * widget, DevhelpPlugin *self);
+static void on_link_clicked(GObject * ignored, DhLink * dhlink, DevhelpPlugin *self);
+static void on_back_button_clicked(GtkToolButton * btn, DevhelpPlugin *self);
+static void on_forward_button_clicked(GtkToolButton * btn, DevhelpPlugin *self);
+static void on_zoom_in_button_clicked(GtkToolButton * btn, DevhelpPlugin *self);
+static void on_zoom_out_button_clicked(GtkToolButton *btn, DevhelpPlugin *self);
+static void on_document_load_finished(WebKitWebView *view, WebKitWebFrame *frame, DevhelpPlugin *self);
+static void on_uri_changed_notify(GObject *object, GParamSpec *pspec, DevhelpPlugin *self);
+static void on_load_status_changed_notify(GObject *object, GParamSpec *pspec, DevhelpPlugin *self);
+
+/* Misc internal functions */
+static inline void update_history_buttons(DevhelpPlugin *self);
+static inline gchar* clean_word(gchar *str);
+static GtkWidget* devhelp_plugin_ref_unpack_webview_tab(DevhelpPlugin *self);
+static void devhelp_plugin_set_webview_location(DevhelpPlugin *self, DevhelpPluginWebViewLocation location);
+
+
+/* include long boring code from dhp-settings.c */
+#include "dhp-settings.c"
+
+
+static void devhelp_plugin_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+	DevhelpPlugin *self = DEVHELP_PLUGIN(object);
+
+	switch(property_id)
+	{
+		case PROP_WEBVIEW_URI:
+			devhelp_plugin_set_webview_uri(self, g_value_get_string(value));
+			break;
+		case PROP_SIDEBAR_TABS_BOTTOM:
+			devhelp_plugin_set_sidebar_tabs_bottom(self, g_value_get_boolean(value));
+			break;
+		case PROP_UI_ACTIVE:
+			devhelp_plugin_set_ui_active(self, g_value_get_boolean(value));
+			break;
+		case PROP_IN_MESSAGE_WINDOW:
+			devhelp_plugin_set_in_message_window(self, g_value_get_boolean(value));
+			break;
+		case PROP_ZOOM_LEVEL:
+			devhelp_plugin_set_zoom_level(self, g_value_get_float(value));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+			break;
+	}
+}
+
+
+static void devhelp_plugin_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+	DevhelpPlugin *self = DEVHELP_PLUGIN(object);
+
+	switch(property_id)
+	{
+		case PROP_CURRENT_WORD:
+			g_value_set_string(value, devhelp_plugin_get_current_word(self));
+			break;
+		case PROP_WEBVIEW_URI:
+			g_value_set_string(value, devhelp_plugin_get_webview_uri(self));
+			break;
+		case PROP_SIDEBAR_TABS_BOTTOM:
+			g_value_set_boolean(value, devhelp_plugin_get_sidebar_tabs_bottom(self));
+			break;
+		case PROP_UI_ACTIVE:
+			g_value_set_boolean(value, devhelp_plugin_get_ui_active(self));
+			break;
+		case PROP_IN_MESSAGE_WINDOW:
+			g_value_set_boolean(value, devhelp_plugin_get_in_message_window(self));
+			break;
+		case PROP_ZOOM_LEVEL:
+			g_value_set_float(value, devhelp_plugin_get_zoom_level(self));
+			break;
+		case PROP_WEBVIEW:
+			g_value_set_object(value, devhelp_plugin_get_webview(self));
+			break;
+		case PROP_TEMP_FILES:
+			g_value_set_pointer(value, devhelp_plugin_get_temp_files(self));
+			break;
+		case PROP_MAN_PROG_PATH:
+			g_value_set_string(value, devhelp_plugin_get_man_prog_path(self));
+			break;
+		case PROP_HAVE_MAN_PROG:
+			g_value_set_boolean(value, devhelp_plugin_get_have_man_prog(self));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+			break;
+	}
+}
+
+
+/* Put cleanup code in here */
+static void devhelp_plugin_finalize(GObject * object)
+{
+	DevhelpPlugin *self;
+
+	g_return_if_fail(object != NULL);
+	g_return_if_fail(DEVHELP_IS_PLUGIN(object));
+
+	self = DEVHELP_PLUGIN(object);
+
+	devhelp_plugin_set_sidebar_tabs_bottom(self, FALSE);
+	devhelp_plugin_remove_manpages_temp_files(self);
+
+	gtk_widget_destroy(self->priv->sb_notebook);
+
+	gtk_widget_unref(devhelp_plugin_ref_unpack_webview_tab(self));
+
+	gtk_widget_destroy(self->priv->editor_menu_sep);
+	gtk_widget_destroy(self->priv->editor_menu_item);
+
+	g_free(self->priv->man_prog_path);
+	g_free(self->priv->man_pager_prog);
+	g_free(self->priv->man_section_order);
+	g_free(self->priv->codesearch_base_uri);
+	g_free(self->priv->codesearch_params);
+	g_free(self->priv->custom_homepage);
+
+	G_OBJECT_CLASS(devhelp_plugin_parent_class)->finalize(object);
+}
+
+
+static void devhelp_plugin_class_init(DevhelpPluginClass * klass)
+{
+	GObjectClass *g_object_class;
+	GParamSpec *pspec;
+
+	g_object_class = G_OBJECT_CLASS(klass);
+
+	g_object_class->set_property = devhelp_plugin_set_property;
+	g_object_class->get_property = devhelp_plugin_get_property;
+	g_object_class->finalize = devhelp_plugin_finalize;
+
+	pspec = g_param_spec_string(
+				"current-word",
+				"Current word in editor",
+				"Gets the currently selected word, or the word where the cursor is.",
+				NULL,
+				G_PARAM_READABLE);
+	g_object_class_install_property(g_object_class, PROP_CURRENT_WORD, pspec);
+
+	pspec = g_param_spec_string(
+				"webview-uri",
+				"WebKit WebView URI",
+				"Gets or sets the URI loaded in the WebView widget.",
+				DHPLUG_WEBVIEW_HOME_FILE,
+				G_PARAM_READWRITE);
+	g_object_class_install_property(g_object_class, PROP_WEBVIEW_URI, pspec);
+
+	pspec = g_param_spec_boolean(
+				"sidebar-tabs-bottom",
+				"Sidebar tabs on bottom",
+				"Gets or sets whether Geany's sidebar tabs are positioned on the bottom or not.",
+				FALSE,
+				G_PARAM_READWRITE);
+	g_object_class_install_property(g_object_class, PROP_SIDEBAR_TABS_BOTTOM, pspec);
+
+	pspec = g_param_spec_boolean(
+				"ui-active",
+				"UI widgets are active",
+				"Gets or sets whether the plugin's UI widgets are active/selected/visible.",
+				FALSE,
+				G_PARAM_READWRITE);
+	g_object_class_install_property(g_object_class, PROP_UI_ACTIVE, pspec);
+
+	pspec = g_param_spec_boolean(
+				"in-message-window",
+				"Documentation in the message window notebook",
+				"Gets or sets whether the notebook page with the WebKit WebView is located "
+					"in the main documents notebook area or in the message window notebook.",
+				FALSE,
+				G_PARAM_READWRITE);
+	g_object_class_install_property(g_object_class, PROP_IN_MESSAGE_WINDOW, pspec);
+
+	pspec = g_param_spec_float(
+				"zoom-level",
+				"Zoom level of the WebKit WebView",
+				"Gets or sets the zoom level (font size, etc) of the contents of the "
+					"WebKit WebView.",
+				G_MINFLOAT, G_MAXFLOAT/* FIXME */, 1.0F,
+				G_PARAM_READWRITE);
+	g_object_class_install_property(g_object_class, PROP_ZOOM_LEVEL, pspec);
+
+	pspec = g_param_spec_object(
+				"webview",
+				"WebKit WebView",
+				"Gets the WebKit WebView used to display documentation.",
+				WEBKIT_TYPE_WEB_VIEW,
+				G_PARAM_READABLE);
+	g_object_class_install_property(g_object_class, PROP_WEBVIEW, pspec);
+
+	pspec = g_param_spec_pointer(
+				"temp-files",
+				"Temporary files",
+				"Gets the GList used to track temporary files so they can be deleted later.",
+				G_PARAM_READABLE);
+	g_object_class_install_property(g_object_class, PROP_TEMP_FILES, pspec);
+
+	pspec = g_param_spec_string(
+				"man-prog-path",
+				"Manual page program path",
+				"Gets the path to the system's 'man' program if present.",
+				NULL,
+				G_PARAM_READABLE);
+	g_object_class_install_property(g_object_class, PROP_MAN_PROG_PATH, pspec);
+
+	pspec = g_param_spec_boolean(
+				"have-man-prog",
+				"Have manual page program",
+				"Gets whether a manual page program was found on the system.",
+				FALSE,
+				G_PARAM_READABLE);
+	g_object_class_install_property(g_object_class, PROP_HAVE_MAN_PROG, pspec);
+
+	g_type_class_add_private((gpointer) klass, sizeof(DevhelpPluginPrivate));
+}
+
+
+/*
+ * Initialize the Devhelp library/widgets.
+ * The Devhelp API isn't exactly stable, so handle quirks in here.
+ */
+static void devhelp_plugin_init_dh(DevhelpPlugin *self)
+{
+#ifdef HAVE_BOOK_MANAGER /* for newer api */
+	DhBookManager *book_manager;
+#else
+	GNode *books;
+	GList *keywords;
+#endif
+
+	if (dhbase == NULL)
+		dhbase = dh_base_new();
+	self->priv->dhbase = dhbase;
+
+#ifdef HAVE_BOOK_MANAGER /* for newer api */
+	book_manager = dh_base_get_book_manager(self->priv->dhbase);
+	self->priv->book_tree = dh_book_tree_new(book_manager);
+	self->priv->search = dh_search_new(book_manager);
+#else
+	books = dh_base_get_book_tree(self->priv->dhbase);
+	keywords = dh_base_get_keywords(self->priv->dhbase);
+	self->priv->book_tree = dh_book_tree_new(books);
+	self->priv->search = dh_search_new(keywords);
+#endif
+
+	gtk_widget_show(self->priv->search);
+
+	g_signal_connect(self->priv->book_tree, "link-selected", G_CALLBACK(on_link_clicked), self);
+	g_signal_connect(self->priv->search, "link-selected", G_CALLBACK(on_link_clicked), self);
+}
+
+
+/* Initialize the stuff in the editor's context menu */
+static void devhelp_plugin_init_edit_menu(DevhelpPlugin *self)
+{
+	GtkWidget *doc_menu, *devhelp_item, *code_item, *man_item;
+	DevhelpPluginPrivate *p;
+
+	g_return_if_fail(self != NULL);
+
+	p = self->priv;
+
+	p->editor_menu_sep = gtk_separator_menu_item_new();
+	p->editor_menu_item = gtk_menu_item_new_with_label(_("Search for 'Tag' Documentation in"));
+	doc_menu = gtk_menu_new();
+
+	devhelp_item = gtk_menu_item_new_with_label(_("Devhelp"));
+	gtk_menu_shell_append(GTK_MENU_SHELL(doc_menu), devhelp_item);
+	g_signal_connect(devhelp_item, "activate", G_CALLBACK(on_search_help_activate), self);
+	gtk_widget_show(devhelp_item);
+
+	if (devhelp_plugin_get_have_man_prog(self))
+	{
+		man_item = gtk_menu_item_new_with_label(_("Manual Pages"));
+		gtk_menu_shell_append(GTK_MENU_SHELL(doc_menu), man_item);
+		g_signal_connect(man_item, "activate", G_CALLBACK(on_search_help_man_activate), self);
+		gtk_widget_show(man_item);
+	}
+
+	code_item = gtk_menu_item_new_with_label(_("Google Code"));
+	gtk_menu_shell_append(GTK_MENU_SHELL(doc_menu), code_item);
+	g_signal_connect(code_item, "activate", G_CALLBACK(on_search_help_code_activate), self);
+	gtk_widget_show(code_item);
+
+	g_signal_connect(geany->main_widgets->editor_menu, "show", G_CALLBACK(on_editor_menu_popup), self);
+	gtk_menu_item_set_submenu(GTK_MENU_ITEM(p->editor_menu_item), doc_menu);
+	gtk_menu_shell_append(GTK_MENU_SHELL(geany->main_widgets->editor_menu), p->editor_menu_sep);
+	gtk_menu_shell_append(GTK_MENU_SHELL(geany->main_widgets->editor_menu), p->editor_menu_item);
+	gtk_widget_show(p->editor_menu_sep);
+	gtk_widget_show_all(p->editor_menu_item);
+}
+
+
+/* Initialize the WebKit browser and associated widgets */
+static void devhelp_plugin_init_webkit(DevhelpPlugin *self)
+{
+	GtkWidget *vbox, *toolbar;
+	GtkToolItem *btn_zoom_in, *btn_zoom_out, *tb_sep;
+	GtkScrolledWindow *webview_sw;
+	DevhelpPluginPrivate *p;
+
+	g_return_if_fail(self != NULL);
+
+	p = self->priv;
+
+	p->webview = webkit_web_view_new();
+
+	webview_sw = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL));
+	gtk_scrolled_window_set_policy(webview_sw, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+	gtk_scrolled_window_set_shadow_type(webview_sw, GTK_SHADOW_ETCHED_IN);
+	gtk_container_add(GTK_CONTAINER(webview_sw), p->webview);
+
+	gtk_widget_show_all(GTK_WIDGET(webview_sw));
+
+	vbox = gtk_vbox_new(FALSE, 0);
+	toolbar = gtk_toolbar_new();
+
+	p->btn_back = gtk_tool_button_new_from_stock(GTK_STOCK_GO_BACK);
+	p->btn_forward = gtk_tool_button_new_from_stock(GTK_STOCK_GO_FORWARD);
+	btn_zoom_in = gtk_tool_button_new_from_stock(GTK_STOCK_ZOOM_IN);
+	btn_zoom_out = gtk_tool_button_new_from_stock(GTK_STOCK_ZOOM_OUT);
+	tb_sep = gtk_separator_tool_item_new();
+
+	gtk_widget_set_tooltip_text(GTK_WIDGET(p->btn_back), _("Go back one page"));
+	gtk_widget_set_tooltip_text(GTK_WIDGET(p->btn_forward), _("Go forward one page"));
+	gtk_widget_set_tooltip_text(GTK_WIDGET(btn_zoom_in), _("Zoom in"));
+	gtk_widget_set_tooltip_text(GTK_WIDGET(btn_zoom_out), _("Zoom out"));
+
+	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), p->btn_back, -1);
+	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), p->btn_forward, -1);
+	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tb_sep, -1);
+	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), btn_zoom_in, -1);
+	gtk_toolbar_insert(GTK_TOOLBAR(toolbar), btn_zoom_out, -1);
+
+	gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, TRUE, 0);
+	gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(webview_sw), TRUE, TRUE, 0);
+
+	gtk_widget_show_all(vbox);
+	p->webview_tab = vbox;
+	devhelp_plugin_set_webview_location(self, DEVHELP_PLUGIN_WEBVIEW_LOCATION_MAIN_NOTEBOOK);
+
+	g_signal_connect(p->btn_back, "clicked", G_CALLBACK(on_back_button_clicked), self);
+	g_signal_connect(p->btn_forward, "clicked", G_CALLBACK(on_forward_button_clicked), self);
+	g_signal_connect(btn_zoom_in, "clicked", G_CALLBACK(on_zoom_in_button_clicked), self);
+	g_signal_connect(btn_zoom_out, "clicked", G_CALLBACK(on_zoom_out_button_clicked), self);
+
+	g_signal_connect(WEBKIT_WEB_VIEW(p->webview), "document-load-finished", G_CALLBACK(on_document_load_finished), self);
+	g_signal_connect(WEBKIT_WEB_VIEW(p->webview), "notify::uri", G_CALLBACK(on_uri_changed_notify), self);
+	g_signal_connect(WEBKIT_WEB_VIEW(p->webview), "notify::load-status", G_CALLBACK(on_load_status_changed_notify), self);
+
+	devhelp_plugin_set_webview_uri(self, NULL);
+}
+
+
+/* Initialize the stuff added to the sidebar. */
+static void devhelp_plugin_init_sidebar(DevhelpPlugin *self)
+{
+	GtkWidget *label;
+	GtkWidget *book_tree_sw;
+	DevhelpPluginPrivate *p;
+
+	g_return_if_fail(self != NULL);
+
+	p = self->priv;
+
+	p->sb_notebook = gtk_notebook_new();
+	p->orig_sb_tab_pos = gtk_notebook_get_tab_pos(GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook));
+
+	book_tree_sw = gtk_scrolled_window_new(NULL, NULL);
+	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(book_tree_sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+	gtk_container_set_border_width(GTK_CONTAINER(book_tree_sw), 6);
+	gtk_container_add(GTK_CONTAINER(book_tree_sw), p->book_tree);
+	gtk_widget_show(p->book_tree);
+
+	label = gtk_label_new(_("Contents"));
+	gtk_notebook_append_page(GTK_NOTEBOOK(p->sb_notebook), book_tree_sw, label);
+
+	label = gtk_label_new(_("Search"));
+	gtk_notebook_append_page(GTK_NOTEBOOK(p->sb_notebook), p->search, label);
+
+	gtk_notebook_set_current_page(GTK_NOTEBOOK(p->sb_notebook), 0);
+	gtk_widget_show_all(p->sb_notebook);
+
+	label = gtk_label_new(_("Devhelp"));
+	gtk_notebook_append_page(GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook), p->sb_notebook, label);
+}
+
+
+/* Called when a new plugin is being initialized */
+static void devhelp_plugin_init(DevhelpPlugin * self)
+{
+	DevhelpPluginPrivate *p;
+
+	g_return_if_fail(self != NULL);
+
+	self->priv = p = G_TYPE_INSTANCE_GET_PRIVATE(self, DEVHELP_TYPE_PLUGIN, DevhelpPluginPrivate);
+	devhelp_plugin_init_dh(self);
+
+	p->in_message_window = FALSE;
+	p->tabs_toggled = FALSE;
+	p->location = DEVHELP_PLUGIN_WEBVIEW_LOCATION_NONE;
+	p->main_notebook = NULL;
+
+	p->kf = NULL;
+	p->focus_webview_on_search = TRUE;
+	p->focus_sidebar_on_search = TRUE;
+	p->custom_homepage = NULL;
+	p->use_devhelp = TRUE;
+	p->use_man = TRUE;
+	p->use_codesearch = TRUE;
+
+	p->man_prog_path = g_find_program_in_path("man");
+	p->man_pager_prog = g_strdup("col -b");
+	p->man_section_order = g_strdup("3:2:1:8:5:4:7:6");
+
+	p->codesearch_base_uri = g_strdup("http://www.google.com/codesearch");
+	p->codesearch_params = NULL;
+	p->codesearch_use_lang = TRUE;
+
+    p->main_nb_tab_pos = GTK_POS_BOTTOM;
+
+	devhelp_plugin_init_edit_menu(self);
+	devhelp_plugin_init_sidebar(self);
+	devhelp_plugin_init_webkit(self);
+
+	p->last_main_tab_id = gtk_notebook_get_current_page(GTK_NOTEBOOK(p->main_notebook));
+	p->last_sb_tab_id = gtk_notebook_get_current_page(GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook));
+}
+
+
+/** Create a new Devhelp plugin instance. */
+DevhelpPlugin *devhelp_plugin_new(void)
+{
+	return g_object_new(DEVHELP_TYPE_PLUGIN, NULL);
+}
+
+
+/**
+ * Gets the WebKit WebView object used by the plugin.
+ *
+ * @param self Devhelp plugin.
+ *
+ * @return The webview used by the plugin.
+ */
+const gchar *devhelp_plugin_get_webview_uri(DevhelpPlugin *self)
+{
+	g_return_val_if_fail(DEVHELP_IS_PLUGIN(self), NULL);
+	return webkit_web_view_get_uri(WEBKIT_WEB_VIEW(self->priv->webview));
+}
+
+
+/**
+ * Loads the specified @a uri in the WebKit WebView.
+ *
+ * @param self Devhelp plugin.
+ * @param uri The URI to load in the webview or NULL for default homepage.
+ */
+void devhelp_plugin_set_webview_uri(DevhelpPlugin *self, const gchar *uri)
+{
+	/* stolen from Webhelper plugin */
+	gchar *real_uri;
+	gchar *scheme;
+
+	g_return_if_fail(DEVHELP_IS_PLUGIN(self));
+
+	if (uri == NULL)
+		real_uri = g_filename_to_uri(DHPLUG_WEBVIEW_HOME_FILE, NULL, NULL);
+	else
+		real_uri = g_strdup(uri);
+
+	scheme = g_uri_parse_scheme(real_uri);
+	if (!scheme)
+	{
+		gchar *tmp = g_strconcat("http://", uri, NULL);
+		g_free(real_uri);
+		real_uri = tmp;
+	}
+	g_free(scheme);
+
+	if (g_strcmp0(real_uri, devhelp_plugin_get_webview_uri(self)) != 0)
+	{
+		webkit_web_view_open(WEBKIT_WEB_VIEW(self->priv->webview), real_uri);
+		g_object_notify(G_OBJECT(self), "webview-uri");
+	}
+	g_free(real_uri);
+}
+
+
+/**
+ * Same as devhelp_plugin_search_books().
+ *
+ * @param self Devhelp plugin.
+ * @param term The search term to look up.
+ */
+void devhelp_plugin_search(DevhelpPlugin *self, const gchar *term)
+{
+	devhelp_plugin_search_books(self, term);
+}
+
+
+/**
+ * Search for a term in Devhelp and activate/show the plugin's UI stuff.
+ *
+ * @param dhplug	Devhelp plugin
+ * @param term		The string to search for
+ */
+void devhelp_plugin_search_books(DevhelpPlugin *self, const gchar *term)
+{
+
+	g_return_if_fail(self != NULL);
+	g_return_if_fail(term != NULL);
+
+	dh_search_set_search_string(DH_SEARCH(self->priv->search), term, NULL);
+
+	devhelp_plugin_activate_all_tabs(self);
+}
+
+
+/*
+ * Cleans up a word/tag before searching.
+ *
+ * Replaces non @c GEANY_WORDCHARS in str with spaces and then trims whitespace.
+ * This function does not allocate a new string, it modifies @a str in place
+ * and returns a pointer to @a str.
+ * TODO: make this only remove stuff from the start or end of string.
+ *
+ * @param	str	String to clean
+ *
+ * @return Pointer to (cleaned) @a str.
+ */
+static inline gchar *clean_word(gchar* str)
+{
+	return g_strstrip(g_strcanon(str, GEANY_WORDCHARS, ' '));
+}
+
+
+/**
+ * Gets either the current selection or the word at the current selection.
+ *
+ * @return Newly allocated string with current tag or NULL no tag.
+ */
+gchar *devhelp_plugin_get_current_word(DevhelpPlugin *self)
+{
+	gint pos;
+	gchar *tag = NULL;
+	GeanyDocument *doc = document_get_current();
+
+	g_return_val_if_fail(DEVHELP_IS_PLUGIN(self), NULL);
+
+	if (doc == NULL || doc->editor == NULL || doc->editor->sci == NULL)
+		return NULL;
+
+	if (sci_has_selection(doc->editor->sci))
+		return clean_word(sci_get_selection_contents(doc->editor->sci));
+
+	pos = sci_get_current_position(doc->editor->sci);
+	tag = editor_get_word_at_pos(doc->editor, pos, GEANY_WORDCHARS);
+
+	if (tag == NULL || strlen(tag) == 0)
+	{
+		g_free(tag /* might be null, ok */);
+		return NULL;
+	}
+
+	return clean_word(tag);
+}
+
+
+/**
+ * Activate the plugin's tabs in the UI.
+ *
+ * @param dhplug Devhelp plugin
+ * @param search_tabs_shown If TRUE, show the sidebar search tab, otherwise
+ * 	show the contents tab.
+ */
+void devhelp_plugin_activate_ui(DevhelpPlugin *self, gboolean show_search_tab)
+{
+	g_return_if_fail(self != NULL);
+	devhelp_plugin_set_ui_active(self, TRUE);
+	gtk_notebook_set_current_page(GTK_NOTEBOOK(self->priv->sb_notebook), (show_search_tab) ? 1 : 0);
+}
+
+
+/**
+ * Get whether or not the plugin's tabs are shown/active in the UI.
+ *
+ * @param self Devhelp plugin.
+ *
+ * @return TRUE if the UI elements are active FALSE if not.
+ */
+gboolean devhelp_plugin_get_ui_active(DevhelpPlugin *self)
+{
+	g_return_val_if_fail(DEVHELP_IS_PLUGIN(self), FALSE);
+	return self->priv->tabs_toggled;
+}
+
+
+/**
+ * Set whether or not the plugin's tabs are shown/active in the UI.
+ *
+ * @param self Devhelp plugin
+ * @param active Whether to show the plugin's tabs or the previous tabs.
+ */
+void devhelp_plugin_set_ui_active(DevhelpPlugin *self, gboolean active)
+{
+	GtkNotebook *main_nb, *sbar_nb;
+
+	g_return_if_fail(DEVHELP_IS_PLUGIN(self));
+
+	main_nb = GTK_NOTEBOOK(self->priv->main_notebook);
+	sbar_nb = GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook);
+
+	if (active && !devhelp_plugin_get_ui_active(self))
+	{
+		self->priv->last_main_tab_id = gtk_notebook_get_current_page(main_nb);
+		self->priv->last_sb_tab_id = gtk_notebook_get_current_page(sbar_nb);
+		gtk_notebook_set_current_page(main_nb, gtk_notebook_page_num(main_nb, self->priv->webview_tab));
+		gtk_notebook_set_current_page(sbar_nb, gtk_notebook_page_num(sbar_nb, self->priv->sb_notebook));
+		self->priv->tabs_toggled = TRUE;
+		g_object_notify(G_OBJECT(self), "ui-active");
+	}
+	else if (!active && devhelp_plugin_get_ui_active(self))
+	{
+		gtk_notebook_set_current_page(main_nb, self->priv->last_main_tab_id);
+		gtk_notebook_set_current_page(sbar_nb, self->priv->last_sb_tab_id);
+		self->priv->tabs_toggled = FALSE;
+		g_object_notify(G_OBJECT(self), "ui-active");
+	}
+}
+
+
+/**
+ * Gets whether the Geany sidebar tabs are in the bottom or their original position.
+ *
+ * @param self Devhelp plugin.
+ */
+gboolean devhelp_plugin_get_sidebar_tabs_bottom(DevhelpPlugin *self)
+{
+	GtkPositionType pos;
+	g_return_val_if_fail(DEVHELP_IS_PLUGIN(self), FALSE);
+	pos = gtk_notebook_get_tab_pos(GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook));
+	return  pos == GTK_POS_BOTTOM;
+}
+
+
+/**
+ * Sets whether the Geany sidebar tabs are at the bottom or in their original position.
+ *
+ * @param self Devhelp plugin.
+ * @param bottom If TRUE, set the sidebar tab position to @c GTK_POS_BOTTOM
+ * otherwise set back to original position.
+ */
+void devhelp_plugin_set_sidebar_tabs_bottom(DevhelpPlugin *self, gboolean bottom)
+{
+	GtkNotebook *nb;
+
+	g_return_if_fail(DEVHELP_IS_PLUGIN(self));
+
+	nb = GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook);
+
+	if (!devhelp_plugin_get_sidebar_tabs_bottom(self) && bottom)
+	{
+		self->priv->orig_sb_tab_pos = gtk_notebook_get_tab_pos(nb);
+		gtk_notebook_set_tab_pos(nb, GTK_POS_BOTTOM);
+		g_object_notify(G_OBJECT(self), "sidebar-tabs-bottom");
+	}
+	else if (devhelp_plugin_get_sidebar_tabs_bottom(self) && !bottom)
+	{
+		gtk_notebook_set_tab_pos(nb, self->priv->orig_sb_tab_pos);
+		g_object_notify(G_OBJECT(self), "sidebar-tabs-bottom");
+	}
+}
+
+
+/**
+ * Gets whether the Documentation tab is in a main_notebook or in the
+ * message window.
+ *
+ * @param self Devhelp plugin.
+ *
+ * @return TRUE if the Documentation tab is in a main_notebok or FALSE if it's
+ * in the message window notebook.
+ */
+gboolean devhelp_plugin_get_in_message_window(DevhelpPlugin *self)
+{
+	g_return_val_if_fail(DEVHELP_IS_PLUGIN(self), FALSE);
+	return self->priv->in_message_window;
+}
+
+
+/* Refs the webkit tab stuff and removes it from parents, returns pointer to
+ * widget that was ref'd. */
+static GtkWidget* devhelp_plugin_ref_unpack_webview_tab(DevhelpPlugin *self)
+{
+	GtkWidget *parent, *doc_nb;
+
+	g_return_val_if_fail(DEVHELP_IS_PLUGIN(self), NULL);
+
+	/* Prevents a segfault bug from popping up when messing with doc notebook */
+	gtk_widget_set_sensitive(geany->main_widgets->notebook, FALSE);
+
+	gtk_widget_ref(self->priv->webview_tab);
+
+	if (self->priv->location != DEVHELP_PLUGIN_WEBVIEW_LOCATION_NONE)
+	{
+		parent = gtk_widget_get_parent(self->priv->webview_tab);
+		gtk_container_remove(GTK_CONTAINER(parent), self->priv->webview_tab);
+	}
+
+	/* If we were using the "main notebook", put the UI back to normal */
+	if (self->priv->location == DEVHELP_PLUGIN_WEBVIEW_LOCATION_MAIN_NOTEBOOK)
+	{
+		parent = gtk_widget_get_parent(self->priv->main_notebook);
+		doc_nb = gtk_widget_ref(geany->main_widgets->notebook);
+		gtk_container_remove(GTK_CONTAINER(self->priv->main_notebook), doc_nb);
+		gtk_container_remove(GTK_CONTAINER(parent), self->priv->main_notebook);
+		gtk_container_add(GTK_CONTAINER(parent), doc_nb);
+		gtk_widget_unref(doc_nb);
+		self->priv->main_notebook = NULL;
+	}
+
+	self->priv->location = DEVHELP_PLUGIN_WEBVIEW_LOCATION_NONE;
+
+	gtk_widget_set_sensitive(geany->main_widgets->notebook, TRUE);
+
+	return self->priv->webview_tab;
+}
+
+
+static void devhelp_plugin_set_webview_location(DevhelpPlugin *self, DevhelpPluginWebViewLocation location)
+{
+	g_return_if_fail(DEVHELP_IS_PLUGIN(self));
+
+	if (location == self->priv->location) /* no change, so do nothing */
+		return;
+
+	switch(location)
+	{
+		case DEVHELP_PLUGIN_WEBVIEW_LOCATION_SIDEBAR:
+			gtk_notebook_append_page(
+				GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook),
+				devhelp_plugin_ref_unpack_webview_tab(self),
+				gtk_label_new(DEVHELP_PLUGIN_WEBVIEW_TAB_LABEL));
+			gtk_widget_unref(self->priv->webview_tab);
+			self->priv->location = DEVHELP_PLUGIN_WEBVIEW_LOCATION_SIDEBAR;
+			break;
+		case DEVHELP_PLUGIN_WEBVIEW_LOCATION_MESSAGE_WINDOW:
+			gtk_notebook_append_page(
+				GTK_NOTEBOOK(geany->main_widgets->message_window_notebook),
+				devhelp_plugin_ref_unpack_webview_tab(self),
+				gtk_label_new(DEVHELP_PLUGIN_WEBVIEW_TAB_LABEL));
+			gtk_widget_unref(self->priv->webview_tab);
+			self->priv->location = DEVHELP_PLUGIN_WEBVIEW_LOCATION_MESSAGE_WINDOW;
+			break;
+		case DEVHELP_PLUGIN_WEBVIEW_LOCATION_MAIN_NOTEBOOK:
+		{
+			GtkWidget *parent, *doc_nb, *main_notebook, *webview_tab;
+
+			webview_tab = devhelp_plugin_ref_unpack_webview_tab(self);
+			doc_nb = geany->main_widgets->notebook;
+			parent = gtk_widget_get_parent(doc_nb);
+
+			gtk_widget_ref(doc_nb);
+
+			gtk_container_remove(GTK_CONTAINER(parent), doc_nb);
+			main_notebook = gtk_notebook_new();
+			self->priv->main_notebook = main_notebook;
+
+			gtk_notebook_append_page(GTK_NOTEBOOK(main_notebook),
+				doc_nb, gtk_label_new(DEVHELP_PLUGIN_DOCUMENTS_TAB_LABEL));
+			gtk_notebook_append_page(GTK_NOTEBOOK(main_notebook),
+				webview_tab, gtk_label_new(DEVHELP_PLUGIN_WEBVIEW_TAB_LABEL));
+
+			gtk_container_add(GTK_CONTAINER(parent), main_notebook);
+
+			gtk_widget_show_all(doc_nb);
+			gtk_widget_show_all(webview_tab);
+			gtk_widget_show_all(main_notebook);
+
+			gtk_widget_unref(doc_nb);
+			gtk_widget_unref(webview_tab);
+
+			self->priv->location = DEVHELP_PLUGIN_WEBVIEW_LOCATION_MAIN_NOTEBOOK;
+			break;
+		}
+		default:
+			g_warning("Unable to set location of webview.");
+			break;
+	}
+}
+
+
+/**
+ * Sets whether the Documentation tab is in the message window notebook or is
+ * in a main_notebook.
+ *
+ * @param self Devhelp plugin.
+ * @param in_msgwin TRUE to move the Documentation tab to the message window
+ * notebook or FALSE to create a main_notebook and put it there.
+ */
+void devhelp_plugin_set_in_message_window(DevhelpPlugin *self, gboolean in_msgwin)
+{
+	g_return_if_fail(DEVHELP_IS_PLUGIN(self));
+
+	if (in_msgwin && !self->priv->in_message_window)
+	{
+		devhelp_plugin_set_webview_location(self,
+			DEVHELP_PLUGIN_WEBVIEW_LOCATION_MESSAGE_WINDOW);
+		self->priv->in_message_window = TRUE;
+		g_object_notify(G_OBJECT(self), "in-message-window");
+	}
+	else if (!in_msgwin && self->priv->in_message_window)
+	{
+		devhelp_plugin_set_webview_location(self,
+			DEVHELP_PLUGIN_WEBVIEW_LOCATION_MAIN_NOTEBOOK);
+		self->priv->in_message_window = FALSE;
+		g_object_notify(G_OBJECT(self), "in-message-window");
+	}
+}
+
+
+/**
+ * Gets the zoom level of the WebKit WebView.
+ *
+ * @param self Devhelp plugin.
+ *
+ * @return The zoom level.
+ */
+gfloat devhelp_plugin_get_zoom_level(DevhelpPlugin *self)
+{
+	g_return_val_if_fail(DEVHELP_IS_PLUGIN(self), 0.0F);
+	return webkit_web_view_get_zoom_level(WEBKIT_WEB_VIEW(self->priv->webview));
+}
+
+
+/**
+ * Sets the zoom level of the WebKit WebView.
+ *
+ * @param self Devhelp plugin.
+ * @param zoom_level The zoom level to set.
+ */
+void devhelp_plugin_set_zoom_level(DevhelpPlugin *self, gfloat zoom_level)
+{
+	g_return_if_fail(DEVHELP_IS_PLUGIN(self));
+
+	if (devhelp_plugin_get_zoom_level(self) != zoom_level)
+	{
+		webkit_web_view_set_zoom_level(WEBKIT_WEB_VIEW(self->priv->webview), zoom_level);
+		g_object_notify(G_OBJECT(self), "zoom-level");
+	}
+}
+
+
+WebKitWebView* devhelp_plugin_get_webview(DevhelpPlugin *self)
+{
+	g_return_val_if_fail(DEVHELP_IS_PLUGIN(self), NULL);
+	return WEBKIT_WEB_VIEW(self->priv->webview);
+}
+
+
+/**
+ * Returns a pointer to the list used to track temp files.
+ *
+ * @param self Devhelp plugin.
+ *
+ * @return Pointer to the internal list used to track temp files.
+ */
+GList* devhelp_plugin_get_temp_files(DevhelpPlugin *self)
+{
+	g_return_val_if_fail(DEVHELP_IS_PLUGIN(self), NULL);
+	return self->priv->temp_files;
+}
+
+
+/**
+ * Returns the path to the 'man' program on the system or NULL if one was not
+ * found.
+ *
+ * @param self Devhelp plugin.
+ *
+ * @return The path to the 'man' program or NULL if not found.  Free the
+ * returned value when no longer needed.
+ */
+const gchar* devhelp_plugin_get_man_prog_path(DevhelpPlugin *self)
+{
+	g_return_val_if_fail(DEVHELP_IS_PLUGIN(self), NULL);
+	return (const gchar *)self->priv->man_prog_path;
+}
+
+
+/**
+ * Finds whether or not a 'man' program is available (in the path) on the
+ * current system.
+ *
+ * @param self Devhelp plugin.
+ *
+ * @return TRUE if a 'man' program was found or FALSE if not.
+ */
+gboolean devhelp_plugin_get_have_man_prog(DevhelpPlugin *self)
+{
+	g_return_val_if_fail(DEVHELP_IS_PLUGIN(self), FALSE);
+	return devhelp_plugin_get_man_prog_path(self) != NULL;
+}
+
+
+/* TODO: make properties for the following accessor functions */
+
+gboolean devhelp_plugin_get_devhelp_sidebar_visible(DevhelpPlugin *self)
+{
+	g_return_val_if_fail(DEVHELP_IS_PLUGIN(self), FALSE);
+	return gtk_widget_get_visible(self->priv->sb_notebook);
+}
+
+
+void devhelp_plugin_set_devhelp_sidebar_visible(DevhelpPlugin *self, gboolean visible)
+{
+	g_return_if_fail(DEVHELP_IS_PLUGIN(self));
+	gtk_widget_set_visible(self->priv->sb_notebook, visible);
+}
+
+
+gboolean devhelp_plugin_get_use_devhelp(DevhelpPlugin *self)
+{
+	g_return_val_if_fail(DEVHELP_IS_PLUGIN(self), FALSE);
+	return self->priv->use_devhelp;
+}
+
+
+void devhelp_plugin_set_use_devhelp(DevhelpPlugin *self, gboolean use)
+{
+	g_return_if_fail(DEVHELP_IS_PLUGIN(self));
+	self->priv->use_devhelp = use;
+	gtk_widget_set_visible(self->priv->sb_notebook, use);
+	/* TODO: hide edit menu items and keybindings */
+	/* TODO: if no providers, hide webview */
+}
+
+
+gboolean devhelp_plugin_get_use_man(DevhelpPlugin *self)
+{
+	g_return_val_if_fail(DEVHELP_IS_PLUGIN(self), FALSE);
+	return self->priv->use_man;
+}
+
+
+void devhelp_plugin_set_use_man(DevhelpPlugin *self, gboolean use)
+{
+	g_return_if_fail(DEVHELP_IS_PLUGIN(self));
+	self->priv->use_man = use;
+	/* TODO: hide edit menu items and keybindings */
+	/* TODO: if no providers, hide webview */
+}
+
+
+gboolean devhelp_plugin_get_use_codesearch(DevhelpPlugin *self)
+{
+	g_return_val_if_fail(DEVHELP_IS_PLUGIN(self), FALSE);
+	return self->priv->use_codesearch;
+}
+
+
+void devhelp_plugin_set_use_codesearch(DevhelpPlugin *self, gboolean use)
+{
+	g_return_if_fail(DEVHELP_IS_PLUGIN(self));
+	self->priv->use_codesearch = use;
+	/* TODO: hide edit menu items and keybindings */
+	/* TODO: if no providers, hide webview */
+}
+
+
+/* Activates (brings to top/makes visible) the Devhelp plugin's sidebar tab. */
+static inline void devhelp_plugin_activate_sidebar_tab(DevhelpPlugin *self)
+{
+	GtkNotebook *nb;
+	gint current_tab_id;
+
+	g_return_if_fail(self != NULL);
+
+	nb = GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook);
+
+	current_tab_id = gtk_notebook_get_current_page(nb);
+	if (current_tab_id != gtk_notebook_page_num(nb, self->priv->sb_notebook))
+		self->priv->last_sb_tab_id = current_tab_id;
+
+	gtk_widget_set_visible(self->priv->sb_notebook, TRUE);
+	gtk_notebook_set_current_page(nb, gtk_notebook_page_num(nb, self->priv->sb_notebook));
+}
+
+
+/**
+ * Activates the Devhelp plugin's sidebar tab, and then the internal notebook's
+ * Search tab.
+ *
+ * @param self Devhelp plugin.
+ */
+void devhelp_plugin_activate_search_tab(DevhelpPlugin *self)
+{
+	g_return_if_fail(self != NULL);
+	devhelp_plugin_activate_sidebar_tab(self);
+	gtk_notebook_set_current_page(GTK_NOTEBOOK(self->priv->sb_notebook), 1);
+}
+
+
+/**
+ * Activates the Devhelp plugin's sidebar tab, and then the internal notebook's
+ * Contents tab.
+ *
+ * @param self Devhelp plugin.
+ */
+void devhelp_plugin_activate_contents_tab(DevhelpPlugin *self)
+{
+	g_return_if_fail(self != NULL);
+	devhelp_plugin_activate_sidebar_tab(self);
+	gtk_notebook_set_current_page(GTK_NOTEBOOK(self->priv->sb_notebook), 0);
+}
+
+
+/**
+ * Activates the Devhelp plugin's main notebook's Documentation tab.
+ *
+ * @param self Devhelp plugin.
+ */
+void devhelp_plugin_activate_webview_tab(DevhelpPlugin *self)
+{
+	GtkNotebook *nb;
+	gint current_tab_id;
+
+	g_return_if_fail(self != NULL);
+
+	nb = GTK_NOTEBOOK(self->priv->main_notebook);
+
+	current_tab_id = gtk_notebook_get_current_page(nb);
+	if (current_tab_id != gtk_notebook_page_num(nb, self->priv->webview_tab))
+		self->priv->last_main_tab_id = current_tab_id;
+
+	gtk_notebook_set_current_page(nb, gtk_notebook_page_num(nb, self->priv->webview_tab));
+}
+
+
+/* Toggles the Devhelp tab in the Geany sidebar notebook. */
+static inline void devhelp_plugin_toggle_sidebar_tab(DevhelpPlugin *self, gint tab)
+{
+	GtkNotebook *sbar_nb;
+	gint current_tab_id;
+
+	g_return_if_fail(self != NULL);
+
+	sbar_nb = GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook);
+	current_tab_id = gtk_notebook_get_current_page(sbar_nb);
+
+	if (current_tab_id == gtk_notebook_page_num(sbar_nb, self->priv->sb_notebook))
+		gtk_notebook_set_current_page(sbar_nb, self->priv->last_sb_tab_id);
+	else
+	{
+		if (tab == 0)
+			devhelp_plugin_activate_contents_tab(self);
+		else if (tab == 1)
+			devhelp_plugin_activate_search_tab(self);
+		else
+			g_warning("Can't toggle to unknown tab ID: %d", tab);
+	}
+}
+
+
+/**
+ * Toggle's between the Devhelp plugin's search tab and the previous Geany
+ * sidebar tab.
+ *
+ * @param self Devhelp plugin.
+ */
+void devhelp_plugin_toggle_search_tab(DevhelpPlugin *self)
+{
+	devhelp_plugin_toggle_sidebar_tab(self, 1);
+}
+
+
+/**
+ * Toggle's between the Devhelp plugin's contents tab and the previous Geany
+ * sidebar tab.
+ *
+ * @param self Devhelp plugin.
+ */
+void devhelp_plugin_toggle_contents_tab(DevhelpPlugin *self)
+{
+	devhelp_plugin_toggle_sidebar_tab(self, 0);
+}
+
+
+/**
+ * Toggle's between the Devhelp plugin's main notebook tab and the previous
+ * main notebook tab.
+ *
+ * @param self Devhelp plugin.
+ */
+void devhelp_plugin_toggle_webview_tab(DevhelpPlugin *self)
+{
+	gint current_tab_id;
+
+	g_return_if_fail(self != NULL);
+
+	current_tab_id = gtk_notebook_get_current_page(GTK_NOTEBOOK(self->priv->main_notebook));
+	if (current_tab_id == self->priv->last_main_tab_id)
+	{
+		gtk_notebook_set_current_page(GTK_NOTEBOOK(self->priv->main_notebook),
+			self->priv->last_main_tab_id);
+	}
+	else
+		devhelp_plugin_activate_webview_tab(self);
+}
+
+
+/**
+ * Activates/shows all the Devhelp plugins tabs.
+ *
+ * @param self Devhelp plugin.
+ */
+void devhelp_plugin_activate_all_tabs(DevhelpPlugin *self)
+{
+	devhelp_plugin_activate_sidebar_tab(self);
+	devhelp_plugin_activate_webview_tab(self);
+}
+
+
+/* Called when the editor menu item is selected */
+static void on_search_help_activate(GtkMenuItem * menuitem, DevhelpPlugin *self)
+{
+	gchar *current_tag;
+
+	g_return_if_fail(self != NULL);
+
+	if ((current_tag = devhelp_plugin_get_current_word(self)) == NULL)
+		return;
+
+	devhelp_plugin_search_books(self, current_tag);
+
+	g_free(current_tag);
+}
+
+
+/* Called when the editor menu item is selected */
+static void on_search_help_man_activate(GtkMenuItem * menuitem, DevhelpPlugin *self)
+{
+	gchar *current_tag;
+
+	g_return_if_fail(self != NULL);
+
+	if ((current_tag = devhelp_plugin_get_current_word(self)) == NULL)
+		return;
+
+	devhelp_plugin_search_manpages(self, current_tag);
+
+	g_free(current_tag);
+}
+
+
+static void on_search_help_code_activate(GtkMenuItem *menuitem, DevhelpPlugin *self)
+{
+	gchar *current_tag;
+	const gchar *lang = NULL;
+	GeanyDocument *doc;
+
+	g_return_if_fail(self != NULL);
+
+	if ((current_tag = devhelp_plugin_get_current_word(self)) == NULL)
+		return;
+
+	doc = document_get_current();
+	if (doc != NULL && doc->file_type != NULL && doc->file_type->name != NULL)
+		lang = doc->file_type->name;
+
+	devhelp_plugin_search_code(self, current_tag, lang);
+
+	g_free(current_tag);
+}
+
+
+/*
+ * Called when the editor context menu is shown so that the devhelp
+ * search item can be disabled if there isn't a selected tag.
+ */
+static void on_editor_menu_popup(GtkWidget * widget, DevhelpPlugin *self)
+{
+	gchar *label_tag, *curword, *new_label;
+
+	g_return_if_fail(self != NULL);
+
+	curword = devhelp_plugin_get_current_word(self);
+
+	if (curword == NULL)
+	{
+		gtk_widget_set_sensitive(self->priv->editor_menu_item, FALSE);
+		return;
+	}
+
+	label_tag = g_strstrip(g_strndup(curword, DHPLUG_MAX_LABEL_TAG));
+	new_label = g_strdup_printf(_("Search for '%s' Documentation in"), label_tag);
+
+	gtk_menu_item_set_label(GTK_MENU_ITEM(self->priv->editor_menu_item), new_label);
+
+	g_free(new_label);
+	g_free(label_tag);
+
+	gtk_widget_set_sensitive(self->priv->editor_menu_item, TRUE);
+
+	g_free(curword);
+}
+
+
+/*
+ * Called when a link in either the contents or search areas on the sidebar
+ * have a link clicked on, meaning to load that file into the webview.
+ */
+static void on_link_clicked(GObject * ignored, DhLink * dhlink, DevhelpPlugin *self)
+{
+	gchar *uri;
+
+	g_return_if_fail(DEVHELP_IS_PLUGIN(self));
+
+	uri = dh_link_get_uri(dhlink);
+	devhelp_plugin_set_webview_uri(self, uri);
+	devhelp_plugin_activate_webview_tab(self);
+	g_free(uri);
+}
+
+
+static void on_back_button_clicked(GtkToolButton * btn, DevhelpPlugin *self)
+{
+	g_return_if_fail(DEVHELP_IS_PLUGIN(self));
+	webkit_web_view_go_back(WEBKIT_WEB_VIEW(self->priv->webview));
+}
+
+
+static void on_forward_button_clicked(GtkToolButton * btn, DevhelpPlugin *self)
+{
+	g_return_if_fail(DEVHELP_IS_PLUGIN(self));
+	webkit_web_view_go_forward(WEBKIT_WEB_VIEW(self->priv->webview));
+}
+
+
+static void on_zoom_in_button_clicked(GtkToolButton * btn, DevhelpPlugin *self)
+{
+	g_return_if_fail(DEVHELP_IS_PLUGIN(self));
+	webkit_web_view_zoom_in(devhelp_plugin_get_webview(self));
+}
+
+
+static void on_zoom_out_button_clicked(GtkToolButton *btn, DevhelpPlugin *self)
+{
+	g_return_if_fail(DEVHELP_IS_PLUGIN(self));
+	webkit_web_view_zoom_out(devhelp_plugin_get_webview(self));
+}
+
+
+/* Controls the sensitivity of the back/forward buttons when webkit page changes. */
+static inline void update_history_buttons(DevhelpPlugin *self)
+{
+	g_return_if_fail(DEVHELP_IS_PLUGIN(self));
+
+	gtk_widget_set_sensitive(GTK_WIDGET(self->priv->btn_back),
+		webkit_web_view_can_go_back(devhelp_plugin_get_webview(self)));
+	gtk_widget_set_sensitive(GTK_WIDGET(self->priv->btn_forward),
+		webkit_web_view_can_go_forward(devhelp_plugin_get_webview(self)));
+}
+
+
+static void on_document_load_finished(WebKitWebView *view, WebKitWebFrame *frame, DevhelpPlugin *self)
+{
+	update_history_buttons(self);
+}
+
+
+static void on_uri_changed_notify(GObject *object, GParamSpec *pspec, DevhelpPlugin *self)
+{
+	update_history_buttons(self);
+}
+
+
+static void on_load_status_changed_notify(GObject *object, GParamSpec *pspec, DevhelpPlugin *self)
+{
+	update_history_buttons(self);
+}
+

Added: trunk/geany-plugins/devhelp/src/dhp-plugin.c
===================================================================
--- trunk/geany-plugins/devhelp/src/dhp-plugin.c	                        (rev 0)
+++ trunk/geany-plugins/devhelp/src/dhp-plugin.c	2011-05-24 09:04:06 UTC (rev 2082)
@@ -0,0 +1,209 @@
+/*
+ * plugin.c - Part of the Geany Devhelp Plugin
+ *
+ * Copyright 2010 Matthew Brush <mbrush at leftclick.ca>
+ *
+ * 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 3 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <sys/stat.h> /* for g_mkdir_with_parents, is it portable? */
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h> /* for keybindings */
+#include <geanyplugin.h>
+#include <devhelp/dh-search.h>
+
+#include "dhp-plugin.h"
+#include "dhp.h"
+
+
+PLUGIN_VERSION_CHECK(200)
+
+PLUGIN_SET_INFO(
+	_("Devhelp Plugin"),
+	_("Adds support for looking up documentation in Devhelp, manual pages, and "
+	  "Google Code Search in the integrated viewer."),
+	"1.0", "Matthew Brush <mbrush at leftclick.ca>")
+
+
+GeanyPlugin	 	*geany_plugin;
+GeanyData	   	*geany_data;
+GeanyFunctions 	*geany_functions;
+
+struct PluginData plugin;
+
+/* keybindings */
+enum
+{
+	KB_DEVHELP_TOGGLE_CONTENTS,
+	KB_DEVHELP_TOGGLE_SEARCH,
+	KB_DEVHELP_TOGGLE_WEBVIEW,
+	KB_DEVHELP_ACTIVATE_DEVHELP,
+	KB_DEVHELP_SEARCH_SYMBOL,
+	KB_DEVHELP_SEARCH_MANPAGES,
+	KB_DEVHELP_SEARCH_CODESEARCH,
+	KB_COUNT
+};
+
+/* Called when a keybinding is activated */
+static void kb_activate(guint key_id)
+{
+	gchar *current_tag;
+
+	switch (key_id)
+	{
+		case KB_DEVHELP_TOGGLE_CONTENTS:
+			devhelp_plugin_toggle_contents_tab(plugin.devhelp);
+			break;
+		case KB_DEVHELP_TOGGLE_SEARCH:
+			devhelp_plugin_toggle_search_tab(plugin.devhelp);
+			break;
+		case KB_DEVHELP_TOGGLE_WEBVIEW: /* not working */
+			devhelp_plugin_toggle_webview_tab(plugin.devhelp);
+			break;
+		case KB_DEVHELP_ACTIVATE_DEVHELP:
+			devhelp_plugin_activate_all_tabs(plugin.devhelp);
+			break;
+		case KB_DEVHELP_SEARCH_SYMBOL:
+		{
+			current_tag = devhelp_plugin_get_current_word(plugin.devhelp);
+			if (current_tag == NULL)
+				return;
+			devhelp_plugin_search_books(plugin.devhelp, current_tag);
+			g_free(current_tag);
+			break;
+		}
+		case KB_DEVHELP_SEARCH_MANPAGES:
+		{
+			current_tag = devhelp_plugin_get_current_word(plugin.devhelp);
+			if (current_tag == NULL)
+				return;
+			devhelp_plugin_search_manpages(plugin.devhelp, current_tag);
+			g_free(current_tag);
+			break;
+		}
+		case KB_DEVHELP_SEARCH_CODESEARCH:
+		{
+			const gchar *lang = NULL;
+			GeanyDocument *doc;
+
+			if ((current_tag = devhelp_plugin_get_current_word(plugin.devhelp)) == NULL)
+				return;
+
+			doc = document_get_current();
+			if (doc == NULL || doc->file_type == NULL || doc->file_type->name == NULL)
+				lang = doc->file_type->name;
+
+			devhelp_plugin_search_code(plugin.devhelp, current_tag, lang);
+
+			g_free(current_tag);
+			break;
+		}
+	}
+}
+
+
+gboolean plugin_config_init(struct PluginData *pd)
+{
+	gchar *user_config_dir;
+
+	g_return_val_if_fail(pd != NULL, FALSE);
+
+	plugin.default_config = g_build_path(G_DIR_SEPARATOR_S, DHPLUG_DATA_DIR, "devhelp.conf", NULL);
+
+	user_config_dir = g_build_path(G_DIR_SEPARATOR_S, geany_data->app->configdir, "plugins", "devhelp", NULL);
+	plugin.user_config = g_build_path(G_DIR_SEPARATOR_S, user_config_dir, "devhelp.conf", NULL);
+	if (g_mkdir_with_parents(user_config_dir, S_IRUSR | S_IWUSR | S_IXUSR) != 0)
+	{
+		g_warning(_("Unable to create config dir at '%s'"), user_config_dir);
+		g_free(user_config_dir);
+		return FALSE;
+	}
+	g_free(user_config_dir);
+
+	/* copy default config into user config if it doesn't exist */
+	if (!g_file_test(pd->user_config, G_FILE_TEST_EXISTS))
+	{
+		gchar *config_text;
+		GError *error;
+
+		error = NULL;
+		if (!g_file_get_contents(pd->default_config, &config_text, NULL, &error))
+		{
+			g_warning(_("Unable to get default configuration: %s"), error->message);
+			g_error_free(error);
+			return FALSE;
+		}
+		else
+		{
+			if (!g_file_set_contents(pd->user_config, config_text, -1, &error))
+			{
+				g_warning(_("Unable to write default configuration: %s"), error->message);
+				g_error_free(error);
+				return FALSE;
+			}
+		}
+	}
+
+	return TRUE;
+}
+
+
+void plugin_init(GeanyData *data)
+{
+	GeanyKeyGroup *key_group;
+
+	plugin_module_make_resident(geany_plugin);
+
+	if (!g_thread_supported())
+		g_thread_init(NULL);
+
+	memset(&plugin, 0, sizeof(struct PluginData));
+
+	plugin.devhelp = devhelp_plugin_new();
+	plugin_config_init(&plugin);
+
+	devhelp_plugin_load_settings(plugin.devhelp, plugin.user_config);
+
+	key_group = plugin_set_key_group(geany_plugin, "devhelp", KB_COUNT, NULL);
+
+	keybindings_set_item(key_group, KB_DEVHELP_TOGGLE_CONTENTS, kb_activate,
+		0, 0, "devhelp_toggle_contents", _("Toggle sidebar contents tab"), NULL);
+	keybindings_set_item(key_group, KB_DEVHELP_TOGGLE_SEARCH, kb_activate,
+		0, 0, "devhelp_toggle_search", _("Toggle sidebar search tab"), NULL);
+	keybindings_set_item(key_group, KB_DEVHELP_TOGGLE_WEBVIEW, kb_activate,
+		0, 0, "devhelp_toggle_webview", _("Toggle documentation tab"), NULL);
+	keybindings_set_item(key_group, KB_DEVHELP_ACTIVATE_DEVHELP, kb_activate,
+		0, 0, "devhelp_activate_all", _("Activate all tabs"), NULL);
+	keybindings_set_item(key_group, KB_DEVHELP_SEARCH_SYMBOL, kb_activate,
+		0, 0, "devhelp_search_symbol", _("Search for current tag in Devhelp"), NULL);
+	if (devhelp_plugin_get_have_man_prog(plugin.devhelp))
+	{
+		keybindings_set_item(key_group, KB_DEVHELP_SEARCH_MANPAGES, kb_activate,
+			0, 0, "devhelp_search_manpages", _("Search for current tag in Manual Pages"), NULL);
+	}
+	keybindings_set_item(key_group, KB_DEVHELP_SEARCH_CODESEARCH, kb_activate,
+		0, 0, "devhelp_search_codesearch", _("Search for current tag in Google Code Search"), NULL);
+}
+
+
+void plugin_cleanup(void)
+{
+	devhelp_plugin_store_settings(plugin.devhelp, plugin.user_config);
+	g_object_unref(plugin.devhelp);
+	g_free(plugin.default_config);
+	g_free(plugin.user_config);
+}

Copied: trunk/geany-plugins/devhelp/src/dhp-plugin.h (from rev 2081, trunk/geany-plugins/devhelp/src/plugin.h)
===================================================================
--- trunk/geany-plugins/devhelp/src/dhp-plugin.h	                        (rev 0)
+++ trunk/geany-plugins/devhelp/src/dhp-plugin.h	2011-05-24 09:04:06 UTC (rev 2082)
@@ -0,0 +1,51 @@
+/*
+ * plugin.h - Part of the Geany Devhelp Plugin
+ *
+ * Copyright 2010 Matthew Brush <mbrush at leftclick.ca>
+ *
+ * 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 3 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef PLUGIN_COMMON_H
+#define PLUGIN_COMMON_H
+
+
+#include <gtk/gtk.h>
+#include <geanyplugin.h>
+
+#include "dhp.h"
+
+
+extern GeanyPlugin	 	*geany_plugin;
+extern GeanyData	   	*geany_data;
+extern GeanyFunctions 	*geany_functions;
+
+
+struct PluginData
+{
+	gchar *default_config;
+	gchar *user_config;
+
+	DevhelpPlugin *devhelp;
+};
+
+extern struct PluginData plugin;
+
+
+gboolean	plugin_config_init			(struct PluginData *pd);
+
+
+#endif

Added: trunk/geany-plugins/devhelp/src/dhp-settings.c
===================================================================
--- trunk/geany-plugins/devhelp/src/dhp-settings.c	                        (rev 0)
+++ trunk/geany-plugins/devhelp/src/dhp-settings.c	2011-05-24 09:04:06 UTC (rev 2082)
@@ -0,0 +1,343 @@
+/* Included directly into dhp-object.c just to keep this whole mess out
+ * of that file until it's not done so stupidly. */
+
+void devhelp_plugin_load_settings(DevhelpPlugin *self, const gchar *filename)
+{
+	GError *error;
+	GKeyFile *kf;
+	gboolean value;
+
+	g_return_if_fail(DEVHELP_IS_PLUGIN(self));
+

@@ Diff output truncated at 100000 characters. @@

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



More information about the Plugins-Commits mailing list