Revision: 2082 http://geany-plugins.svn.sourceforge.net/geany-plugins/?rev=2082&view=re... 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@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@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@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@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@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@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.