1 
2 /*
3  * geanylua.c - Lua scripting plugin for the Geany IDE
4  * Copyright 2007-2008 Jeff Pohlmeyer <yetanothergeek(at)gmail(dot)com>
5  *
6  * Portions copyright Enrico Tröger <enrico.troeger(at)uvena(dot)de>
7  * Portions copyright Nick Treleaven <nick.treleaven(at)btinternet(dot)com>
8  *
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  *
26  * Some portions of this code were adapted from the Lua standalone
27  * interpreter sources, and may be subject to the terms and conditions
28  * specified under the Lua license. See the file COPYRIGHT.LUA for more
29  * information, or visit  http://www.lua.org/license.html .
30  */
31 
32 
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36 
37 
38 #include <geanyplugin.h>
39 
40 #include "glspi_ver.h"
41 
42 #define SUPPORT_LIB "libgeanylua." G_MODULE_SUFFIX
43 
44 #define CB_COPY(field) plugin_callbacks[i].field=glspi_geany_callbacks[i].field;
45 
46 #define GETSYM(name,ptr) ( g_module_symbol(libgeanylua, name, (gpointer) &ptr) && ptr )
47 
48 
49 PLUGIN_EXPORT
50 PLUGIN_VERSION_CHECK(MY_GEANY_API_VER)
51 
52 PLUGIN_EXPORT
53 PLUGIN_SET_INFO(PLUGIN_NAME, PLUGIN_DESC, PLUGIN_VER, PLUGIN_AUTHOR)
54 
55 PLUGIN_EXPORT
56 GeanyPlugin *geany_plugin;
57 
58 
59 
60 typedef void (*InitFunc) (GeanyData *data, GeanyPlugin *plugin);
61 typedef void (*ConfigFunc) (GtkWidget *parent);
62 typedef void (*CleanupFunc) (void);
63 
64 
65 static gchar **glspi_version = NULL;
66 static guint *glspi_abi = NULL;
67 static InitFunc glspi_init = NULL;
68 static ConfigFunc glspi_configure = NULL;
69 static CleanupFunc glspi_cleanup = NULL;
70 static PluginCallback *glspi_geany_callbacks = NULL;
71 
72 
73 
74 /*
75 	It seems to me like we could simply pass the callbacks pointer directly
76 	from the support library to the application. But for some reason that
77 	doesn't work at all. So we make a copy of the callbacks array here,
78 	and all is well...
79 */
80 PLUGIN_EXPORT
81 PluginCallback	plugin_callbacks[8] = {
82 	{NULL, NULL, FALSE, NULL},
83 	{NULL, NULL, FALSE, NULL},
84 	{NULL, NULL, FALSE, NULL},
85 	{NULL, NULL, FALSE, NULL},
86 	{NULL, NULL, FALSE, NULL},
87 	{NULL, NULL, FALSE, NULL},
88 	{NULL, NULL, FALSE, NULL},
89 	{NULL, NULL, FALSE, NULL}
90 };
91 
copy_callbacks(void)92 static void copy_callbacks(void)
93 {
94 	gint i;
95 	for (i=0; glspi_geany_callbacks[i].signal_name; i++) {
96 		CB_COPY(signal_name);
97 		CB_COPY(callback);
98 		CB_COPY(after);
99 		CB_COPY(user_data);
100 	}
101 }
102 
103 
104 
105 static GModule *libgeanylua = NULL;
106 
107 
fail_init(void)108 static void fail_init(void) {
109 	if (libgeanylua) { g_module_close(libgeanylua); }
110 	libgeanylua = NULL;
111 	glspi_version = NULL;
112 	glspi_abi = NULL;
113 	glspi_init = NULL;
114 	glspi_configure = NULL;
115 	glspi_cleanup = NULL;
116 	glspi_geany_callbacks = NULL;
117 	plugin_callbacks[0].signal_name=NULL;
118 	plugin_callbacks[0].callback=NULL;
119 	plugin_callbacks[0].after=FALSE;
120 	plugin_callbacks[0].user_data=NULL;
121 }
122 
123 static GeanyData *geany_data=NULL;
124 
125 
get_lib_dir(void)126 static gchar *get_lib_dir(void)
127 {
128 #ifdef G_OS_WIN32
129 	gchar *install_dir, *result;
130 # if GLIB_CHECK_VERSION(2, 16, 0)
131 	install_dir = g_win32_get_package_installation_directory_of_module(NULL);
132 # else
133 	install_dir = g_win32_get_package_installation_directory(NULL, NULL);
134 # endif
135 	result = g_strconcat(install_dir, "\\lib", NULL);
136 	g_free(install_dir);
137 	return result;
138 #else
139 	return g_strdup(LIBDIR);
140 #endif
141 }
142 
143 
144 
load_support_lib(const gchar * libname)145 static gboolean load_support_lib(const gchar *libname)
146 {
147 	if ( !g_file_test(libname,G_FILE_TEST_IS_REGULAR) ) {
148 		return FALSE;
149 	}
150 	libgeanylua=g_module_open(libname,0);
151 	if (!libgeanylua) {
152 		g_printerr("%s\n", g_module_error());
153 		g_printerr(_("%s: Can't load support library %s!\n"), PLUGIN_NAME, libname);
154 		return FALSE;
155 	}
156 	if ( !(
157 		GETSYM("glspi_version", glspi_version) &&
158 		GETSYM("glspi_abi", glspi_abi) &&
159 		GETSYM("glspi_init", glspi_init) &&
160 		GETSYM("glspi_configure", glspi_configure) &&
161 		GETSYM("glspi_cleanup", glspi_cleanup) &&
162 		GETSYM("glspi_geany_callbacks", glspi_geany_callbacks)
163 	)) {
164 		g_printerr("%s\n", g_module_error());
165 		g_printerr(_("%s: Failed to initialize support library %s!\n"), PLUGIN_NAME, libname);
166 		fail_init();
167 		return FALSE;
168 	}
169 	if (!g_str_equal(*glspi_version, VERSION)) {
170 		g_printerr(_("%s: Support library version mismatch: %s for %s (should be %s)!\n"),
171 			PLUGIN_NAME, *glspi_version, libname, VERSION);
172 		fail_init();
173 		return FALSE;
174 	}
175 	if (*glspi_abi != GEANY_ABI_VERSION) {
176 		g_printerr(_("%s: Support library ABI mismatch: %d for %s (should be %d)!\n"),
177 			PLUGIN_NAME, *glspi_abi, libname, GEANY_ABI_VERSION);
178 		fail_init();
179 		return FALSE;
180 	}
181 	if (geany->app->debug_mode) {
182 		g_printerr("%s: Using support library path: %s\n", PLUGIN_NAME, libname);
183 	}
184 	return TRUE;
185 }
186 
187 
188 PLUGIN_EXPORT
plugin_init(GeanyData * data)189 void plugin_init(GeanyData *data)
190 {
191 	gchar *libname=NULL;
192 
193 	main_locale_init(LOCALEDIR, GETTEXT_PACKAGE);
194 
195 	geany_data=data;
196 	/* first try the user config path */
197 	libname=g_build_path(G_DIR_SEPARATOR_S, data->app->configdir, "plugins", "geanylua", SUPPORT_LIB, NULL);
198 	if (!load_support_lib(libname)) {
199 		/* try the system path */
200 		gchar *libdir=get_lib_dir();
201 		g_free(libname);
202 		libname=g_build_path(G_DIR_SEPARATOR_S, libdir, "geany-plugins", "geanylua", SUPPORT_LIB, NULL);
203 		g_free(libdir);
204 		if (!load_support_lib(libname)) {
205 			g_printerr(_("%s: Can't find support library %s!\n"), PLUGIN_NAME, libname);
206 			g_free(libname);
207 			return;
208 		}
209 	}
210 	g_free(libname);
211 	copy_callbacks();
212 
213 	glspi_init(data, geany_plugin);
214 }
215 
216 
217 PLUGIN_EXPORT
plugin_configure_single(GtkWidget * parent)218 void plugin_configure_single(GtkWidget *parent)
219 {
220 	if (glspi_configure) {
221 		glspi_configure(parent);
222 	} else {
223 		dialogs_show_msgbox(GTK_MESSAGE_ERROR,
224 			_("The %s plugin failed to load properly.\n"
225 			"Please check your installation."), PLUGIN_NAME );
226 	}
227 }
228 
229 
230 PLUGIN_EXPORT
plugin_cleanup(void)231 void plugin_cleanup(void)
232 {
233 	if (glspi_cleanup) { glspi_cleanup(); }
234 	if (libgeanylua) { g_module_close(libgeanylua); }
235 }
236