1 /*
2 * plugin.c
3 *
4 * Copyright 2010 Alexander Petukhov <devel(at)apetukhov.ru>
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 2 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 /*
23 * geany debugger plugin
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 #include <geanyplugin.h>
30
31 #include "breakpoints.h"
32 #include "callbacks.h"
33 #include "debug.h"
34 #include "tpage.h"
35 #include "utils.h"
36 #include "btnpanel.h"
37 #include "keys.h"
38 #include "dconfig.h"
39 #include "dpaned.h"
40 #include "tabs.h"
41 #include "envtree.h"
42 #include "pixbuf.h"
43
44 /* These items are set by Geany before plugin_init() is called. */
45 GeanyPlugin *geany_plugin;
46 GeanyData *geany_data;
47
48 /* vbox for keeping breaks/stack/watch notebook */
49 static GtkWidget *hbox = NULL;
50
51 static PluginCallback plugin_debugger_callbacks[] =
52 {
53 /* Set 'after' (third field) to TRUE to run the callback @a after the default handler.
54 * If 'after' is FALSE, the callback is run @a before the default handler, so the plugin
55 * can prevent Geany from processing the notification. Use this with care. */
56 { "editor-notify", (GCallback) &on_editor_notify, FALSE, NULL },
57 { "document_open", (GCallback) &on_document_open, FALSE, NULL },
58 { "document_save", (GCallback) &on_document_save, FALSE, NULL },
59 { "document_before_save", (GCallback) &on_document_before_save, FALSE, NULL },
60 { "project_open", (GCallback) &config_on_project_open, FALSE, NULL },
61 { "project_close", (GCallback) &config_on_project_close, FALSE, NULL },
62 { "project_save", (GCallback) &config_on_project_save, FALSE, NULL },
63
64 { NULL, NULL, FALSE, NULL }
65 };
66
on_paned_mode_changed(GtkToggleButton * button,gpointer user_data)67 static void on_paned_mode_changed(GtkToggleButton *button, gpointer user_data)
68 {
69 gboolean state = gtk_toggle_button_get_active(button);
70 dpaned_set_tabbed(state);
71 tpage_pack_widgets(state);
72 }
73
74 /* Called by Geany to initialize the plugin.
75 * Note: data is the same as geany_data. */
plugin_debugger_init(GeanyPlugin * plugin,G_GNUC_UNUSED gpointer pdata)76 static gboolean plugin_debugger_init(GeanyPlugin *plugin, G_GNUC_UNUSED gpointer pdata)
77 {
78 GtkWidget* vbox;
79 guint i;
80
81 geany_plugin = plugin;
82 geany_data = plugin->geany_data;
83
84 plugin_module_make_resident(geany_plugin);
85
86 keys_init();
87
88 pixbufs_init();
89
90 /* main box */
91 #if GTK_CHECK_VERSION(3, 0, 0)
92 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 7);
93 #else
94 hbox = gtk_hbox_new(FALSE, 7);
95 #endif
96 gtk_container_set_border_width(GTK_CONTAINER(hbox), 6);
97
98 /* add target page */
99 tpage_init();
100
101 /* init brekpoints */
102 breaks_init(editor_open_position);
103
104 /* init markers */
105 markers_init();
106
107 /* init debug */
108 debug_init();
109
110 /* load config */
111 config_init();
112
113 /* init paned */
114 dpaned_init();
115 tpage_pack_widgets(config_get_tabbed());
116
117 vbox = btnpanel_create(on_paned_mode_changed);
118
119 gtk_box_pack_start(GTK_BOX(hbox), dpaned_get_paned(), TRUE, TRUE, 0);
120 gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
121
122 gtk_widget_show_all(hbox);
123
124 gtk_notebook_append_page(
125 GTK_NOTEBOOK(geany->main_widgets->message_window_notebook),
126 hbox,
127 gtk_label_new(_("Debug")));
128
129 if (geany_data->app->project)
130 {
131 config_update_project_keyfile();
132 }
133 config_set_debug_store(
134 config_get_save_to_project() && geany_data->app->project ? DEBUG_STORE_PROJECT : DEBUG_STORE_PLUGIN
135 );
136
137 /* set calltips for all currently opened documents */
138 foreach_document(i)
139 {
140 scintilla_send_message(document_index(i)->editor->sci, SCI_SETMOUSEDWELLTIME, 500, 0);
141 scintilla_send_message(document_index(i)->editor->sci, SCI_CALLTIPUSESTYLE, 20, (long)NULL);
142 }
143
144 return TRUE;
145 }
146
147 /* Called by Geany to show the plugin's configure dialog. This function is always called after
148 * plugin_init() was called.
149 * You can omit this function if the plugin doesn't need to be configured.
150 * Note: parent is the parent window which can be used as the transient window for the created
151 * dialog. */
plugin_debugger_configure(G_GNUC_UNUSED GeanyPlugin * plugin,GtkDialog * dialog,G_GNUC_UNUSED gpointer pdata)152 static GtkWidget *plugin_debugger_configure(G_GNUC_UNUSED GeanyPlugin *plugin, GtkDialog *dialog, G_GNUC_UNUSED gpointer pdata)
153 {
154 return config_plugin_configure(dialog);
155 }
156
157
158 /* Called by Geany before unloading the plugin.
159 * Here any UI changes should be removed, memory freed and any other finalization done.
160 * Be sure to leave Geany as it was before plugin_init(). */
plugin_debugger_cleanup(G_GNUC_UNUSED GeanyPlugin * plugin,G_GNUC_UNUSED gpointer pdata)161 static void plugin_debugger_cleanup(G_GNUC_UNUSED GeanyPlugin *plugin, G_GNUC_UNUSED gpointer pdata)
162 {
163 /* stop debugger if running */
164 if (DBS_IDLE != debug_get_state())
165 {
166 debug_stop();
167 while (DBS_IDLE != debug_get_state())
168 g_main_context_iteration(NULL,FALSE);
169 }
170
171 config_destroy();
172 pixbufs_destroy();
173 debug_destroy();
174 breaks_destroy();
175 dpaned_destroy();
176 envtree_destroy();
177
178 /* release other allocated strings and objects */
179 gtk_widget_destroy(hbox);
180 }
181
182
183 /* Show help */
plugin_debugger_help(G_GNUC_UNUSED GeanyPlugin * plugin,G_GNUC_UNUSED gpointer pdata)184 static void plugin_debugger_help (G_GNUC_UNUSED GeanyPlugin *plugin, G_GNUC_UNUSED gpointer pdata)
185 {
186 utils_open_browser("https://plugins.geany.org/debugger.html");
187 }
188
189
190 /* Load module */
191 G_MODULE_EXPORT
geany_load_module(GeanyPlugin * plugin)192 void geany_load_module(GeanyPlugin *plugin)
193 {
194 /* Setup translation */
195 main_locale_init(LOCALEDIR, GETTEXT_PACKAGE);
196
197 /* Set metadata */
198 plugin->info->name = _("Debugger");
199 plugin->info->description = _("Various debuggers integration.");
200 plugin->info->version = VERSION;
201 plugin->info->author = "Alexander Petukhov <devel@apetukhov.ru>";
202
203 /* Set functions */
204 plugin->funcs->init = plugin_debugger_init;
205 plugin->funcs->cleanup = plugin_debugger_cleanup;
206 plugin->funcs->help = plugin_debugger_help;
207 plugin->funcs->configure = plugin_debugger_configure;
208 plugin->funcs->callbacks = plugin_debugger_callbacks;
209
210 /* Register! */
211 GEANY_PLUGIN_REGISTER(plugin, 226);
212 }
213