indentation-c-style: Update preferences UI file to gtk+-3
[anjuta.git] / plugins / debug-manager / variable.c
blob8037d239024df95197860d4159faf1efb9e563b8
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 variable.c
4 Copyright (C) 2008 Sébastien Granjoux
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 laterdversion.
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.
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, MA 02110-1301 USA
22 * Group all objects handling variables (watch, local) and take care of general
23 * feature like variable tips.
24 *---------------------------------------------------------------------------*/
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
30 #include "variable.h"
31 #include "utilities.h"
32 #include "locals.h"
33 #include "watch.h"
35 /*#define DEBUG*/
36 #include <libanjuta/anjuta-debug.h>
37 #include <libanjuta/interfaces/ianjuta-editor-hover.h>
38 #include <libanjuta/interfaces/ianjuta-editor-selection.h>
39 #include <libanjuta/interfaces/ianjuta-document-manager.h>
41 /* Constants
42 *---------------------------------------------------------------------------*/
44 #define DEFAULT_VARIABLE_NAME 64
46 /* Types
47 *---------------------------------------------------------------------------*/
49 struct _DmaVariableDBase
51 AnjutaPlugin *plugin;
53 Locals *locals;
54 ExprWatch *watch;
56 guint editor_watch; /* Editor watch */
57 IAnjutaEditor* editor; /* Current editor */
60 /* Helper functions
61 *---------------------------------------------------------------------------*/
63 static gboolean
64 is_name (gchar c)
66 return g_ascii_isalnum (c) || (c == '_');
69 static gchar*
70 get_hovered_word (IAnjutaEditor* editor, IAnjutaIterable* iter)
72 gchar *buf;
73 IAnjutaIterable *start;
74 IAnjutaIterable *end;
76 if (iter == NULL) return NULL;
78 /* Get selected characters if possible */
79 if (IANJUTA_IS_EDITOR_SELECTION (editor))
81 /* Check if hover on selection */
82 start = ianjuta_editor_selection_get_start (IANJUTA_EDITOR_SELECTION (editor), NULL);
83 if (start && (ianjuta_iterable_compare (start, iter, NULL) <= 0))
85 end = ianjuta_editor_selection_get_end (IANJUTA_EDITOR_SELECTION (editor), NULL);
86 if (end && (ianjuta_iterable_compare (end, iter, NULL) > 0))
88 /* Hover on selection, get selected characters */
89 g_object_unref (end);
90 g_object_unref (start);
91 return ianjuta_editor_selection_get (IANJUTA_EDITOR_SELECTION (editor),
92 NULL);
94 if (end) g_object_unref (end);
96 if (start) g_object_unref (start);
99 /* Find word below cursor */
100 DEBUG_PRINT("current char %c", ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL));
101 if (!is_name (ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (iter), 0, NULL)))
103 /* Not hover on a name */
104 return NULL;
107 /* Look for the beginning of the name */
108 for (start = ianjuta_iterable_clone (iter, NULL); ianjuta_iterable_previous (start, NULL);)
110 if (!is_name (ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (start), 0, NULL)))
112 ianjuta_iterable_next (start, NULL);
113 break;
117 /* Look for the end of the name */
118 for (end = ianjuta_iterable_clone (iter, NULL); ianjuta_iterable_next (end, NULL);)
120 if (!is_name (ianjuta_editor_cell_get_char (IANJUTA_EDITOR_CELL (end), 0, NULL)))
121 break;
124 buf = ianjuta_editor_get_text (editor, start, end, NULL);
125 DEBUG_PRINT("get name %s", buf == NULL ? "(null)" : buf);
126 g_object_unref (start);
127 g_object_unref (end);
129 return buf;
132 /* Private functions
133 *---------------------------------------------------------------------------*/
135 /* Callback functions
136 *---------------------------------------------------------------------------*/
138 static void
139 on_hover_over (DmaVariableDBase *self, IAnjutaIterable* pos, IAnjutaEditorHover* editor)
141 gchar *name;
143 DEBUG_PRINT("Hover on editor %p at %d", editor,
144 pos == NULL ? -1 : ianjuta_iterable_get_position (pos, NULL));
146 name = get_hovered_word (IANJUTA_EDITOR (editor), pos);
147 if (name != NULL)
149 gchar *value;
151 /* Search for variable in local */
152 value = locals_find_variable_value (self->locals, name);
153 if (value == NULL)
155 /* Not found search in watch */
156 value = expr_watch_find_variable_value (self->watch, name);
157 if (value == NULL)
159 /* Does not exist */
160 g_free (name);
161 return;
165 gchar *display;
167 display = g_strconcat(name, " = ", value, NULL);
168 ianjuta_editor_hover_display (editor, pos, display, NULL);
169 g_free (display);
170 g_free (value);
171 g_free (name);
175 static void
176 on_added_current_editor (AnjutaPlugin *plugin, const char *name,
177 const GValue *value, gpointer user_data)
179 DmaVariableDBase *self = (DmaVariableDBase *)user_data;
180 GObject *editor;
182 editor = g_value_get_object (value);
184 /* Connect to hover interface */
185 if (IANJUTA_IS_EDITOR_HOVER (editor))
187 g_signal_connect_swapped (editor, "hover-over", G_CALLBACK (on_hover_over), self);
188 self->editor = IANJUTA_EDITOR (editor);
192 static void
193 on_removed_current_editor (AnjutaPlugin *plugin,
194 const char *name, gpointer user_data)
196 DmaVariableDBase *self = (DmaVariableDBase *)user_data;
198 /* Disconnect to previous hover interface */
199 if (self->editor != NULL)
201 g_signal_handlers_disconnect_matched (self->editor, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
202 self->editor = NULL;
206 static void
207 on_program_running (DmaVariableDBase *self)
209 if (self->editor_watch != -1)
211 anjuta_plugin_remove_watch (ANJUTA_PLUGIN(self->plugin), self->editor_watch, TRUE);
212 self->editor_watch = -1;
216 static void
217 on_program_stopped (DmaVariableDBase *self)
219 if (self->editor_watch == -1)
221 /* set editor watch */
222 self->editor_watch = anjuta_plugin_add_watch (ANJUTA_PLUGIN(self->plugin), IANJUTA_DOCUMENT_MANAGER_CURRENT_DOCUMENT,
223 on_added_current_editor, on_removed_current_editor, self);
227 static void
228 on_program_exited (DmaVariableDBase *self)
230 if (self->editor_watch != -1)
232 anjuta_plugin_remove_watch (ANJUTA_PLUGIN(self->plugin), self->editor_watch, TRUE);
233 self->editor_watch = -1;
236 /* Disconnect from other debugger signal */
237 g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_program_exited), self);
238 g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_program_stopped), self);
239 g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_program_running), self);
242 static void
243 on_program_started (DmaVariableDBase *self)
245 /* Connect to other debugger signal */
246 g_signal_connect_swapped (self->plugin, "program-stopped", G_CALLBACK (on_program_stopped), self);
247 g_signal_connect_swapped (self->plugin, "program-exited", G_CALLBACK (on_program_exited), self);
248 g_signal_connect_swapped (self->plugin, "program-running", G_CALLBACK (on_program_running), self);
251 /* Constructor & Destructor
252 *---------------------------------------------------------------------------*/
254 DmaVariableDBase *
255 dma_variable_dbase_new (DebugManagerPlugin *plugin)
257 DmaVariableDBase *self = g_new0 (DmaVariableDBase, 1);
259 self->plugin = ANJUTA_PLUGIN (plugin);
260 self->editor_watch = -1;
261 self->editor = NULL;
262 self->watch = expr_watch_new (ANJUTA_PLUGIN (plugin));
263 self->locals = locals_new (plugin);
265 g_signal_connect_swapped (self->plugin, "program-started", G_CALLBACK (on_program_started), self);
267 return self;
270 void
271 dma_variable_dbase_free (DmaVariableDBase *self)
273 g_return_if_fail (self != NULL);
275 g_signal_handlers_disconnect_matched (self->plugin, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
277 locals_free (self->locals);
278 expr_watch_destroy (self->watch);
280 g_free (self);