1 /*
2  * plugin.c - Part of the Geany Devhelp Plugin
3  *
4  * Copyright 2010 Matthew Brush <mbrush@leftclick.ca>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  * MA 02110-1301, USA.
20  */
21 
22 #include <string.h>
23 #include <sys/stat.h> /* for g_mkdir_with_parents, is it portable? */
24 
25 #include <gtk/gtk.h>
26 #include <gdk/gdkkeysyms.h> /* for keybindings */
27 
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31 #include <geanyplugin.h>
32 
33 #include <devhelp/dh-search.h>
34 
35 #include "dhp-plugin.h"
36 #include "dhp.h"
37 
38 
39 GeanyPlugin	 	*geany_plugin;
40 GeanyData	   	*geany_data;
41 
42 
43 struct PluginData
44 {
45 	gchar *default_config;
46 	gchar *user_config;
47 
48 	DevhelpPlugin *devhelp;
49 };
50 
51 
52 struct PluginData plugin_data;
53 
54 /* keybindings */
55 enum
56 {
57 	KB_DEVHELP_TOGGLE_CONTENTS,
58 	KB_DEVHELP_TOGGLE_SEARCH,
59 	KB_DEVHELP_TOGGLE_WEBVIEW,
60 	KB_DEVHELP_ACTIVATE_DEVHELP,
61 	KB_DEVHELP_SEARCH_SYMBOL,
62 	KB_DEVHELP_SEARCH_MANPAGES,
63 	KB_COUNT
64 };
65 
66 /* Called when a keybinding is activated */
kb_activate(guint key_id)67 static void kb_activate(guint key_id)
68 {
69 	gchar *current_tag;
70 
71 	switch (key_id)
72 	{
73 		case KB_DEVHELP_TOGGLE_CONTENTS:
74 			devhelp_plugin_toggle_contents_tab(plugin_data.devhelp);
75 			break;
76 		case KB_DEVHELP_TOGGLE_SEARCH:
77 			devhelp_plugin_toggle_search_tab(plugin_data.devhelp);
78 			break;
79 		case KB_DEVHELP_TOGGLE_WEBVIEW: /* not working */
80 			devhelp_plugin_toggle_webview_tab(plugin_data.devhelp);
81 			break;
82 		case KB_DEVHELP_ACTIVATE_DEVHELP:
83 			devhelp_plugin_activate_all_tabs(plugin_data.devhelp);
84 			break;
85 		case KB_DEVHELP_SEARCH_SYMBOL:
86 		{
87 			current_tag = devhelp_plugin_get_current_word(plugin_data.devhelp);
88 			if (current_tag == NULL)
89 				return;
90 			devhelp_plugin_search_books(plugin_data.devhelp, current_tag);
91 			g_free(current_tag);
92 			break;
93 		}
94 		case KB_DEVHELP_SEARCH_MANPAGES:
95 		{
96 			current_tag = devhelp_plugin_get_current_word(plugin_data.devhelp);
97 			if (current_tag == NULL)
98 				return;
99 			devhelp_plugin_search_manpages(plugin_data.devhelp, current_tag);
100 			g_free(current_tag);
101 			break;
102 		}
103 	}
104 }
105 
106 
plugin_config_init(struct PluginData * pd)107 gboolean plugin_config_init(struct PluginData *pd)
108 {
109 	gchar *user_config_dir;
110 
111 	g_return_val_if_fail(pd != NULL, FALSE);
112 
113 	plugin_data.default_config = g_build_path(G_DIR_SEPARATOR_S, DHPLUG_DATA_DIR, "devhelp.conf", NULL);
114 
115 	user_config_dir = g_build_path(G_DIR_SEPARATOR_S, geany_data->app->configdir, "plugins", "devhelp", NULL);
116 	plugin_data.user_config = g_build_path(G_DIR_SEPARATOR_S, user_config_dir, "devhelp.conf", NULL);
117 	if (g_mkdir_with_parents(user_config_dir, S_IRUSR | S_IWUSR | S_IXUSR) != 0)
118 	{
119 		g_warning(_("Unable to create config dir at '%s'"), user_config_dir);
120 		g_free(user_config_dir);
121 		return FALSE;
122 	}
123 	g_free(user_config_dir);
124 
125 	/* copy default config into user config if it doesn't exist */
126 	if (!g_file_test(pd->user_config, G_FILE_TEST_EXISTS))
127 	{
128 		gchar *config_text;
129 		GError *error;
130 
131 		error = NULL;
132 		if (!g_file_get_contents(pd->default_config, &config_text, NULL, &error))
133 		{
134 			g_warning(_("Unable to get default configuration: %s"), error->message);
135 			g_error_free(error);
136 			return FALSE;
137 		}
138 		else
139 		{
140 			if (!g_file_set_contents(pd->user_config, config_text, -1, &error))
141 			{
142 				g_warning(_("Unable to write default configuration: %s"), error->message);
143 				g_error_free(error);
144 				return FALSE;
145 			}
146 		}
147 	}
148 
149 	return TRUE;
150 }
151 
152 
plugin_devhelp_init(GeanyPlugin * plugin,G_GNUC_UNUSED gpointer pdata)153 static gboolean plugin_devhelp_init(GeanyPlugin *plugin, G_GNUC_UNUSED gpointer pdata)
154 {
155 	GeanyKeyGroup *key_group;
156 
157 	geany_plugin = plugin;
158 	geany_data = plugin->geany_data;
159 
160 	plugin_module_make_resident(geany_plugin);
161 
162 	if (!g_thread_supported())
163 		g_thread_init(NULL);
164 
165 	memset(&plugin_data, 0, sizeof(struct PluginData));
166 
167 	plugin_data.devhelp = devhelp_plugin_new();
168 	plugin_config_init(&plugin_data);
169 
170 	devhelp_plugin_load_settings(plugin_data.devhelp, plugin_data.user_config);
171 
172 	key_group = plugin_set_key_group(geany_plugin, "devhelp", KB_COUNT, NULL);
173 
174 	keybindings_set_item(key_group, KB_DEVHELP_TOGGLE_CONTENTS, kb_activate,
175 		0, 0, "devhelp_toggle_contents", _("Toggle sidebar contents tab"), NULL);
176 	keybindings_set_item(key_group, KB_DEVHELP_TOGGLE_SEARCH, kb_activate,
177 		0, 0, "devhelp_toggle_search", _("Toggle sidebar search tab"), NULL);
178 	keybindings_set_item(key_group, KB_DEVHELP_TOGGLE_WEBVIEW, kb_activate,
179 		0, 0, "devhelp_toggle_webview", _("Toggle documentation tab"), NULL);
180 	keybindings_set_item(key_group, KB_DEVHELP_ACTIVATE_DEVHELP, kb_activate,
181 		0, 0, "devhelp_activate_all", _("Activate all tabs"), NULL);
182 	keybindings_set_item(key_group, KB_DEVHELP_SEARCH_SYMBOL, kb_activate,
183 		0, 0, "devhelp_search_symbol", _("Search for current tag in Devhelp"), NULL);
184 	if (devhelp_plugin_get_have_man_prog(plugin_data.devhelp))
185 	{
186 		keybindings_set_item(key_group, KB_DEVHELP_SEARCH_MANPAGES, kb_activate,
187 			0, 0, "devhelp_search_manpages", _("Search for current tag in Manual Pages"), NULL);
188 	}
189 
190 	return TRUE;
191 }
192 
193 
plugin_devhelp_cleanup(G_GNUC_UNUSED GeanyPlugin * plugin,G_GNUC_UNUSED gpointer pdata)194 static void plugin_devhelp_cleanup(G_GNUC_UNUSED GeanyPlugin *plugin, G_GNUC_UNUSED gpointer pdata)
195 {
196 	devhelp_plugin_store_settings(plugin_data.devhelp, plugin_data.user_config);
197 	g_object_unref(plugin_data.devhelp);
198 	g_free(plugin_data.default_config);
199 	g_free(plugin_data.user_config);
200 }
201 
202 
plugin_devhelp_help(G_GNUC_UNUSED GeanyPlugin * plugin,G_GNUC_UNUSED gpointer pdata)203 static void plugin_devhelp_help (G_GNUC_UNUSED GeanyPlugin *plugin, G_GNUC_UNUSED gpointer pdata)
204 {
205 	utils_open_browser("https://plugins.geany.org/devhelp.html");
206 }
207 
208 
209 /* Load module */
210 G_MODULE_EXPORT
geany_load_module(GeanyPlugin * plugin)211 void geany_load_module(GeanyPlugin *plugin)
212 {
213 	/* Setup translation */
214 	main_locale_init(LOCALEDIR, GETTEXT_PACKAGE);
215 
216 	/* Set metadata */
217 	plugin->info->name = _("Devhelp Plugin");
218 	plugin->info->description = _("Adds support for looking up documentation in Devhelp, manual pages, and "
219 		"Google Code Search in the integrated viewer.");
220 	plugin->info->version = "1.0";
221 	plugin->info->author = "Matthew Brush <mbrush@leftclick.ca>";
222 
223 	/* Set functions */
224 	plugin->funcs->init = plugin_devhelp_init;
225 	plugin->funcs->cleanup = plugin_devhelp_cleanup;
226 	plugin->funcs->help = plugin_devhelp_help;
227 
228 	/* Register! */
229 	GEANY_PLUGIN_REGISTER(plugin, 226);
230 }
231