1 /*
2  *      debug.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  * 		Debug activities handlers (Run, Stop, etc)
24  *		Manages GUI that is debug-state dependent.
25  * 		Finaly, after checking current debug state - passes
26  * 		command to the active debug module.
27  * 		Also creates debug-related GUI (local, debug terminal pages)
28  * 		and handles run-time watches and breakpoints changes.
29  * 		Contains callbacks from debugger module to handle debug state changes.
30  */
31 
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35 
36 #include <stdio.h>
37 
38 #include <stdlib.h>
39 int unlockpt(int fildes);
40 int grantpt(int fd);
41 
42 #include <string.h>
43 #include <unistd.h>
44 #if defined(HAVE_UTIL_H)
45 #include <util.h>
46 #elif defined(HAVE_LIBUTIL_H)
47 #include <libutil.h>
48 #elif defined(HAVE_PTY_H)
49 #include <pty.h>
50 #endif
51 #include <gtk/gtk.h>
52 #include <gdk/gdkkeysyms.h>
53 #include <vte/vte.h>
54 
55 #ifdef HAVE_CONFIG_H
56 	#include "config.h"
57 #endif
58 #include <geanyplugin.h>
59 #include <gp_vtecompat.h>
60 extern GeanyData		*geany_data;
61 
62 #include "tpage.h"
63 #include "breakpoints.h"
64 #include "debug.h"
65 #include "utils.h"
66 #include "stree.h"
67 #include "watch_model.h"
68 #include "wtree.h"
69 #include "atree.h"
70 #include "tpage.h"
71 #include "calltip.h"
72 #include "bptree.h"
73 #include "btnpanel.h"
74 #include "dconfig.h"
75 #include "tabs.h"
76 
77 /*
78  *  calltip size
79  */
80 #define CALLTIP_HEIGHT 20
81 #define CALLTIP_WIDTH 200
82 
83 /* module description structure (name/module pointer) */
84 typedef struct _module_description {
85 	const gchar *title;
86 	dbg_module *module;
87 } module_description;
88 
89 /* holds current debug state */
90 enum dbs debug_state = DBS_IDLE;
91 
92 /* debug modules declarations */
93 extern dbg_module dbg_module_gdb;
94 /* extern dbg_module dbg_module_bash; */
95 
96 /* active debug module */
97 dbg_module *active_module = NULL;
98 
99 /* Interrupt relateed data
100  * Interrtion is requested when breakpoint is set/added/removed
101  * asyncronously. Then debug_request_interrupt is called,
102  * supplied with interrupt reason (interrupt_flags),
103  * breakpoint pointer (interrupt_data) and callback to call
104  * after interruption
105  */
106 bs_callback			interrupt_cb = NULL;
107 gpointer			interrupt_data = NULL;
108 
109 /* flag to set when debug stop is requested while debugger is running.
110  * Then this flag is set to TRUE, and debug_request_interrupt function is called
111  */
112 gboolean exit_pending = FALSE;
113 
114 /* debug terminal PTY master/slave file descriptors */
115 int pty_master, pty_slave;
116 
117 /* debug terminal widget */
118 GtkWidget *terminal = NULL;
119 
120 /* GtkTextView to put debugger messages */
121 static GtkWidget *debugger_messages_textview = NULL;
122 
123 /*
124  * Adjustments of a scroll view containing debugger messages
125  * text view. Values are changed during new text adding.
126  */
127 static GtkAdjustment *hadj = NULL;
128 static GtkAdjustment *vadj = NULL;
129 
130 /* stack trace/watch/autos CtkTreeView widgets */
131 static GtkWidget *stree = NULL;
132 static GtkWidget *wtree = NULL;
133 static GtkWidget *atree = NULL;
134 
135 /* watch tree view model and store */
136 GtkTreeStore *wstore = NULL;
137 GtkTreeModel *wmodel = NULL;
138 
139 /* array of widgets, ti enable/disable regard of a debug state */
140 static GtkWidget **sensitive_widget[] = {&stree, &wtree, &atree, NULL};
141 
142 /*
143  * current stack for holding
144  * position of ffreames markers
145  */
146 static GList* stack = NULL;
147 
148 /*
149  * pages which are loaded in debugger and therefore, are set readonly
150  */
151 static GList *read_only_pages = NULL;
152 
153 /* available modules */
154 static module_description modules[] =
155 {
156 	{ "GDB", &dbg_module_gdb },
157 	{ NULL, NULL }
158 };
159 
160 /* calltips cache  */
161 static GHashTable *calltips = NULL;
162 
163 /*
164  * remove stack margin markers
165  */
remove_stack_markers(void)166 static void remove_stack_markers(void)
167 {
168 	int active_frame_index = active_module->get_active_frame();
169 
170 	GList *iter;
171 	int frame_index;
172 	for (iter = stack, frame_index = 0; iter; iter = iter->next, frame_index++)
173 	{
174 		if (iter)
175 		{
176 			frame *f = (frame*)iter->data;
177 			if (f->have_source)
178 			{
179 				if (active_frame_index == frame_index)
180 				{
181 					markers_remove_current_instruction(f->file, f->line);
182 				}
183 				else
184 				{
185 					markers_remove_frame(f->file, f->line);
186 				}
187 			}
188 		}
189 	}
190 }
191 
192 /*
193  * add stack margin markers
194  */
add_stack_markers(void)195 static void add_stack_markers(void)
196 {
197 	int active_frame_index = active_module->get_active_frame();
198 
199 	GList *iter;
200 	int frame_index;
201 	for (iter = stack, frame_index = 0; iter; iter = iter->next, frame_index++)
202 	{
203 		if (iter)
204 		{
205 			frame *f = (frame*)iter->data;
206 			if (f->have_source)
207 			{
208 				if (active_frame_index == frame_index)
209 				{
210 					markers_add_current_instruction(f->file, f->line);
211 				}
212 				else
213 				{
214 					markers_add_frame(f->file, f->line);
215 				}
216 			}
217 		}
218 	}
219 }
220 
221 /*
222  * Handlers for GUI maked changes in watches
223  */
224 
225 /*
226  * watch expression has been changed
227  */
on_watch_changed(GtkCellRendererText * renderer,gchar * path,gchar * new_text,gpointer user_data)228 static void on_watch_changed(GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer user_data)
229 {
230 	/* get iterator to the changed row */
231 	GtkTreeIter  iter;
232 	gchar *oldvalue;
233 	gchar *internal = NULL;
234 	GtkTreePath *empty_path;
235 	GtkTreePath *tree_path = gtk_tree_path_new_from_string (path);
236 	gboolean is_empty_row;
237 	gchar *striped;
238 
239 	gtk_tree_model_get_iter (
240 		 gtk_tree_view_get_model(GTK_TREE_VIEW(wtree)),
241 		 &iter,
242 		 tree_path);
243 
244 	/* get oldvalue */
245 	gtk_tree_model_get (
246 		wmodel,
247 		&iter,
248 		W_NAME, &oldvalue,
249 		-1);
250 	gtk_tree_model_get (
251 		wmodel,
252 		&iter,
253 		W_INTERNAL, &internal,
254 		-1);
255 
256 	/* check if it is empty row */
257 	empty_path = wtree_empty_path();
258 	is_empty_row = !gtk_tree_path_compare (tree_path, empty_path);
259 	gtk_tree_path_free(empty_path);
260 
261 	striped = g_strstrip(g_strdup(new_text));
262 	if (!strlen(striped) &&
263 		!is_empty_row &&
264 		dialogs_show_question(_("Delete variable?")))
265 	{
266 		/* if new value is empty string on non-empty row
267 		 * offer to delete watch */
268 		gtk_tree_store_remove(wstore, &iter);
269 		if (DBS_STOPPED == debug_state)
270 			active_module->remove_watch(internal);
271 
272 		config_set_debug_changed();
273 	}
274 	else if (strcmp(oldvalue, striped))
275     {
276 		/* new value is non empty */
277 
278 		/* insert new row if changing was the last empty row */
279 		GtkTreeIter newiter;
280 		if (is_empty_row)
281 			gtk_tree_store_insert_before(wstore, &newiter, NULL, &iter);
282 
283 		/* set expression */
284 		variable_set_name_only(wstore, is_empty_row ? &newiter : &iter, striped);
285 
286 		/* if debug is active - remove old watch and add new one */
287 		if (DBS_STOPPED == debug_state)
288 		{
289 			variable *newvar;
290 
291 			active_module->remove_watch(internal);
292 			newvar = active_module->add_watch(striped);
293 			change_watch(GTK_TREE_VIEW(wtree), is_empty_row ? &newiter : &iter, newvar);
294 		}
295 
296 		/* if new watch has been added - set selection to the new created row */
297 		if (is_empty_row)
298 		{
299 			GtkTreePath *_path = gtk_tree_model_get_path(wmodel, &newiter);
300 			GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(wtree));
301 			gtk_tree_selection_unselect_all(selection);
302 			gtk_tree_selection_select_path(selection, _path);
303 			gtk_tree_path_free(_path);
304 		}
305 
306 		config_set_debug_changed();
307 	}
308 
309 	/* free resources */
310 	gtk_tree_path_free(tree_path);
311 	g_free(oldvalue);
312 	g_free(internal);
313 	g_free(striped);
314 }
315 
316 /*
317  * text has been dragged into the watch tree view
318  */
on_watch_dragged_callback(GtkWidget * wgt,GdkDragContext * context,int x,int y,GtkSelectionData * seldata,guint info,guint _time,gpointer userdata)319 static void on_watch_dragged_callback(GtkWidget *wgt, GdkDragContext *context, int x, int y,
320 	GtkSelectionData *seldata, guint info, guint _time,
321     gpointer userdata)
322 {
323 	/* string that is dragged */
324 	gchar *expression = (gchar*)gtk_selection_data_get_data(seldata);
325 	GtkTreePath *path = NULL;
326 	GtkTreeViewDropPosition pos;
327 	GtkTreePath *empty_path;
328 	GtkTreeIter newvar;
329 
330 	/* lookup for where the text has been dropped */
331 	gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(wtree), x, y, &path, &pos);
332 
333 	/* if dropped into last row - insert before it */
334 	empty_path = wtree_empty_path();
335 	if (!gtk_tree_path_compare(empty_path, path))
336 		pos = GTK_TREE_VIEW_DROP_BEFORE;
337 	gtk_tree_path_free(empty_path);
338 
339 	/* if dropped into children area - insert before parent */
340 	if (gtk_tree_path_get_depth(path) > 1)
341 	{
342 		while (gtk_tree_path_get_depth(path) > 1)
343 			gtk_tree_path_up(path);
344 		pos = GTK_TREE_VIEW_DROP_BEFORE;
345 	}
346 
347 	/* insert new row */
348 	if (path)
349 	{
350 		GtkTreeIter sibling;
351 		gtk_tree_model_get_iter(wmodel, &sibling, path);
352 
353 		if (GTK_TREE_VIEW_DROP_BEFORE == pos || GTK_TREE_VIEW_DROP_INTO_OR_BEFORE == pos)
354 			gtk_tree_store_insert_before(wstore, &newvar, NULL, &sibling);
355 		else
356 			gtk_tree_store_insert_after(wstore, &newvar, NULL, &sibling);
357 	}
358 	else
359 	{
360 		GtkTreeIter empty;
361 
362 		wtree_empty_row(&empty);
363 		gtk_tree_store_insert_before(wstore, &newvar, NULL, &empty);
364 	}
365 
366 	/* if debugger is active (in stopped condition) - add to run-time watch list
367 	 *  if not - just set new expession in the tree view */
368 	if (DBS_STOPPED == debug_state)
369 	{
370 		variable *var = active_module->add_watch(expression);
371 		change_watch(GTK_TREE_VIEW(wtree), &newvar, var);
372 	}
373 	else
374 		variable_set_name_only(wstore, &newvar, expression);
375 
376 	config_set_debug_changed();
377 }
378 
379 /*
380  * key has been pressed while being in watch tree view
381  */
on_watch_key_pressed_callback(GtkWidget * widget,GdkEvent * event,gpointer user_data)382 static gboolean on_watch_key_pressed_callback(GtkWidget *widget, GdkEvent  *event, gpointer user_data)
383 {
384 	GtkTreeSelection *selection;
385 	GList *rows;
386 	GtkTreePath *empty_path;
387 
388 	/* handling only Delete button pressing
389 	 * that means "delete selected rows" */
390 	if (((GdkEventKey*)event)->keyval != GDK_Delete)
391 		return FALSE;
392 
393 	/* get selected rows */
394 	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(wtree));
395 	rows = gtk_tree_selection_get_selected_rows(selection, &wmodel);
396 
397 	/* empty row path */
398 	empty_path = wtree_empty_path();
399 
400 	/* check whether only empty row was selected */
401 	if (1 != gtk_tree_selection_count_selected_rows(selection) ||
402 	    (rows && gtk_tree_path_compare((GtkTreePath*)rows->data, empty_path)))
403 	{
404 		/* path reference to select after deleteing finishes */
405 		GtkTreeRowReference *reference_to_select = NULL;
406 		GtkTreePath *path_to_select;
407 
408 		/* get references to the rows */
409 		GList *references = NULL;
410 		GList *iter = rows;
411 		while (iter)
412 		{
413 			GtkTreePath *path = (GtkTreePath*)iter->data;
414 
415 			/* move up paths to the root elements */
416 			while (gtk_tree_path_get_depth(path) > 1)
417 				gtk_tree_path_up(path);
418 
419 			/* add path reference if it's not an empty row*/
420 			if (gtk_tree_path_compare(path, empty_path))
421 				references = g_list_prepend(references, gtk_tree_row_reference_new(wmodel, path));
422 
423 			iter = iter->next;
424 		}
425 
426 		/* iterate through references and remove */
427 		iter = g_list_reverse(references);
428 		while (iter)
429 		{
430 			GtkTreeRowReference *reference = (GtkTreeRowReference*)iter->data;
431 			/* check for valid reference because two or more equal
432 			refernces could be put in the list if several child items
433 			of the same node were selected and the path for the
434 			current reference was already deleted */
435 			if (gtk_tree_row_reference_valid(reference))
436 			{
437 				GtkTreeIter titer;
438 				GtkTreePath *path = gtk_tree_row_reference_get_path(reference);
439 
440 				if (!reference_to_select)
441 				{
442 					/* select upper sibling of the upper
443 					selected row that has unselected upper sibling */
444 					GtkTreePath *sibling = gtk_tree_path_copy(path);
445 					if(gtk_tree_path_prev(sibling))
446 					{
447 						if (!gtk_tree_selection_path_is_selected(selection, sibling))
448 							reference_to_select = gtk_tree_row_reference_new(gtk_tree_view_get_model(GTK_TREE_VIEW(wtree)), sibling);
449 					}
450 					else if (gtk_tree_path_next(sibling), gtk_tree_path_compare(path, sibling))
451 						reference_to_select = gtk_tree_row_reference_new(gtk_tree_view_get_model(GTK_TREE_VIEW(wtree)), sibling);
452 				}
453 
454 				/* get iterator */
455 				gtk_tree_model_get_iter(wmodel, &titer, path);
456 
457 				/* remove from the debug session, if it's active */
458 				if (DBS_STOPPED == debug_state)
459 				{
460 
461 					gchar *internal = NULL;
462 					gtk_tree_model_get (
463 						wmodel,
464 						&titer,
465 						W_INTERNAL, &internal,
466 						-1);
467 
468 					active_module->remove_watch(internal);
469 
470 					g_free(internal);
471 				}
472 
473 
474 				gtk_tree_store_remove(wstore, &titer);
475 
476 				gtk_tree_path_free(path);
477 			}
478 
479 			iter = iter->next;
480 		}
481 
482 		/* if all (with or without empty row) was selected - set empty row
483 		as a path to be selected after deleting */
484 		if (!reference_to_select)
485 		{
486 			GtkTreePath *path = wtree_empty_path();
487 			reference_to_select = gtk_tree_row_reference_new (gtk_tree_view_get_model(GTK_TREE_VIEW(wtree)), path);
488 			gtk_tree_path_free(path);
489 		}
490 
491 		/* set selection */
492 		gtk_tree_selection_unselect_all(selection);
493 		path_to_select = gtk_tree_row_reference_get_path(reference_to_select);
494 		gtk_tree_selection_select_path(selection, path_to_select);
495 		gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(widget), path_to_select, NULL, TRUE, 0.5, 0.5);
496 		gtk_tree_path_free(path_to_select);
497 
498 		/* free references list */
499 		g_list_foreach (references, (GFunc)gtk_tree_row_reference_free, NULL);
500 		g_list_free (references);
501 
502 		config_set_debug_changed();
503 	}
504 
505 	gtk_tree_path_free(empty_path);
506 
507 	/* free rows list */
508 	g_list_foreach (rows, (GFunc)gtk_tree_path_free, NULL);
509 	g_list_free (rows);
510 
511 	return FALSE;
512 }
513 
514 /*
515  * mouse button has been pressed while being in watch(autos) tree view
516  */
on_watch_button_pressed_callback(GtkWidget * treeview,GdkEventButton * event,gpointer userdata)517 static gboolean on_watch_button_pressed_callback(GtkWidget *treeview, GdkEventButton *event, gpointer userdata)
518 {
519     if (event->type == GDK_2BUTTON_PRESS  &&  event->button == 1)
520 	{
521 		GtkTreePath *path = NULL;
522 		if (gtk_tree_view_get_path_at_pos(
523 			GTK_TREE_VIEW(treeview),
524 		    (int)event->x, (int)event->y, &path, NULL, NULL, NULL))
525 		{
526 			gchar *expression = NULL;
527 			GtkTreeIter iter;
528 			GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
529 			gtk_tree_model_get_iter (model, &iter, path);
530 
531 			gtk_tree_model_get(model, &iter,
532 				W_EXPRESSION, &expression,
533 			    -1);
534 
535 			if (strlen(expression))
536 			{
537 				GtkTreeIter newvar, empty;
538 
539 				wtree_empty_row(&empty);
540 				gtk_tree_store_insert_before(wstore, &newvar, NULL, &empty);
541 
542 				/* if debugger is active (in stopped condition) - add to run-time watch list
543 				 *  if not - just set new expession in the tree view */
544 				if (DBS_STOPPED == debug_state)
545 				{
546 					variable *var = active_module->add_watch(expression);
547 					change_watch(GTK_TREE_VIEW(wtree), &newvar, var);
548 				}
549 				else
550 					variable_set_name_only(wstore, &newvar, expression);
551 
552 				config_set_debug_changed();
553 			}
554 
555 			g_free(expression);
556 		}
557 	}
558 
559 	return FALSE;
560 }
561 
562 
563 /*
564  * watch that has children has been expanded
565  */
on_watch_expanded_callback(GtkTreeView * tree,GtkTreeIter * iter,GtkTreePath * path,gpointer user_data)566 static void on_watch_expanded_callback(GtkTreeView *tree, GtkTreeIter *iter, GtkTreePath *path, gpointer user_data)
567 {
568 	/* get tree view model and store as it can be watch or autos tree */
569 	GtkTreeModel *model = gtk_tree_view_get_model(tree);
570 	GtkTreeStore *store = GTK_TREE_STORE(model);
571 
572 	/* get a flag indicating that item has only stub andd need to
573 	 * evaluate its children */
574 	gboolean only_stub = FALSE;
575 	gtk_tree_model_get (
576 		model,
577 		iter,
578 		W_STUB, &only_stub,
579 		-1);
580 
581 	if (only_stub)
582 	{
583 		GList *children;
584 		gchar *internal;
585 
586 		/* if item has not been expanded before */
587 		gtk_tree_model_get (
588 			model,
589 			iter,
590 			W_INTERNAL, &internal,
591 			-1);
592 
593 		/* get children list */
594 		children = active_module->get_children(internal);
595 
596 		/* remove stub and add children */
597 		expand_stub(tree, iter, children);
598 
599 		/* free children list */
600 		free_variables_list(children);
601 
602 		/* unset W_STUB flag */
603 		gtk_tree_store_set (store, iter,
604 			W_STUB, FALSE,
605 			-1);
606 
607 		g_free(internal);
608 	}
609 }
610 
611 /*
612  * GUI functions
613  */
614 
615 /*
616  * enable/disable sensitive widgets
617  * arguments:
618  * 		enable - enable or disable widgets
619  */
enable_sensitive_widgets(gboolean enable)620 static void enable_sensitive_widgets(gboolean enable)
621 {
622 	int i;
623 	for(i = 0; sensitive_widget[i]; i++)
624 		gtk_widget_set_sensitive(*sensitive_widget[i], enable);
625 }
626 
627 /*
628  * Debug state changed hanflers
629  */
630 
631 /*
632  * called from debug module when debugger is being run
633  */
on_debugger_run(void)634 static void on_debugger_run (void)
635 {
636 	/* update debug state */
637 	debug_state = DBS_RUNNING;
638 
639 	/* if curren instruction marker was set previously - remove it */
640 	if (stack)
641 	{
642 		remove_stack_markers();
643 		g_list_foreach(stack, (GFunc)frame_unref, NULL);
644 		g_list_free(stack);
645 		stack = NULL;
646 
647 		stree_remove_frames();
648 	}
649 
650 	/* disable widgets */
651 	enable_sensitive_widgets(FALSE);
652 
653 	/* update buttons panel state */
654 	btnpanel_set_debug_state(debug_state);
655 }
656 
657 
658 /*
659  * called from debug module when debugger is being stopped
660  */
on_debugger_stopped(int thread_id)661 static void on_debugger_stopped (int thread_id)
662 {
663 	GList *iter, *files, *autos, *watches;
664 
665 	/* update debug state */
666 	debug_state = DBS_STOPPED;
667 
668 	/* update buttons panel state */
669 	if (!interrupt_data)
670 	{
671 		btnpanel_set_debug_state(debug_state);
672 	}
673 
674 	/* clear calltips cache */
675 	if (calltips)
676 		g_hash_table_remove_all(calltips);
677 
678 	/* if a stop was requested for asyncronous exiting -
679 	 * stop debug module and exit */
680 	if (exit_pending)
681 	{
682 		active_module->stop();
683 		exit_pending = FALSE;
684 		return;
685 	}
686 
687 	/* check for async activities pending */
688 	if (interrupt_data)
689 	{
690 		interrupt_cb(interrupt_data);
691 		interrupt_data = NULL;
692 
693 		active_module->resume();
694 
695 		return;
696 	}
697 
698 	/* clear stack tree view */
699 	stree_set_active_thread_id(thread_id);
700 
701 	/* get current stack trace and put in the tree view */
702 	stack = active_module->get_stack();
703 	stree_add (stack);
704 	stree_select_first_frame(TRUE);
705 
706 	/* files */
707 	files = active_module->get_files();
708 	/* remove from list and make writable those files,
709 	that are not in the current list */
710 	iter = read_only_pages;
711 	while (iter)
712 	{
713 		if (!g_list_find_custom(files, iter->data, (GCompareFunc)g_strcmp0))
714 		{
715 			GList *next;
716 
717 			/* set document writable */
718 			GeanyDocument *doc = document_find_by_real_path((const gchar*)iter->data);
719 			if (doc)
720 				scintilla_send_message(doc->editor->sci, SCI_SETREADONLY, 0, 0);
721 
722 			/* free file name */
723 			g_free(iter->data);
724 			/* save next item pointer */
725 			next = iter->next;
726 			/* remove current item */
727 			read_only_pages = g_list_delete_link(read_only_pages, iter);
728 
729 			/* set next item and continue */
730 			iter = next;
731 			continue;
732 		}
733 
734 		iter = iter->next;
735 	}
736 	/* add to the list and make readonly those files
737 	from the current list that are new */
738 	iter = files;
739 	while (iter)
740 	{
741 		if (!g_list_find_custom(read_only_pages, iter->data, (GCompareFunc)g_strcmp0))
742 		{
743 			/* set document readonly */
744 			GeanyDocument *doc = document_find_by_real_path((const gchar*)iter->data);
745 			if (doc)
746 				scintilla_send_message(doc->editor->sci, SCI_SETREADONLY, 1, 0);
747 
748 			/* add new file to the list */
749 			read_only_pages = g_list_append(read_only_pages, g_strdup((gchar*)iter->data));
750 		}
751 		iter = iter->next;
752 	}
753 	g_list_free(files);
754 
755 	/* autos */
756 	autos = active_module->get_autos();
757 	update_variables(GTK_TREE_VIEW(atree), NULL, autos);
758 
759 	/* watches */
760 	watches = active_module->get_watches();
761 	update_variables(GTK_TREE_VIEW(wtree), NULL, watches);
762 
763 	if (stack)
764 	{
765 		frame *current = (frame*)stack->data;
766 
767 		if (current->have_source)
768 		{
769 			/* open current instruction position */
770 			editor_open_position(current->file, current->line);
771 		}
772 
773 		/* add current instruction marker */
774 		add_stack_markers();
775 	}
776 
777 	/* enable widgets */
778 	enable_sensitive_widgets(TRUE);
779 
780 	/* remove breaks readonly if current module doesn't support run-time breaks operation */
781 	if (!(active_module->features & MF_ASYNC_BREAKS))
782 		bptree_set_readonly(FALSE);
783 }
784 
785 /*
786  * called when debugger exits
787  */
on_debugger_exited(int code)788 static void on_debugger_exited (int code)
789 {
790 	GtkTextIter start, end;
791 	GtkTextBuffer *buffer;
792 	GList *iter;
793 
794 	/* remove marker for current instruction if was set */
795 	if (stack)
796 	{
797 		remove_stack_markers();
798 		g_list_foreach(stack, (GFunc)frame_unref, NULL);
799 		g_list_free(stack);
800 		stack = NULL;
801 	}
802 
803 	/* clear watch page */
804 	clear_watch_values(GTK_TREE_VIEW(wtree));
805 
806 	/* clear autos page */
807 	gtk_tree_store_clear(GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(atree))));
808 
809 	/* clear stack trace tree */
810 	stree_clear();
811 
812 	/* clear debug terminal */
813 	vte_terminal_reset(VTE_TERMINAL(terminal), TRUE, TRUE);
814 
815 	/* clear debug messages window */
816 	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(debugger_messages_textview));
817 	gtk_text_buffer_get_bounds(buffer, &start, &end);
818 	gtk_text_buffer_delete(buffer, &start, &end);
819 
820 	/* enable target page */
821 	tpage_set_readonly(FALSE);
822 
823 	/* remove breaks readonly if current module doesn't support run-time breaks operation */
824 	if (!(active_module->features & MF_ASYNC_BREAKS))
825 		bptree_set_readonly(FALSE);
826 
827 	/* set files that was readonly during debug writable */
828 	for (iter = read_only_pages; iter; iter = iter->next)
829 	{
830 		GeanyDocument *doc = document_find_by_real_path((const gchar*)iter->data);
831 		if (doc)
832 			scintilla_send_message(doc->editor->sci, SCI_SETREADONLY, 0, 0);
833 
834 		/* free file name */
835 		g_free(iter->data);
836 	}
837 	g_list_free(read_only_pages);
838 	read_only_pages = NULL;
839 
840 	/* clear and destroy calltips cache */
841 	if (calltips)
842 	{
843 		g_hash_table_destroy(calltips);
844 		calltips = NULL;
845 	}
846 
847 	/* enable widgets */
848 	enable_sensitive_widgets(TRUE);
849 
850 	/* update buttons panel state */
851 	btnpanel_set_debug_state(DBS_IDLE);
852 
853 	/* update debug state */
854 	debug_state = DBS_IDLE;
855 }
856 
857 /*
858  * called from debugger module to show a message in  debugger messages pane
859  */
on_debugger_message(const gchar * message,const gchar * color)860 static void on_debugger_message (const gchar* message, const gchar *color)
861 {
862 	gchar *msg = g_strdup_printf("%s\n", message);
863 
864 	GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(debugger_messages_textview));
865 
866 	GtkTextIter iter;
867 	gtk_text_buffer_get_end_iter(buffer, &iter);
868 	gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, msg, -1, color, NULL);
869 
870 	g_free(msg);
871 
872 	gtk_adjustment_set_value(vadj, gtk_adjustment_get_upper(vadj));
873 }
874 
875 /*
876  * called from debugger module to clear messages tab
877  */
on_debugger_messages_clear(void)878 static void on_debugger_messages_clear (void)
879 {
880 	/* clear debug messages window */
881 	GtkTextIter start, end;
882 	GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(debugger_messages_textview));
883 	gtk_text_buffer_get_bounds(buffer, &start, &end);
884 	gtk_text_buffer_delete(buffer, &start, &end);
885 }
886 
887 /*
888  * called from debugger module to show an error message box
889  */
on_debugger_error(const gchar * message)890 static void on_debugger_error (const gchar* message)
891 {
892 	dialogs_show_msgbox(GTK_MESSAGE_ERROR, "%s", message);
893 }
894 
895 /*
896  * called from debugger module when a thead has been removed
897  */
on_thread_removed(int thread_id)898 static void on_thread_removed(int thread_id)
899 {
900 	stree_remove_thread(thread_id);
901 }
902 
903 /*
904  * called from debugger module when a new thead has been added
905  */
on_thread_added(int thread_id)906 static void on_thread_added (int thread_id)
907 {
908 	stree_add_thread(thread_id);
909 }
910 
911 /* callbacks structure to pass to debugger module */
912 dbg_callbacks callbacks = {
913 	on_debugger_run,
914 	on_debugger_stopped,
915 	on_debugger_exited,
916 	on_debugger_message,
917 	on_debugger_messages_clear,
918 	on_debugger_error,
919 	on_thread_added,
920 	on_thread_removed,
921 };
922 
923 /*
924  * Interface functions
925  */
926 
927 /*
928  * called when a frame in the stack tree has been selected
929  */
on_select_frame(int frame_number)930 static void on_select_frame(int frame_number)
931 {
932 	GList *autos, *watches;
933 	frame *f = (frame*)g_list_nth_data(stack, active_module->get_active_frame());
934 	if (f)
935 	{
936 		markers_remove_current_instruction(f->file, f->line);
937 		markers_add_frame(f->file, f->line);
938 	}
939 
940 	active_module->set_active_frame(frame_number);
941 
942 	/* clear calltips cache */
943 	if (calltips)
944 		g_hash_table_remove_all(calltips);
945 
946 	/* autos */
947 	autos = active_module->get_autos();
948 	update_variables(GTK_TREE_VIEW(atree), NULL, autos);
949 
950 	/* watches */
951 	watches = active_module->get_watches();
952 	update_variables(GTK_TREE_VIEW(wtree), NULL, watches);
953 
954 	f = (frame*)g_list_nth_data(stack, frame_number);
955 	if (f)
956 	{
957 		markers_remove_frame(f->file, f->line);
958 		markers_add_current_instruction(f->file, f->line);
959 	}
960 }
961 
962 /*
963  * called when a thread should been selected
964  */
on_select_thread(int thread_id)965 static void on_select_thread(int thread_id)
966 {
967 	gboolean success;
968 
969 	if (stack)
970 		remove_stack_markers();
971 
972 	if ((success = active_module->set_active_thread(thread_id)))
973 	{
974 		g_list_free_full(stack, (GDestroyNotify)frame_unref);
975 		stack = active_module->get_stack();
976 
977 		/* update the stack tree */
978 		stree_remove_frames();
979 		stree_set_active_thread_id(thread_id);
980 		stree_add(stack);
981 		stree_select_first_frame(TRUE);
982 	}
983 
984 	if (stack)
985 		add_stack_markers();
986 
987 	if (success)
988 		on_select_frame(0);
989 }
990 
991 /*
992  * init debug related GUI (watch tree view)
993  * arguments:
994  */
debug_init(void)995 void debug_init(void)
996 {
997 	GtkWidget *scrollbar;
998 	GtkWidget *hbox;
999 	GKeyFile *config;
1000 	gchar *configfile;
1001 	gchar *font;
1002 	GtkTextBuffer *buffer;
1003 
1004 #if GTK_CHECK_VERSION(3, 0, 0)
1005 	VtePty *pty;
1006 #endif
1007 
1008 	/* create watch page */
1009 	wtree = wtree_init(on_watch_expanded_callback,
1010 		on_watch_dragged_callback,
1011 		on_watch_key_pressed_callback,
1012 		on_watch_changed,
1013 		on_watch_button_pressed_callback);
1014 	wmodel = gtk_tree_view_get_model(GTK_TREE_VIEW(wtree));
1015 	wstore = GTK_TREE_STORE(wmodel);
1016 
1017 	tab_watch = gtk_scrolled_window_new(NULL, NULL);
1018 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(tab_watch),
1019 		GTK_POLICY_AUTOMATIC,
1020 		GTK_POLICY_AUTOMATIC);
1021 	gtk_container_add(GTK_CONTAINER(tab_watch), wtree);
1022 
1023 	/* create autos page */
1024 	atree = atree_init(on_watch_expanded_callback, on_watch_button_pressed_callback);
1025 	tab_autos = gtk_scrolled_window_new(NULL, NULL);
1026 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(tab_autos),
1027 		GTK_POLICY_AUTOMATIC,
1028 		GTK_POLICY_AUTOMATIC);
1029 	gtk_container_add(GTK_CONTAINER(tab_autos), atree);
1030 
1031 	/* create stack trace page */
1032 	stree = stree_init(editor_open_position, on_select_thread, on_select_frame);
1033 	tab_call_stack = gtk_scrolled_window_new(NULL, NULL);
1034 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(tab_call_stack),
1035 		GTK_POLICY_AUTOMATIC,
1036 		GTK_POLICY_AUTOMATIC);
1037 	gtk_container_add(GTK_CONTAINER(tab_call_stack), stree);
1038 
1039 	/* create debug terminal page */
1040 	terminal = vte_terminal_new();
1041 	/* create PTY */
1042 	openpty(&pty_master, &pty_slave, NULL,
1043 		    NULL,
1044 		    NULL);
1045 	grantpt(pty_master);
1046 	unlockpt(pty_master);
1047 #if GTK_CHECK_VERSION(3, 0, 0)
1048 	pty = vte_pty_new_foreign_sync(pty_master, NULL, NULL);
1049 	vte_terminal_set_pty(VTE_TERMINAL(terminal), pty);
1050 	g_object_unref(pty);
1051 	scrollbar = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(terminal)));
1052 #else
1053 	vte_terminal_set_pty(VTE_TERMINAL(terminal), pty_master);
1054 	scrollbar = gtk_vscrollbar_new(GTK_ADJUSTMENT(VTE_TERMINAL(terminal)->adjustment));
1055 #endif
1056 	gtk_widget_set_can_focus(GTK_WIDGET(scrollbar), FALSE);
1057 	tab_terminal = gtk_frame_new(NULL);
1058 	gtk_frame_set_shadow_type (GTK_FRAME(tab_terminal), GTK_SHADOW_NONE);
1059 #if GTK_CHECK_VERSION(3, 0, 0)
1060 	hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
1061 #else
1062 	hbox = gtk_hbox_new(FALSE, 0);
1063 #endif
1064 	gtk_container_add(GTK_CONTAINER(tab_terminal), hbox);
1065 	gtk_box_pack_start(GTK_BOX(hbox), terminal, TRUE, TRUE, 0);
1066 	gtk_box_pack_start(GTK_BOX(hbox), scrollbar, FALSE, FALSE, 0);
1067 	/* set the default widget size first to prevent VTE expanding too much,
1068 	 * sometimes causing the hscrollbar to be too big or out of view. */
1069 	gtk_widget_set_size_request(GTK_WIDGET(terminal), 10, 10);
1070 	vte_terminal_set_size(VTE_TERMINAL(terminal), 30, 1);
1071 	/* set terminal font. */
1072 	config = g_key_file_new();
1073 	configfile = g_strconcat(geany_data->app->configdir, G_DIR_SEPARATOR_S, "geany.conf", NULL);
1074 	g_key_file_load_from_file(config, configfile, G_KEY_FILE_NONE, NULL);
1075 	font = utils_get_setting_string(config, "VTE", "font", "Monospace 10");
1076 	vte_terminal_set_font_from_string (VTE_TERMINAL(terminal), font);
1077 
1078 	/* debug messages page */
1079 	tab_messages = gtk_scrolled_window_new(NULL, NULL);
1080 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(tab_messages),
1081 		GTK_POLICY_AUTOMATIC,
1082 		GTK_POLICY_AUTOMATIC);
1083 	hadj = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(tab_messages));
1084 	vadj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(tab_messages));
1085 
1086 	debugger_messages_textview =  gtk_text_view_new();
1087 	gtk_text_view_set_editable (GTK_TEXT_VIEW (debugger_messages_textview), FALSE);
1088 #if GTK_CHECK_VERSION(3, 0, 0)
1089 	gtk_container_add(GTK_CONTAINER(tab_messages), debugger_messages_textview);
1090 #else
1091 	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(tab_messages), debugger_messages_textview);
1092 #endif
1093 
1094 	/* create tex tags */
1095 	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(debugger_messages_textview));
1096 	gtk_text_buffer_create_tag(buffer, "black", "foreground", "#000000", NULL);
1097 	gtk_text_buffer_create_tag(buffer, "grey", "foreground", "#AAAAAA", NULL);
1098 	gtk_text_buffer_create_tag(buffer, "red", "foreground", "#FF0000", NULL);
1099 	gtk_text_buffer_create_tag(buffer, "green", "foreground", "#00FF00", NULL);
1100 	gtk_text_buffer_create_tag(buffer, "blue", "foreground", "#0000FF", NULL);
1101 	gtk_text_buffer_create_tag(buffer, "yellow", "foreground", "#FFFF00", NULL);
1102 	gtk_text_buffer_create_tag(buffer, "brown", "foreground", "#BB8915", NULL);
1103 	gtk_text_buffer_create_tag(buffer, "rose", "foreground", "#BA92B7", NULL);
1104 }
1105 
1106 /*
1107  * called when plugin is being unloaded to remove current instruction marker
1108  */
debug_destroy(void)1109 void debug_destroy(void)
1110 {
1111 	/* close PTY file descriptors */
1112 	close(pty_master);
1113 	close(pty_slave);
1114 
1115 	/* remove stack markers if present */
1116 	if (stack)
1117 	{
1118 		remove_stack_markers();
1119 		g_list_foreach(stack, (GFunc)frame_unref, NULL);
1120 		g_list_free(stack);
1121 		stack = NULL;
1122 	}
1123 
1124 	stree_destroy();
1125 }
1126 
1127 /*
1128  * gets current debug state
1129  */
debug_get_state(void)1130 enum dbs debug_get_state(void)
1131 {
1132 	return debug_state;
1133 }
1134 
1135 /*
1136  * gets current stack frames lisy
1137  */
debug_get_stack(void)1138 GList* debug_get_stack(void)
1139 {
1140 	return stack;
1141 }
1142 
1143 /*
1144  * gets debug module index from name
1145  * arguments:
1146  * 		modulename - debug module name
1147  */
debug_get_module_index(const gchar * modulename)1148 int debug_get_module_index(const gchar *modulename)
1149 {
1150 	int _index = 0;
1151 	while (modules[_index].title)
1152 	{
1153 		if (!strcmp(modules[_index].title, modulename))
1154 			return _index;
1155 		_index++;
1156 	}
1157 
1158 	return -1;
1159 }
1160 
1161 /*
1162  * gets GList with all debug modules pointers
1163  */
debug_get_modules(void)1164 GList* debug_get_modules(void)
1165 {
1166 	GList *mods = NULL;
1167 	module_description *desc = modules;
1168 	while (desc->title)
1169 	{
1170 		mods = g_list_prepend(mods, (gpointer)desc->title);
1171 		desc++;
1172 	}
1173 
1174 	return g_list_reverse(mods);
1175 }
1176 
1177 /*
1178  * checks whether currently active debug module supports asyncronous breaks
1179  */
debug_supports_async_breaks(void)1180 gboolean debug_supports_async_breaks(void)
1181 {
1182 	return active_module->features & MF_ASYNC_BREAKS;
1183 }
1184 
1185 /*
1186  * starts or continues debug process
1187  */
debug_run(void)1188 void debug_run(void)
1189 {
1190 	if (DBS_IDLE == debug_state)
1191 	{
1192 		gchar *target, *commandline;
1193 		GList *env, *watches, *breaks;
1194 
1195 		target = g_strstrip(tpage_get_target());
1196 		if (!strlen(target))
1197 		{
1198 			g_free(target);
1199 			return;
1200 		}
1201 		commandline = tpage_get_commandline();
1202 		env = tpage_get_environment();
1203 		watches = get_root_items(GTK_TREE_VIEW(wtree));
1204 		breaks = breaks_get_all();
1205 
1206 		/* init selected debugger  module */
1207 		active_module = modules[tpage_get_debug_module_index()].module;
1208 		if(active_module->run(target, commandline, env, watches, breaks, ttyname(pty_slave), &callbacks))
1209 		{
1210 			/* set target page - readonly */
1211 			tpage_set_readonly(TRUE);
1212 
1213 			/* update debuf state */
1214 			debug_state = DBS_RUN_REQUESTED;
1215 		}
1216 
1217 		/* free stuff */
1218 		g_free(target);
1219 		g_free(commandline);
1220 
1221 		g_list_foreach(env, (GFunc)g_free, NULL);
1222 		g_list_free(env);
1223 
1224 		g_list_foreach(watches, (GFunc)g_free, NULL);
1225 		g_list_free(watches);
1226 
1227 		g_list_free(breaks);
1228 	}
1229 	else if (DBS_STOPPED == debug_state)
1230 	{
1231 		/* resume */
1232 		active_module->resume();
1233 		debug_state = DBS_RUN_REQUESTED;
1234 	}
1235 
1236 	/* set breaks readonly if current module doesn't support run-time breaks operation */
1237 	if (!(active_module->features & MF_ASYNC_BREAKS))
1238 		bptree_set_readonly(TRUE);
1239 }
1240 
1241 /*
1242  * restarts debug process
1243  */
debug_restart(void)1244 void debug_restart(void)
1245 {
1246 	if (DBS_STOPPED == debug_state)
1247 	{
1248 		/* stop instantly if not running */
1249 		vte_terminal_reset(VTE_TERMINAL(terminal), TRUE, TRUE);
1250 		active_module->restart();
1251 		debug_state = DBS_RUN_REQUESTED;
1252 	}
1253 }
1254 
1255 /*
1256  * stops debug process
1257  */
debug_stop(void)1258 void debug_stop(void)
1259 {
1260 	if (DBS_STOPPED == debug_state)
1261 	{
1262 		/* stop instantly if not running */
1263 		active_module->stop();
1264 		debug_state = DBS_STOP_REQUESTED;
1265 	}
1266 	else if (DBS_IDLE != debug_state)
1267 	{
1268 		/* if running - request interrupt */
1269 		exit_pending = TRUE;
1270 		active_module->request_interrupt();
1271 	}
1272 }
1273 
1274 /*
1275  * step over
1276  */
debug_step_over(void)1277 void debug_step_over(void)
1278 {
1279 	if (DBS_STOPPED == debug_state)
1280 		active_module->step_over();
1281 }
1282 
1283 /*
1284  * step into
1285  */
debug_step_into(void)1286 void debug_step_into(void)
1287 {
1288 	if (DBS_STOPPED == debug_state)
1289 		active_module->step_into();
1290 }
1291 
1292 /*
1293  * step out
1294  */
debug_step_out(void)1295 void debug_step_out(void)
1296 {
1297 	if (DBS_STOPPED == debug_state)
1298 		active_module->step_out();
1299 }
1300 
1301 /*
1302  * step to position
1303  */
debug_execute_until(const gchar * file,int line)1304 void debug_execute_until(const gchar *file, int line)
1305 {
1306 	if (DBS_STOPPED == debug_state)
1307 		active_module->execute_until(file, line);
1308 }
1309 
1310 /*
1311  * sets a break
1312  * arguments:
1313  *		bp - breakpoitn to set
1314  * 		bsa - what to do with breakpoint (add/remove/change)
1315  */
debug_set_break(breakpoint * bp,break_set_activity bsa)1316 gboolean debug_set_break(breakpoint* bp, break_set_activity bsa)
1317 {
1318 	if (DBS_STOPPED == debug_state)
1319 	{
1320 		return active_module->set_break(bp, bsa);
1321 	}
1322 	return FALSE;
1323 }
1324 
1325 /*
1326  * removes a break
1327  * arguments:
1328  *		bp - breakpoitn to set
1329  */
debug_remove_break(breakpoint * bp)1330 gboolean debug_remove_break(breakpoint* bp)
1331 {
1332 	if (DBS_STOPPED == debug_state)
1333 	{
1334 		return active_module->remove_break(bp);
1335 	}
1336 	return FALSE;
1337 }
1338 
1339 /*
1340  * requests active debug module to interrupt fo further
1341  * breakpoint modifications
1342  * arguments:
1343  *		cb - callback to call on interruption happents
1344  * 		bp - breakpoint to deal with
1345  * 		flags - whar to do with breakpoint
1346  */
debug_request_interrupt(bs_callback cb,gpointer data)1347 void debug_request_interrupt(bs_callback cb, gpointer data)
1348 {
1349 	interrupt_cb = cb;
1350 	interrupt_data = data;
1351 
1352 	active_module->request_interrupt();
1353 }
1354 
1355 /*
1356  * gets debug modules error message
1357  */
debug_error_message(void)1358 gchar* debug_error_message(void)
1359 {
1360 	return 	active_module->error_message();
1361 }
1362 
1363 /*
1364  * evaluates expression in runtime and returns its value or NULL if unevaluatable
1365  */
debug_evaluate_expression(gchar * expression)1366 gchar* debug_evaluate_expression(gchar *expression)
1367 {
1368 	return active_module->evaluate_expression(expression);
1369 }
1370 
1371 /*
1372  * return list of strings for the calltip
1373  * first line is a header, others should be shifted right with tab
1374  */
debug_get_calltip_for_expression(gchar * expression)1375 gchar* debug_get_calltip_for_expression(gchar* expression)
1376 {
1377 	gchar *calltip = NULL;
1378 	if (!calltips || !(calltip = g_hash_table_lookup(calltips, expression)))
1379 	{
1380 		GString *calltip_str = NULL;
1381 		variable *var = active_module->add_watch(expression);
1382 		if (var)
1383 		{
1384 			calltip_str = get_calltip_line(var, TRUE);
1385 			if (calltip_str)
1386 			{
1387 				if (var->has_children)
1388 				{
1389 					int lines_left = MAX_CALLTIP_HEIGHT - 1;
1390 					GList* children = active_module->get_children(var->internal->str);
1391 					GList* child = children;
1392 					while(child && lines_left)
1393 					{
1394 						variable *varchild = (variable*)child->data;
1395 						GString *child_string = get_calltip_line(varchild, FALSE);
1396 						g_string_append_printf(calltip_str, "\n%s", child_string->str);
1397 						g_string_free(child_string, TRUE);
1398 
1399 						child = child->next;
1400 						lines_left--;
1401 					}
1402 					if (!lines_left && child)
1403 					{
1404 						g_string_append(calltip_str, "\n\t\t........");
1405 					}
1406 					g_list_foreach(children, (GFunc)variable_free, NULL);
1407 					g_list_free(children);
1408 				}
1409 				calltip = g_string_free(calltip_str, FALSE);
1410 			}
1411 
1412 			active_module->remove_watch(var->internal->str);
1413 
1414 			if (!calltips)
1415 			{
1416 				calltips = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)g_free, (GDestroyNotify)g_free);
1417 			}
1418 			g_hash_table_insert(calltips, g_strdup(expression), calltip);
1419 		}
1420 	}
1421 
1422 	return calltip;
1423 }
1424 
1425 /*
1426  * check whether source for the current instruction
1427  * is avaiable
1428  */
debug_current_instruction_have_sources(void)1429 gboolean debug_current_instruction_have_sources(void)
1430 {
1431 	frame *current = (frame*)stack->data;
1432 	return current->have_source ? strlen(current->file) : 0;
1433 }
1434 
1435 /*
1436  * opens position according to the current instruction
1437  */
debug_jump_to_current_instruction(void)1438 void debug_jump_to_current_instruction(void)
1439 {
1440 	frame *current = (frame*)stack->data;
1441 	editor_open_position(current->file, current->line);
1442 }
1443 
1444 /*
1445  * called from the document open callback to set file
1446  * readonly if debug is active and file is a debugging source file
1447  */
debug_on_file_open(GeanyDocument * doc)1448 void debug_on_file_open(GeanyDocument *doc)
1449 {
1450 	const gchar *file = DOC_FILENAME(doc);
1451 	if (g_list_find_custom(read_only_pages, (gpointer)file, (GCompareFunc)g_strcmp0))
1452 		scintilla_send_message(doc->editor->sci, SCI_SETREADONLY, 1, 0);
1453 }
1454 
1455 /*
1456  * get active frame index
1457  */
debug_get_active_frame(void)1458 int debug_get_active_frame(void)
1459 {
1460 	return active_module->get_active_frame();
1461 }
1462