Updated Spanish translation
[anjuta-git-plugin.git] / plugins / debug-manager / start.c
blob1ce8acc9bd5d38a9ca3aa59ba9082459a283ce2f
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 start.c
4 Copyright (C) 2000 Kh. Naba Kumar Singh
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.
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 * Handle start of debugger. It can be done in three ways:
23 * - Load a target of the current project_root_uri
24 * - Load a executable file
25 * - Attach to an already running program
26 *---------------------------------------------------------------------------*/
28 #ifdef HAVE_CONFIG_H
29 # include <config.h>
30 #endif
32 #include "start.h"
34 #include <libanjuta/resources.h>
35 #include <libanjuta/interfaces/ianjuta-project-manager.h>
37 #include <libgnomevfs/gnome-vfs-mime-utils.h>
38 #include <libgnomevfs/gnome-vfs-utils.h>
40 #include <gnome.h>
42 #include <glade/glade-xml.h>
44 #include <errno.h>
45 #include <sys/stat.h>
46 #include <ctype.h>
47 #include <sys/wait.h>
48 #include <unistd.h>
49 #include <string.h>
51 /* Types
52 *---------------------------------------------------------------------------*/
54 typedef struct _AttachProcess AttachProcess;
55 typedef struct _LoadFileCallBack LoadFileCallBack;
57 enum
59 CLEAR_INITIAL,
60 CLEAR_UPDATE,
61 CLEAR_REVIEW,
62 CLEAR_FINAL
65 struct _AttachProcess
67 GtkWidget* dialog;
68 GtkWidget* treeview;
69 gint pid;
71 gboolean hide_paths;
72 gboolean hide_params;
73 gboolean process_tree;
75 gchar* ps_output;
76 GSList* iter_stack;
77 gint iter_stack_level;
78 gint num_spaces_to_skip;
79 gint num_spaces_per_level;
82 enum {
83 PID_COLUMN,
84 USER_COLUMN,
85 START_COLUMN,
86 COMMAND_COLUMN,
87 COLUMNS_NB
90 static char *column_names[COLUMNS_NB] = {
91 N_("Pid"), N_("User"), N_("Time"), N_("Command")
94 struct _LoadFileCallBack
96 AnjutaPlugin *plugin;
97 IAnjutaDebugger *debugger;
100 struct _DmaStart
102 AnjutaPlugin *plugin;
104 IAnjutaDebugger *debugger;
106 gchar* target_uri;
107 gchar* program_args;
108 gboolean run_in_terminal;
111 /* Widgets found in glade file
112 *---------------------------------------------------------------------------*/
114 #define PARAMETER_DIALOG "parameter_dialog"
115 #define TERMINAL_CHECK_BUTTON "parameter_run_in_term_check"
116 #define PARAMETER_COMBO "parameter_combo"
117 #define TARGET_COMBO "target_combo"
118 #define TARGET_SELECT_SIGNAL "on_select_target_clicked"
120 #define ANJUTA_RESPONSE_SELECT_TARGET 0
122 static void attach_process_clear (AttachProcess * ap, gint ClearRequest);
124 /* Helper functions
125 *---------------------------------------------------------------------------*/
127 /* This functions get all directories of the current project containing
128 * static or shared library. Perhaps a more reliable way to find these
129 * directories is to really get the directories of all source files */
131 static GList*
132 get_source_directories (AnjutaPlugin *plugin)
134 gchar *cwd;
135 GList *node, *search_dirs = NULL;
136 GList *slibs_dirs = NULL;
137 GList *libs_dirs = NULL;
138 GValue value = {0,};
140 return NULL;
141 cwd = g_get_current_dir();
142 search_dirs = g_list_prepend (search_dirs, g_strconcat ("file://", cwd, NULL));
143 g_free (cwd);
145 /* Check if a project is already open */
146 anjuta_shell_get_value (plugin->shell, "project_root_uri", &value, NULL);
148 /* Set source file search directories */
149 if (g_value_get_string (&value) != NULL)
151 IAnjutaProjectManager *pm;
152 pm = anjuta_shell_get_interface (plugin->shell,
153 IAnjutaProjectManager, NULL);
154 if (pm)
156 slibs_dirs =
157 ianjuta_project_manager_get_targets (pm,
158 IANJUTA_PROJECT_MANAGER_TARGET_SHAREDLIB,
159 NULL);
160 libs_dirs =
161 ianjuta_project_manager_get_targets (pm,
162 IANJUTA_PROJECT_MANAGER_TARGET_STATICLIB,
163 NULL);
166 slibs_dirs = g_list_reverse (slibs_dirs);
167 libs_dirs = g_list_reverse (libs_dirs);
169 node = slibs_dirs;
170 while (node)
172 gchar *dir_uri;
173 dir_uri = g_path_get_dirname (node->data);
174 search_dirs = g_list_prepend (search_dirs, dir_uri);
175 node = g_list_next (node);
178 node = libs_dirs;
179 while (node)
181 gchar *dir_uri;
182 dir_uri = g_path_get_dirname (node->data);
183 search_dirs = g_list_prepend (search_dirs, dir_uri);
184 node = g_list_next (node);
187 g_list_foreach (slibs_dirs, (GFunc)g_free, NULL);
188 g_list_free (slibs_dirs);
189 g_list_foreach (libs_dirs, (GFunc)g_free, NULL);
190 g_list_free (libs_dirs);
192 return g_list_reverse (search_dirs);
195 static void
196 free_source_directories (GList *dirs)
198 g_list_foreach (dirs, (GFunc)g_free, NULL);
199 g_list_free (dirs);
202 /* Callback for saving session
203 *---------------------------------------------------------------------------*/
205 static void
206 on_session_save (AnjutaShell *shell, AnjutaSessionPhase phase, AnjutaSession *session, DmaStart *this)
208 if (phase != ANJUTA_SESSION_PHASE_NORMAL)
209 return;
211 if (this->program_args)
213 gchar *arg;
214 anjuta_session_set_string (session, "Execution", "Program arguments", this->program_args);
215 arg = anjuta_session_get_string (session, "Execution", "Program arguments");
217 if (this->target_uri)
219 gchar *uri;
220 anjuta_session_set_string (session, "Execution", "Program uri", this->target_uri);
221 uri = anjuta_session_get_string (session, "Execution", "Program uri");
223 anjuta_session_set_int (session, "Execution", "Run in terminal", this->run_in_terminal + 1);
226 static void on_session_load (AnjutaShell *shell, AnjutaSessionPhase phase, AnjutaSession *session, DmaStart *this)
228 gchar *program_args;
229 gchar *target_uri;
230 gint run_in_terminal;
232 if (phase != ANJUTA_SESSION_PHASE_NORMAL)
233 return;
235 program_args = anjuta_session_get_string (session, "Execution", "Program arguments");
236 if (this->program_args)
238 g_free (this->program_args);
239 this->program_args = NULL;
241 if (program_args)
243 this->program_args = program_args;
246 target_uri = anjuta_session_get_string (session, "Execution", "Program uri");
247 if (this->target_uri)
249 g_free (this->target_uri);
250 this->target_uri = NULL;
252 if (target_uri)
254 this->target_uri = target_uri;
257 /* The flag is store as 1 == FALSE, 2 == TRUE */
258 run_in_terminal = anjuta_session_get_int (session, "Execution", "Run in terminal");
260 if (run_in_terminal == 0)
261 this->run_in_terminal = TRUE; /* Default value */
262 else
263 this->run_in_terminal = run_in_terminal - 1;
266 /* Attach to process private functions
267 *---------------------------------------------------------------------------*/
269 static AttachProcess *
270 attach_process_new ()
272 AttachProcess *ap;
273 ap = g_new0 (AttachProcess, 1);
274 attach_process_clear (ap, CLEAR_INITIAL);
275 return ap;
278 static void
279 attach_process_clear (AttachProcess * ap, gint ClearRequest)
281 GtkTreeModel *model;
283 // latest ps output
284 switch (ClearRequest)
286 case CLEAR_UPDATE:
287 case CLEAR_FINAL:
288 if (ap->ps_output)
290 g_free (ap->ps_output);
292 case CLEAR_INITIAL:
293 ap->ps_output = NULL;
296 // helper variables
297 switch (ClearRequest)
299 case CLEAR_INITIAL:
300 case CLEAR_UPDATE:
301 case CLEAR_REVIEW:
302 ap->pid = -1L;
303 ap->iter_stack = NULL;
304 ap->iter_stack_level = -1;
305 ap->num_spaces_to_skip = -1;
308 // tree model
309 switch (ClearRequest)
311 case CLEAR_UPDATE:
312 case CLEAR_REVIEW:
313 case CLEAR_FINAL:
314 model = gtk_tree_view_get_model (GTK_TREE_VIEW (ap->treeview));
315 gtk_tree_store_clear (GTK_TREE_STORE (model));
318 // dialog widget
319 if (ClearRequest == CLEAR_FINAL)
321 gtk_widget_destroy (ap->dialog);
322 ap->dialog = NULL;
326 static inline gchar *
327 skip_spaces (gchar *pos)
329 while (*pos == ' ')
330 pos++;
331 return pos;
334 static inline gchar *
335 skip_token (gchar *pos)
337 while (*pos != ' ')
338 pos++;
339 *pos++ = '\0';
340 return pos;
343 static gchar *
344 skip_token_and_spaces (gchar *pos)
346 pos = skip_token (pos);
347 return skip_spaces (pos);
350 static GtkTreeIter *
351 iter_stack_push_new (AttachProcess *ap, GtkTreeStore *store)
353 GtkTreeIter *new_iter, *top_iter;
354 new_iter = g_new (GtkTreeIter, 1);
355 top_iter = (GtkTreeIter *) (g_slist_nth_data (ap->iter_stack, 0));
356 ap->iter_stack =
357 g_slist_prepend (ap->iter_stack, (gpointer) (new_iter));
358 gtk_tree_store_append (store, new_iter, top_iter);
359 ap->iter_stack_level++;
360 return new_iter;
363 static gboolean
364 iter_stack_pop (AttachProcess *ap)
366 if (ap->iter_stack_level < 0)
367 return FALSE;
369 GtkTreeIter *iter =
370 (GtkTreeIter *) (g_slist_nth_data (ap->iter_stack, 0));
371 ap->iter_stack =
372 g_slist_delete_link (ap->iter_stack, ap->iter_stack);
373 g_free (iter);
374 ap->iter_stack_level--;
375 return TRUE;
378 static void
379 iter_stack_clear (AttachProcess *ap)
381 while (iter_stack_pop (ap));
384 static gchar *
385 calc_depth_and_get_iter (AttachProcess *ap, GtkTreeStore *store,
386 GtkTreeIter **iter, gchar *pos)
388 gchar *orig_pos;
389 guint num_spaces, depth, i;
391 // count spaces
392 orig_pos = pos;
393 while (*pos == ' ')
394 pos++;
395 num_spaces = pos - orig_pos;
397 if (ap->process_tree)
399 if (ap->num_spaces_to_skip < 0)
401 // first process to be inserted
402 ap->num_spaces_to_skip = num_spaces;
403 ap->num_spaces_per_level = -1;
404 *iter = iter_stack_push_new (ap, store);
406 else
408 if (ap->num_spaces_per_level < 0)
410 if (num_spaces == ap->num_spaces_to_skip)
412 // num_spaces_per_level still unknown
413 iter_stack_pop (ap);
414 *iter = iter_stack_push_new (ap, store);
416 else
418 // first time at level 1
419 ap->num_spaces_per_level =
420 num_spaces - ap->num_spaces_to_skip;
421 *iter = iter_stack_push_new (ap, store);
424 else
426 depth = (num_spaces - ap->num_spaces_to_skip) /
427 ap->num_spaces_per_level;
428 if (depth == ap->iter_stack_level)
430 // level not changed
431 iter_stack_pop (ap);
432 *iter = iter_stack_push_new (ap, store);
434 else
435 if (depth == ap->iter_stack_level + 1)
436 *iter = iter_stack_push_new (ap, store);
437 else
438 if (depth < ap->iter_stack_level)
440 // jump some levels backward
441 depth = ap->iter_stack_level - depth;
442 for (i = 0; i <= depth; i++)
443 iter_stack_pop (ap);
444 *iter = iter_stack_push_new (ap, store);
446 else
448 // should never get here
449 g_warning("Unknown error");
450 iter_stack_pop (ap);
451 *iter = iter_stack_push_new (ap, store);
456 else
458 iter_stack_pop (ap);
459 *iter = iter_stack_push_new (ap, store);
462 return pos;
465 static gchar *
466 skip_path (gchar *pos)
468 /* can't use g_path_get_basename() - wouldn't work for a processes
469 started with parameters containing '/' */
470 gchar c, *final_pos = pos;
472 if (*pos == G_DIR_SEPARATOR)
475 c = *pos;
476 if (c == G_DIR_SEPARATOR)
478 final_pos = ++pos;
479 continue;
481 else
482 if (c == ' ' || c == '\0')
483 break;
484 else
485 ++pos;
487 while (1);
489 return final_pos;
492 static inline void
493 remove_params (gchar *pos)
497 if (*(++pos) == ' ')
498 *pos = '\0';
500 while (*pos);
503 static void
504 attach_process_add_line (AttachProcess *ap, GtkTreeStore *store, gchar *line)
506 gchar *pid, *user, *start, *command, *tmp;
507 // guint i, level;
508 GtkTreeIter *iter;
510 pid = skip_spaces (line); // skip leading spaces
511 user = skip_token_and_spaces (pid); // skip PID
512 start = skip_token_and_spaces (user); // skip USER
513 tmp = skip_token (start); // skip START (do not skip spaces)
515 command = calc_depth_and_get_iter (ap, store, &iter, tmp);
517 if (ap->hide_paths)
519 command = skip_path (command);
522 if (ap->hide_params)
524 remove_params(command);
527 gtk_tree_store_set (store, iter,
528 PID_COLUMN, pid,
529 USER_COLUMN, user,
530 START_COLUMN, start,
531 COMMAND_COLUMN, command,
532 -1);
535 static void
536 attach_process_review (AttachProcess *ap)
538 gchar *ps_output, *begin, *end;
539 guint line_num = 0;
540 GtkTreeStore *store;
542 g_return_if_fail (ap);
543 g_return_if_fail (ap->ps_output);
544 store = GTK_TREE_STORE (gtk_tree_view_get_model
545 (GTK_TREE_VIEW (ap->treeview)));
546 g_return_if_fail (store);
548 ps_output = g_strdup (ap->ps_output);
549 end = ps_output;
550 while (*end)
552 begin = end;
553 while (*end && *end != '\n') end++;
554 if (++line_num > 2) // skip description line & process 'init'
556 *end = '\0';
557 attach_process_add_line (ap, store, begin);
559 end++;
561 g_free (ps_output);
563 iter_stack_clear (ap);
564 gtk_tree_view_expand_all (GTK_TREE_VIEW (ap->treeview));
567 static void
568 attach_process_update (AttachProcess * ap)
570 gchar *tmp, *tmp1, *cmd;
571 gint ch_pid;
572 gchar *shell;
573 GtkTreeStore *store;
574 gboolean result;
576 g_return_if_fail (ap);
577 store = GTK_TREE_STORE (gtk_tree_view_get_model
578 (GTK_TREE_VIEW (ap->treeview)));
579 g_return_if_fail (store);
581 if (anjuta_util_prog_is_installed ("ps", TRUE) == FALSE)
582 return;
584 tmp = anjuta_util_get_a_tmp_file ();
585 cmd = g_strconcat ("ps axw -H -o pid,user,start_time,args > ", tmp, NULL);
586 shell = gnome_util_user_shell ();
587 ch_pid = fork ();
588 if (ch_pid == 0)
590 execlp (shell, shell, "-c", cmd, NULL);
592 if (ch_pid < 0)
594 anjuta_util_dialog_error_system (NULL, errno,
595 _("Unable to execute: %s."), cmd);
596 g_free (tmp);
597 g_free (cmd);
598 return;
600 waitpid (ch_pid, NULL, 0);
601 g_free (cmd);
603 result = g_file_get_contents (tmp, &tmp1, NULL, NULL);
604 remove (tmp);
605 g_free (tmp);
606 if (! result)
608 anjuta_util_dialog_error_system (NULL, errno,
609 _("Unable to open the file: %s\n"),
610 tmp);
611 return;
614 attach_process_clear (ap, CLEAR_UPDATE);
615 ap->ps_output = anjuta_util_convert_to_utf8 (tmp1);
616 g_free (tmp1);
617 if (ap->ps_output)
619 attach_process_review (ap);
623 static void
624 on_selection_changed (GtkTreeSelection *selection, AttachProcess *ap)
626 GtkTreeModel *model;
627 GtkTreeIter iter;
629 g_return_if_fail (ap);
630 if (gtk_tree_selection_get_selected (selection, &model, &iter))
632 gchar* text;
633 gtk_tree_model_get (model, &iter, PID_COLUMN, &text, -1);
634 ap->pid = atoi (text);
635 gtk_dialog_set_response_sensitive (GTK_DIALOG (ap->dialog),
636 GTK_RESPONSE_OK, TRUE);
638 else
640 gtk_dialog_set_response_sensitive (GTK_DIALOG (ap->dialog),
641 GTK_RESPONSE_OK, FALSE);
642 ap->pid = -1L;
646 static gboolean
647 on_delete_event (GtkWidget *dialog, GdkEvent *event, AttachProcess *ap)
649 g_return_val_if_fail (ap, FALSE);
650 attach_process_clear (ap, CLEAR_FINAL);
651 return FALSE;
654 static gint
655 sort_pid (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b,
656 gpointer user_data)
658 gchar *nptr;
659 gint pid1, pid2;
661 gtk_tree_model_get (model, a, PID_COLUMN, &nptr, -1);
662 pid1 = atoi (nptr);
664 gtk_tree_model_get (model, b, PID_COLUMN, &nptr, -1);
665 pid2 = atoi (nptr);
667 return pid1 - pid2;
670 static void
671 on_toggle_hide_paths (GtkToggleButton *togglebutton, AttachProcess * ap)
673 ap->hide_paths = gtk_toggle_button_get_active (togglebutton);
674 attach_process_clear (ap, CLEAR_REVIEW);
675 attach_process_review (ap);
678 static void
679 on_toggle_hide_params (GtkToggleButton *togglebutton, AttachProcess * ap)
681 ap->hide_params = gtk_toggle_button_get_active (togglebutton);
682 attach_process_clear (ap, CLEAR_REVIEW);
683 attach_process_review (ap);
686 static void
687 on_toggle_process_tree (GtkToggleButton *togglebutton, AttachProcess * ap)
689 ap->process_tree = gtk_toggle_button_get_active (togglebutton);
690 attach_process_clear (ap, CLEAR_REVIEW);
691 attach_process_review (ap);
694 static pid_t
695 attach_process_show (AttachProcess * ap, GtkWindow *parent)
697 GladeXML *gxml;
698 GtkTreeView *view;
699 GtkTreeStore *store;
700 GtkCellRenderer *renderer;
701 GtkTreeSelection *selection;
702 GtkCheckButton *checkb_hide_paths;
703 GtkCheckButton *checkb_hide_params;
704 GtkCheckButton *checkb_process_tree;
705 gint i, res;
706 pid_t selected_pid = -1;
708 g_return_val_if_fail (ap != NULL, -1);
710 if (!ap->dialog)
712 gxml = glade_xml_new (GLADE_FILE, "attach_process_dialog", NULL);
713 ap->dialog = glade_xml_get_widget (gxml, "attach_process_dialog");
714 ap->treeview = glade_xml_get_widget (gxml, "attach_process_tv");
715 checkb_hide_paths = GTK_CHECK_BUTTON (
716 glade_xml_get_widget (gxml, "checkb_hide_paths"));
717 checkb_hide_params = GTK_CHECK_BUTTON (
718 glade_xml_get_widget (gxml, "checkb_hide_params"));
719 checkb_process_tree = GTK_CHECK_BUTTON (
720 glade_xml_get_widget (gxml, "checkb_process_tree"));
721 g_object_unref (gxml);
723 view = GTK_TREE_VIEW (ap->treeview);
724 store = gtk_tree_store_new (COLUMNS_NB,
725 G_TYPE_STRING,
726 G_TYPE_STRING,
727 G_TYPE_STRING,
728 G_TYPE_STRING);
729 gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));
730 gtk_tree_selection_set_mode (gtk_tree_view_get_selection (view),
731 GTK_SELECTION_SINGLE);
732 g_object_unref (G_OBJECT (store));
734 renderer = gtk_cell_renderer_text_new ();
736 for (i = PID_COLUMN; i < COLUMNS_NB; i++) {
737 GtkTreeViewColumn *column;
739 column = gtk_tree_view_column_new_with_attributes (column_names[i],
740 renderer, "text", i, NULL);
741 gtk_tree_view_column_set_sort_column_id(column, i);
742 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
743 gtk_tree_view_append_column (view, column);
744 if (i == COMMAND_COLUMN)
745 gtk_tree_view_set_expander_column(view, column);
747 gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store), PID_COLUMN,
748 sort_pid, NULL, NULL);
749 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
750 START_COLUMN, GTK_SORT_DESCENDING);
752 ap->hide_paths = gtk_toggle_button_get_active (
753 GTK_TOGGLE_BUTTON (checkb_hide_paths));
754 ap->hide_params = gtk_toggle_button_get_active (
755 GTK_TOGGLE_BUTTON (checkb_hide_params));
756 ap->process_tree = gtk_toggle_button_get_active (
757 GTK_TOGGLE_BUTTON (checkb_process_tree));
759 attach_process_update (ap);
761 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ap->treeview));
762 g_signal_connect (G_OBJECT (selection), "changed",
763 G_CALLBACK (on_selection_changed), ap);
764 g_signal_connect (G_OBJECT (ap->dialog), "delete_event",
765 G_CALLBACK (on_delete_event), ap);
766 g_signal_connect (GTK_OBJECT (checkb_hide_paths), "toggled",
767 G_CALLBACK (on_toggle_hide_paths), ap);
768 g_signal_connect (GTK_OBJECT (checkb_hide_params), "toggled",
769 G_CALLBACK (on_toggle_hide_params), ap);
770 g_signal_connect (GTK_OBJECT (checkb_process_tree), "toggled",
771 G_CALLBACK (on_toggle_process_tree), ap);
774 gtk_window_set_transient_for (GTK_WINDOW (ap->dialog),
775 GTK_WINDOW (parent));
776 /* gtk_widget_show (ap->dialog); */
777 res = gtk_dialog_run (GTK_DIALOG (ap->dialog));
778 while (res == GTK_RESPONSE_APPLY)
780 attach_process_update (ap);
781 res = gtk_dialog_run (GTK_DIALOG (ap->dialog));
783 if (res == GTK_RESPONSE_OK)
785 selected_pid = ap->pid;
787 attach_process_clear (ap, CLEAR_FINAL);
788 return selected_pid;
791 static void
792 attach_process_destroy (AttachProcess * ap)
794 g_return_if_fail (ap);
795 g_free (ap);
798 /* Load file private functions
799 *---------------------------------------------------------------------------*/
801 static void
802 on_select_target (GtkButton *button, gpointer user_data)
804 gtk_dialog_response (GTK_DIALOG (user_data), ANJUTA_RESPONSE_SELECT_TARGET);
807 static void
808 dma_start_load_uri (DmaStart *this)
810 GList *search_dirs;
811 GnomeVFSURI *vfs_uri;
812 gchar *mime_type;
813 const gchar *filename;
814 // GList *node;
816 if ((this->target_uri != NULL) && (*(this->target_uri) != '\0'))
818 vfs_uri = gnome_vfs_uri_new (this->target_uri);
820 g_return_if_fail (vfs_uri != NULL);
822 if (!gnome_vfs_uri_is_local (vfs_uri)) return;
824 search_dirs = get_source_directories (this->plugin);
826 mime_type = gnome_vfs_get_mime_type (this->target_uri);
827 filename = gnome_vfs_uri_get_path (vfs_uri);
829 ianjuta_debugger_interrupt (this->debugger, NULL);
830 ianjuta_debugger_quit (this->debugger, NULL);
831 ianjuta_debugger_load (this->debugger, filename, mime_type, search_dirs, this->run_in_terminal, NULL);
833 g_free (mime_type);
834 gnome_vfs_uri_unref (vfs_uri);
835 free_source_directories (search_dirs);
840 static gboolean
841 dma_set_parameters (DmaStart *this)
843 GladeXML *gxml;
844 GtkWidget *dlg;
845 GtkWindow *parent;
846 GtkToggleButton *term;
847 GtkComboBox *params;
848 GtkComboBox *target;
849 gint response;
850 GtkTreeModel* model;
851 GtkTreeIter iter;
852 GValue value = {0,};
853 const gchar *project_root_uri;
855 parent = GTK_WINDOW (this->plugin->shell);
856 gxml = glade_xml_new (GLADE_FILE, PARAMETER_DIALOG, NULL);
857 if (gxml == NULL)
859 anjuta_util_dialog_error(parent, _("Missing file %s"), GLADE_FILE);
860 return FALSE;
863 dlg = glade_xml_get_widget (gxml, PARAMETER_DIALOG);
864 term = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gxml, TERMINAL_CHECK_BUTTON));
865 params = GTK_COMBO_BOX (glade_xml_get_widget (gxml, PARAMETER_COMBO));
866 target = GTK_COMBO_BOX (glade_xml_get_widget (gxml, TARGET_COMBO));
867 glade_xml_signal_connect_data (gxml, TARGET_SELECT_SIGNAL, GTK_SIGNAL_FUNC (on_select_target), dlg);
868 g_object_unref (gxml);
870 /* Fill parameter combo box */
871 model = GTK_TREE_MODEL (gtk_list_store_new (1, GTK_TYPE_STRING));
872 gtk_combo_box_set_model (params, model);
873 gtk_combo_box_entry_set_text_column( GTK_COMBO_BOX_ENTRY(params), 0);
874 if (this->program_args != NULL)
876 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
877 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, this->program_args, -1);
878 gtk_entry_set_text (GTK_ENTRY (GTK_BIN (params)->child), this->program_args);
880 g_object_unref (model);
882 /* Fill target combo box */
883 model = GTK_TREE_MODEL (gtk_list_store_new (1, GTK_TYPE_STRING));
884 gtk_combo_box_set_model (target, model);
885 gtk_combo_box_entry_set_text_column( GTK_COMBO_BOX_ENTRY(target), 0);
887 anjuta_shell_get_value (this->plugin->shell, "project_root_uri", &value, NULL);
888 project_root_uri = g_value_get_string (&value);
889 if (project_root_uri != NULL)
891 /* One project loaded, get all executable target */
892 IAnjutaProjectManager *pm;
893 GList *exec_targets = NULL;
895 pm = anjuta_shell_get_interface (this->plugin->shell,
896 IAnjutaProjectManager, NULL);
897 if (pm != NULL)
899 exec_targets = ianjuta_project_manager_get_targets (pm,
900 IANJUTA_PROJECT_MANAGER_TARGET_EXECUTABLE,
901 NULL);
903 if (exec_targets != NULL)
905 GList *node;
907 for (node = exec_targets; node; node = g_list_next (node))
909 if ((this->target_uri == NULL) || (strcmp(this->target_uri, node->data) != 0))
911 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
912 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, node->data, -1);
914 g_free (node->data);
916 g_list_free (exec_targets);
919 g_object_unref (model);
921 if (this->target_uri != NULL)
923 gtk_list_store_prepend (GTK_LIST_STORE (model), &iter);
924 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, this->target_uri, -1);
925 gtk_entry_set_text (GTK_ENTRY (GTK_BIN (target)->child), this->target_uri);
927 else if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter))
929 gchar *txt;
931 gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &txt, -1);
932 gtk_entry_set_text (GTK_ENTRY (GTK_BIN (target)->child), txt);
933 g_free (txt);
936 /* Set terminal option */
937 if (this->run_in_terminal) gtk_toggle_button_set_active (term, TRUE);
939 gtk_window_set_transient_for (GTK_WINDOW (dlg), parent);
941 /* Run dialog */
942 for (;;)
944 response = gtk_dialog_run (GTK_DIALOG (dlg));
945 switch (response)
947 case GTK_RESPONSE_OK:
948 case GTK_RESPONSE_APPLY:
950 const gchar *arg;
951 const gchar *uri;
953 if (this->program_args != NULL) g_free (this->program_args);
954 arg = gtk_entry_get_text (GTK_ENTRY (GTK_BIN (params)->child));
955 this->program_args = g_strdup (arg);
957 uri = gtk_entry_get_text (GTK_ENTRY (GTK_BIN (target)->child));
958 if (this->target_uri != NULL)
960 if (strcmp(uri, this->target_uri) != 0)
962 g_free (this->target_uri);
963 this->target_uri = g_strdup (uri);
966 else
968 this->target_uri = g_strdup (uri);
971 this->run_in_terminal = gtk_toggle_button_get_active (term);
972 break;
974 case ANJUTA_RESPONSE_SELECT_TARGET:
976 GtkWidget *sel_dlg = gtk_file_chooser_dialog_new (
977 _("Load Target to debug"), GTK_WINDOW (dlg),
978 GTK_FILE_CHOOSER_ACTION_OPEN,
979 GTK_STOCK_OPEN, GTK_RESPONSE_OK,
980 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
981 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(sel_dlg), FALSE);
982 gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (sel_dlg), TRUE);
984 GtkFileFilter *filter = gtk_file_filter_new ();
985 gtk_file_filter_set_name (filter, _("All files"));
986 gtk_file_filter_add_pattern (filter, "*");
987 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (sel_dlg), filter);
989 //gtk_window_set_transient_for (GTK_WINDOW (dlg), parent);
991 response = gtk_dialog_run (GTK_DIALOG (sel_dlg));
993 if (response == GTK_RESPONSE_OK)
995 gchar* uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (sel_dlg));
997 if (this->target_uri != NULL)
999 if (strcmp(uri, this->target_uri) != 0)
1001 g_free (this->target_uri);
1002 this->target_uri = uri;
1004 else
1006 g_free (uri);
1009 else
1011 this->target_uri = uri;
1014 gtk_entry_set_text (GTK_ENTRY (GTK_BIN (target)->child), this->target_uri);
1017 gtk_widget_destroy (GTK_WIDGET (sel_dlg));
1019 continue;
1021 default:
1022 break;
1024 break;
1026 gtk_widget_destroy (dlg);
1028 return response == GTK_RESPONSE_OK;
1031 /* Public functions
1032 *---------------------------------------------------------------------------*/
1034 void
1035 dma_attach_to_process (DmaStart* this)
1037 pid_t selected_pid;
1038 GtkWindow *parent;
1039 AttachProcess *attach_process = NULL;
1041 parent = GTK_WINDOW (ANJUTA_PLUGIN (this->plugin)->shell);
1042 attach_process = attach_process_new();
1044 selected_pid = attach_process_show (attach_process, parent);
1045 if (selected_pid > 0)
1047 long lpid = selected_pid;
1048 GList *search_dirs;
1050 search_dirs = get_source_directories (this->plugin);
1051 ianjuta_debugger_interrupt (this->debugger, NULL);
1052 ianjuta_debugger_quit (this->debugger, NULL);
1053 ianjuta_debugger_attach (this->debugger, lpid, search_dirs, NULL);
1054 free_source_directories (search_dirs);
1056 attach_process_destroy(attach_process);
1059 gboolean
1060 dma_run_target (DmaStart *this)
1062 if (dma_set_parameters (this) == TRUE)
1064 dma_start_load_uri (this);
1065 ianjuta_debugger_start (this->debugger, this->program_args == NULL ? "" : this->program_args, NULL);
1068 return this->target_uri != NULL;
1071 gboolean
1072 dma_rerun_target (DmaStart *this)
1074 if (this->target_uri == NULL) return FALSE;
1076 dma_start_load_uri (this);
1077 ianjuta_debugger_start (this->debugger, this->program_args == NULL ? "" : this->program_args, NULL);
1079 return TRUE;
1082 /* Constructor & Destructor
1083 *---------------------------------------------------------------------------*/
1085 DmaStart *
1086 dma_start_new (AnjutaPlugin *plugin, IAnjutaDebugger *debugger)
1088 DmaStart *this;
1090 this = g_new0 (DmaStart, 1);
1092 this->plugin = plugin;
1093 this->debugger = debugger;
1095 g_signal_connect (plugin->shell, "save-session",
1096 G_CALLBACK (on_session_save), this);
1097 g_signal_connect (plugin->shell, "load-session",
1098 G_CALLBACK (on_session_load), this);
1100 return this;
1103 void
1104 dma_start_free (DmaStart *this)
1106 g_signal_handlers_disconnect_by_func (this->plugin->shell, G_CALLBACK (on_session_save), this);
1107 g_signal_handlers_disconnect_by_func (this->plugin->shell, G_CALLBACK (on_session_load), this);
1108 if (this->program_args != NULL) g_free (this->program_args);
1109 if (this->target_uri != NULL) g_free (this->target_uri);
1110 g_free (this);