1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
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 *---------------------------------------------------------------------------*/
37 #include <libanjuta/anjuta-debug.h>
38 #include <libanjuta/resources.h>
39 #include <libanjuta/interfaces/ianjuta-project-manager.h>
40 #include <libanjuta/anjuta-utils.h>
42 #include <libgnomevfs/gnome-vfs-mime-utils.h>
43 #include <libgnomevfs/gnome-vfs-utils.h>
47 #include <glade/glade-xml.h>
57 *---------------------------------------------------------------------------*/
59 typedef struct _AttachProcess AttachProcess
;
60 typedef struct _AddSourceDialog AddSourceDialog
;
61 typedef struct _LoadFileCallBack LoadFileCallBack
;
79 gboolean process_tree
;
83 gint iter_stack_level
;
84 gint num_spaces_to_skip
;
85 gint num_spaces_per_level
;
96 static char *column_names
[COLUMNS_NB
] = {
97 N_("Pid"), N_("User"), N_("Time"), N_("Command")
100 struct _AddSourceDialog
103 GtkFileChooser
*entry
;
107 struct _LoadFileCallBack
109 AnjutaPlugin
*plugin
;
110 DmaDebuggerQueue
*debugger
;
115 AnjutaPlugin
*plugin
;
117 DmaDebuggerQueue
*debugger
;
121 gboolean run_in_terminal
;
122 gboolean stop_at_beginning
;
127 /* Widgets found in glade file
128 *---------------------------------------------------------------------------*/
130 #define PARAMETER_DIALOG "parameter_dialog"
131 #define TERMINAL_CHECK_BUTTON "parameter_run_in_term_check"
132 #define STOP_AT_BEGINNING_CHECK_BUTTON "stop_at_beginning_check"
133 #define PARAMETER_COMBO "parameter_combo"
134 #define TARGET_COMBO "target_combo"
135 #define TARGET_SELECT_SIGNAL "on_select_target_clicked"
137 #define ADD_SOURCE_DIALOG "source_paths_dialog"
138 #define SOURCE_ENTRY "src_entry"
139 #define SOURCE_LIST "src_clist"
140 #define ADD_BUTTON "add_button"
141 #define REMOVE_BUTTON "remove_button"
142 #define UP_BUTTON "up_button"
143 #define DOWN_BUTTON "down_button"
145 #define ANJUTA_RESPONSE_SELECT_TARGET 0
147 static void attach_process_clear (AttachProcess
* ap
, gint ClearRequest
);
150 *---------------------------------------------------------------------------*/
152 /* This functions get all directories of the current project containing
153 * static or shared library. Perhaps a more reliable way to find these
154 * directories is to really get the directories of all source files */
157 get_source_directories (AnjutaPlugin
*plugin
)
160 GList
*node
, *search_dirs
= NULL
;
161 GList
*slibs_dirs
= NULL
;
162 GList
*libs_dirs
= NULL
;
166 cwd
= g_get_current_dir();
167 search_dirs
= g_list_prepend (search_dirs
, gnome_vfs_get_uri_from_local_path(cwd
));
170 /* Check if a project is already open */
171 anjuta_shell_get_value (plugin
->shell
, "project_root_uri", &value
, NULL
);
173 /* Set source file search directories */
174 if (g_value_get_string (&value
) != NULL
)
176 IAnjutaProjectManager
*pm
;
177 pm
= anjuta_shell_get_interface (plugin
->shell
,
178 IAnjutaProjectManager
, NULL
);
182 ianjuta_project_manager_get_targets (pm
,
183 IANJUTA_PROJECT_MANAGER_TARGET_SHAREDLIB
,
186 ianjuta_project_manager_get_targets (pm
,
187 IANJUTA_PROJECT_MANAGER_TARGET_STATICLIB
,
191 slibs_dirs
= g_list_reverse (slibs_dirs
);
192 libs_dirs
= g_list_reverse (libs_dirs
);
198 dir_uri
= g_path_get_dirname (node
->data
);
199 search_dirs
= g_list_prepend (search_dirs
, dir_uri
);
200 node
= g_list_next (node
);
207 dir_uri
= g_path_get_dirname (node
->data
);
208 search_dirs
= g_list_prepend (search_dirs
, dir_uri
);
209 node
= g_list_next (node
);
212 g_list_foreach (slibs_dirs
, (GFunc
)g_free
, NULL
);
213 g_list_free (slibs_dirs
);
214 g_list_foreach (libs_dirs
, (GFunc
)g_free
, NULL
);
215 g_list_free (libs_dirs
);
217 return g_list_reverse (search_dirs
);
221 free_source_directories (GList
*dirs
)
223 g_list_foreach (dirs
, (GFunc
)g_free
, NULL
);
227 /* Callback for saving session
228 *---------------------------------------------------------------------------*/
231 on_session_save (AnjutaShell
*shell
, AnjutaSessionPhase phase
, AnjutaSession
*session
, DmaStart
*this)
233 if (phase
!= ANJUTA_SESSION_PHASE_NORMAL
)
236 if (this->program_args
)
239 anjuta_session_set_string (session
, "Execution", "Program arguments", this->program_args
);
240 arg
= anjuta_session_get_string (session
, "Execution", "Program arguments");
242 if (this->target_uri
)
245 anjuta_session_set_string (session
, "Execution", "Program uri", this->target_uri
);
246 uri
= anjuta_session_get_string (session
, "Execution", "Program uri");
248 anjuta_session_set_int (session
, "Execution", "Run in terminal", this->run_in_terminal
+ 1);
249 anjuta_session_set_int (session
, "Execution", "Stop at beginning", this->stop_at_beginning
+ 1);
250 if (this->source_dirs
)
252 anjuta_session_set_string_list (session
, "Debugger", "Source directories", this->source_dirs
);
256 static void on_session_load (AnjutaShell
*shell
, AnjutaSessionPhase phase
, AnjutaSession
*session
, DmaStart
*this)
260 gint run_in_terminal
;
261 gint stop_at_beginning
;
263 if (phase
!= ANJUTA_SESSION_PHASE_NORMAL
)
266 program_args
= anjuta_session_get_string (session
, "Execution", "Program arguments");
267 if (this->program_args
)
269 g_free (this->program_args
);
270 this->program_args
= NULL
;
274 this->program_args
= program_args
;
277 target_uri
= anjuta_session_get_string (session
, "Execution", "Program uri");
278 if (this->target_uri
)
280 g_free (this->target_uri
);
281 this->target_uri
= NULL
;
285 this->target_uri
= target_uri
;
288 /* The flag is store as 1 == FALSE, 2 == TRUE */
289 run_in_terminal
= anjuta_session_get_int (session
, "Execution", "Run in terminal");
290 if (run_in_terminal
== 0)
291 this->run_in_terminal
= TRUE
; /* Default value */
293 this->run_in_terminal
= run_in_terminal
- 1;
295 stop_at_beginning
= anjuta_session_get_int (session
, "Execution", "Stop at beginning");
296 if (stop_at_beginning
== 0)
297 this->stop_at_beginning
= TRUE
; /* Default value */
299 this->stop_at_beginning
= stop_at_beginning
- 1;
300 /* Initialize source_dirs */
301 if (this->source_dirs
!= NULL
)
303 g_list_foreach (this->source_dirs
, (GFunc
)g_free
, NULL
);
304 g_list_free (this->source_dirs
);
306 this->source_dirs
= anjuta_session_get_string_list (session
, "Debugger", "Source directories");
309 /* Attach to process private functions
310 *---------------------------------------------------------------------------*/
312 static AttachProcess
*
313 attach_process_new ()
316 ap
= g_new0 (AttachProcess
, 1);
317 attach_process_clear (ap
, CLEAR_INITIAL
);
322 attach_process_clear (AttachProcess
* ap
, gint ClearRequest
)
327 switch (ClearRequest
)
333 g_free (ap
->ps_output
);
336 ap
->ps_output
= NULL
;
340 switch (ClearRequest
)
346 ap
->iter_stack
= NULL
;
347 ap
->iter_stack_level
= -1;
348 ap
->num_spaces_to_skip
= -1;
352 switch (ClearRequest
)
357 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (ap
->treeview
));
358 gtk_tree_store_clear (GTK_TREE_STORE (model
));
362 if (ClearRequest
== CLEAR_FINAL
)
364 gtk_widget_destroy (ap
->dialog
);
369 static inline gchar
*
370 skip_spaces (gchar
*pos
)
377 static inline gchar
*
378 skip_token (gchar
*pos
)
387 skip_token_and_spaces (gchar
*pos
)
389 pos
= skip_token (pos
);
390 return skip_spaces (pos
);
394 iter_stack_push_new (AttachProcess
*ap
, GtkTreeStore
*store
)
396 GtkTreeIter
*new_iter
, *top_iter
;
397 new_iter
= g_new (GtkTreeIter
, 1);
398 top_iter
= (GtkTreeIter
*) (g_slist_nth_data (ap
->iter_stack
, 0));
400 g_slist_prepend (ap
->iter_stack
, (gpointer
) (new_iter
));
401 gtk_tree_store_append (store
, new_iter
, top_iter
);
402 ap
->iter_stack_level
++;
407 iter_stack_pop (AttachProcess
*ap
)
409 if (ap
->iter_stack_level
< 0)
413 (GtkTreeIter
*) (g_slist_nth_data (ap
->iter_stack
, 0));
415 g_slist_delete_link (ap
->iter_stack
, ap
->iter_stack
);
417 ap
->iter_stack_level
--;
422 iter_stack_clear (AttachProcess
*ap
)
424 while (iter_stack_pop (ap
));
428 calc_depth_and_get_iter (AttachProcess
*ap
, GtkTreeStore
*store
,
429 GtkTreeIter
**iter
, gchar
*pos
)
432 guint num_spaces
, depth
, i
;
438 num_spaces
= pos
- orig_pos
;
440 if (ap
->process_tree
)
442 if (ap
->num_spaces_to_skip
< 0)
444 // first process to be inserted
445 ap
->num_spaces_to_skip
= num_spaces
;
446 ap
->num_spaces_per_level
= -1;
447 *iter
= iter_stack_push_new (ap
, store
);
451 if (ap
->num_spaces_per_level
< 0)
453 if (num_spaces
== ap
->num_spaces_to_skip
)
455 // num_spaces_per_level still unknown
457 *iter
= iter_stack_push_new (ap
, store
);
461 // first time at level 1
462 ap
->num_spaces_per_level
=
463 num_spaces
- ap
->num_spaces_to_skip
;
464 *iter
= iter_stack_push_new (ap
, store
);
469 depth
= (num_spaces
- ap
->num_spaces_to_skip
) /
470 ap
->num_spaces_per_level
;
471 if (depth
== ap
->iter_stack_level
)
475 *iter
= iter_stack_push_new (ap
, store
);
478 if (depth
== ap
->iter_stack_level
+ 1)
479 *iter
= iter_stack_push_new (ap
, store
);
481 if (depth
< ap
->iter_stack_level
)
483 // jump some levels backward
484 depth
= ap
->iter_stack_level
- depth
;
485 for (i
= 0; i
<= depth
; i
++)
487 *iter
= iter_stack_push_new (ap
, store
);
491 // should never get here
492 g_warning("Unknown error");
494 *iter
= iter_stack_push_new (ap
, store
);
502 *iter
= iter_stack_push_new (ap
, store
);
509 skip_path (gchar
*pos
)
511 /* can't use g_path_get_basename() - wouldn't work for a processes
512 started with parameters containing '/' */
513 gchar c
, *final_pos
= pos
;
515 if (*pos
== G_DIR_SEPARATOR
)
519 if (c
== G_DIR_SEPARATOR
)
525 if (c
== ' ' || c
== '\0')
536 remove_params (gchar
*pos
)
547 attach_process_add_line (AttachProcess
*ap
, GtkTreeStore
*store
, gchar
*line
)
549 gchar
*pid
, *user
, *start
, *command
, *tmp
;
553 pid
= skip_spaces (line
); // skip leading spaces
554 user
= skip_token_and_spaces (pid
); // skip PID
555 start
= skip_token_and_spaces (user
); // skip USER
556 tmp
= skip_token (start
); // skip START (do not skip spaces)
558 command
= calc_depth_and_get_iter (ap
, store
, &iter
, tmp
);
562 command
= skip_path (command
);
567 remove_params(command
);
570 gtk_tree_store_set (store
, iter
,
574 COMMAND_COLUMN
, command
,
579 attach_process_review (AttachProcess
*ap
)
581 gchar
*ps_output
, *begin
, *end
;
585 g_return_if_fail (ap
);
586 g_return_if_fail (ap
->ps_output
);
587 store
= GTK_TREE_STORE (gtk_tree_view_get_model
588 (GTK_TREE_VIEW (ap
->treeview
)));
589 g_return_if_fail (store
);
591 ps_output
= g_strdup (ap
->ps_output
);
596 while (*end
&& *end
!= '\n') end
++;
597 if (++line_num
> 2) // skip description line & process 'init'
600 attach_process_add_line (ap
, store
, begin
);
606 iter_stack_clear (ap
);
607 gtk_tree_view_expand_all (GTK_TREE_VIEW (ap
->treeview
));
611 attach_process_update (AttachProcess
* ap
)
613 gchar
*tmp
, *tmp1
, *cmd
;
619 g_return_if_fail (ap
);
620 store
= GTK_TREE_STORE (gtk_tree_view_get_model
621 (GTK_TREE_VIEW (ap
->treeview
)));
622 g_return_if_fail (store
);
624 if (anjuta_util_prog_is_installed ("ps", TRUE
) == FALSE
)
627 tmp
= anjuta_util_get_a_tmp_file ();
628 cmd
= g_strconcat ("ps axw -H -o pid,user,start_time,args > ", tmp
, NULL
);
629 shell
= gnome_util_user_shell ();
633 execlp (shell
, shell
, "-c", cmd
, NULL
);
637 anjuta_util_dialog_error_system (NULL
, errno
,
638 _("Unable to execute: %s."), cmd
);
643 waitpid (ch_pid
, NULL
, 0);
646 result
= g_file_get_contents (tmp
, &tmp1
, NULL
, NULL
);
651 anjuta_util_dialog_error_system (NULL
, errno
,
652 _("Unable to open the file: %s\n"),
657 attach_process_clear (ap
, CLEAR_UPDATE
);
658 ap
->ps_output
= anjuta_util_convert_to_utf8 (tmp1
);
662 attach_process_review (ap
);
667 on_selection_changed (GtkTreeSelection
*selection
, AttachProcess
*ap
)
672 g_return_if_fail (ap
);
673 if (gtk_tree_selection_get_selected (selection
, &model
, &iter
))
676 gtk_tree_model_get (model
, &iter
, PID_COLUMN
, &text
, -1);
677 ap
->pid
= atoi (text
);
678 gtk_dialog_set_response_sensitive (GTK_DIALOG (ap
->dialog
),
679 GTK_RESPONSE_OK
, TRUE
);
683 gtk_dialog_set_response_sensitive (GTK_DIALOG (ap
->dialog
),
684 GTK_RESPONSE_OK
, FALSE
);
690 on_delete_event (GtkWidget
*dialog
, GdkEvent
*event
, AttachProcess
*ap
)
692 g_return_val_if_fail (ap
, FALSE
);
693 attach_process_clear (ap
, CLEAR_FINAL
);
698 sort_pid (GtkTreeModel
*model
, GtkTreeIter
*a
, GtkTreeIter
*b
,
704 gtk_tree_model_get (model
, a
, PID_COLUMN
, &nptr
, -1);
707 gtk_tree_model_get (model
, b
, PID_COLUMN
, &nptr
, -1);
714 on_toggle_hide_paths (GtkToggleButton
*togglebutton
, AttachProcess
* ap
)
716 ap
->hide_paths
= gtk_toggle_button_get_active (togglebutton
);
717 attach_process_clear (ap
, CLEAR_REVIEW
);
718 attach_process_review (ap
);
722 on_toggle_hide_params (GtkToggleButton
*togglebutton
, AttachProcess
* ap
)
724 ap
->hide_params
= gtk_toggle_button_get_active (togglebutton
);
725 attach_process_clear (ap
, CLEAR_REVIEW
);
726 attach_process_review (ap
);
730 on_toggle_process_tree (GtkToggleButton
*togglebutton
, AttachProcess
* ap
)
732 ap
->process_tree
= gtk_toggle_button_get_active (togglebutton
);
733 attach_process_clear (ap
, CLEAR_REVIEW
);
734 attach_process_review (ap
);
738 attach_process_show (AttachProcess
* ap
, GtkWindow
*parent
)
743 GtkCellRenderer
*renderer
;
744 GtkTreeSelection
*selection
;
745 GtkCheckButton
*checkb_hide_paths
;
746 GtkCheckButton
*checkb_hide_params
;
747 GtkCheckButton
*checkb_process_tree
;
749 pid_t selected_pid
= -1;
751 g_return_val_if_fail (ap
!= NULL
, -1);
755 gxml
= glade_xml_new (GLADE_FILE
, "attach_process_dialog", NULL
);
756 ap
->dialog
= glade_xml_get_widget (gxml
, "attach_process_dialog");
757 ap
->treeview
= glade_xml_get_widget (gxml
, "attach_process_tv");
758 checkb_hide_paths
= GTK_CHECK_BUTTON (
759 glade_xml_get_widget (gxml
, "checkb_hide_paths"));
760 checkb_hide_params
= GTK_CHECK_BUTTON (
761 glade_xml_get_widget (gxml
, "checkb_hide_params"));
762 checkb_process_tree
= GTK_CHECK_BUTTON (
763 glade_xml_get_widget (gxml
, "checkb_process_tree"));
764 g_object_unref (gxml
);
766 view
= GTK_TREE_VIEW (ap
->treeview
);
767 store
= gtk_tree_store_new (COLUMNS_NB
,
772 gtk_tree_view_set_model (view
, GTK_TREE_MODEL (store
));
773 gtk_tree_selection_set_mode (gtk_tree_view_get_selection (view
),
774 GTK_SELECTION_SINGLE
);
775 g_object_unref (G_OBJECT (store
));
777 renderer
= gtk_cell_renderer_text_new ();
779 for (i
= PID_COLUMN
; i
< COLUMNS_NB
; i
++) {
780 GtkTreeViewColumn
*column
;
782 column
= gtk_tree_view_column_new_with_attributes (column_names
[i
],
783 renderer
, "text", i
, NULL
);
784 gtk_tree_view_column_set_sort_column_id(column
, i
);
785 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
786 gtk_tree_view_append_column (view
, column
);
787 if (i
== COMMAND_COLUMN
)
788 gtk_tree_view_set_expander_column(view
, column
);
790 gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store
), PID_COLUMN
,
791 sort_pid
, NULL
, NULL
);
792 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store
),
793 START_COLUMN
, GTK_SORT_DESCENDING
);
795 ap
->hide_paths
= gtk_toggle_button_get_active (
796 GTK_TOGGLE_BUTTON (checkb_hide_paths
));
797 ap
->hide_params
= gtk_toggle_button_get_active (
798 GTK_TOGGLE_BUTTON (checkb_hide_params
));
799 ap
->process_tree
= gtk_toggle_button_get_active (
800 GTK_TOGGLE_BUTTON (checkb_process_tree
));
802 attach_process_update (ap
);
804 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (ap
->treeview
));
805 g_signal_connect (G_OBJECT (selection
), "changed",
806 G_CALLBACK (on_selection_changed
), ap
);
807 g_signal_connect (G_OBJECT (ap
->dialog
), "delete_event",
808 G_CALLBACK (on_delete_event
), ap
);
809 g_signal_connect (GTK_OBJECT (checkb_hide_paths
), "toggled",
810 G_CALLBACK (on_toggle_hide_paths
), ap
);
811 g_signal_connect (GTK_OBJECT (checkb_hide_params
), "toggled",
812 G_CALLBACK (on_toggle_hide_params
), ap
);
813 g_signal_connect (GTK_OBJECT (checkb_process_tree
), "toggled",
814 G_CALLBACK (on_toggle_process_tree
), ap
);
817 gtk_window_set_transient_for (GTK_WINDOW (ap
->dialog
),
818 GTK_WINDOW (parent
));
819 /* gtk_widget_show (ap->dialog); */
820 res
= gtk_dialog_run (GTK_DIALOG (ap
->dialog
));
821 while (res
== GTK_RESPONSE_APPLY
)
823 attach_process_update (ap
);
824 res
= gtk_dialog_run (GTK_DIALOG (ap
->dialog
));
826 if (res
== GTK_RESPONSE_OK
)
828 selected_pid
= ap
->pid
;
830 attach_process_clear (ap
, CLEAR_FINAL
);
835 attach_process_destroy (AttachProcess
* ap
)
837 g_return_if_fail (ap
);
841 /* Load file private functions
842 *---------------------------------------------------------------------------*/
845 on_select_target (GtkButton
*button
, gpointer user_data
)
847 gtk_dialog_response (GTK_DIALOG (user_data
), ANJUTA_RESPONSE_SELECT_TARGET
);
851 dma_start_load_uri (DmaStart
*this)
854 GnomeVFSURI
*vfs_uri
;
858 if (!dma_quit_debugger (this)) return;
860 if ((this->target_uri
!= NULL
) && (*(this->target_uri
) != '\0'))
862 vfs_uri
= gnome_vfs_uri_new (this->target_uri
);
864 g_return_if_fail (vfs_uri
!= NULL
);
866 if (!gnome_vfs_uri_is_local (vfs_uri
)) return;
868 search_dirs
= get_source_directories (this->plugin
);
870 mime_type
= gnome_vfs_get_mime_type (this->target_uri
);
871 filename
= gnome_vfs_get_local_path_from_uri (this->target_uri
);
873 dma_queue_load (this->debugger
, filename
, mime_type
, this->source_dirs
);
877 gnome_vfs_uri_unref (vfs_uri
);
878 free_source_directories (search_dirs
);
884 dma_set_parameters (DmaStart
*this)
889 GtkToggleButton
*term
;
890 GtkToggleButton
*stop_at_beginning
;
897 const gchar
*project_root_uri
;
899 parent
= GTK_WINDOW (this->plugin
->shell
);
900 gxml
= glade_xml_new (GLADE_FILE
, PARAMETER_DIALOG
, NULL
);
903 anjuta_util_dialog_error(parent
, _("Missing file %s"), GLADE_FILE
);
907 dlg
= glade_xml_get_widget (gxml
, PARAMETER_DIALOG
);
908 term
= GTK_TOGGLE_BUTTON (glade_xml_get_widget (gxml
, TERMINAL_CHECK_BUTTON
));
909 stop_at_beginning
= GTK_TOGGLE_BUTTON (glade_xml_get_widget (gxml
, STOP_AT_BEGINNING_CHECK_BUTTON
));
910 params
= GTK_COMBO_BOX (glade_xml_get_widget (gxml
, PARAMETER_COMBO
));
911 target
= GTK_COMBO_BOX (glade_xml_get_widget (gxml
, TARGET_COMBO
));
912 glade_xml_signal_connect_data (gxml
, TARGET_SELECT_SIGNAL
, GTK_SIGNAL_FUNC (on_select_target
), dlg
);
913 g_object_unref (gxml
);
915 /* Fill parameter combo box */
916 model
= GTK_TREE_MODEL (gtk_list_store_new (1, GTK_TYPE_STRING
));
917 gtk_combo_box_set_model (params
, model
);
918 gtk_combo_box_entry_set_text_column( GTK_COMBO_BOX_ENTRY(params
), 0);
919 if (this->program_args
!= NULL
)
921 gtk_list_store_append (GTK_LIST_STORE (model
), &iter
);
922 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
, 0, this->program_args
, -1);
923 gtk_entry_set_text (GTK_ENTRY (GTK_BIN (params
)->child
), this->program_args
);
925 g_object_unref (model
);
927 /* Fill target combo box */
928 model
= GTK_TREE_MODEL (gtk_list_store_new (1, GTK_TYPE_STRING
));
929 gtk_combo_box_set_model (target
, model
);
930 gtk_combo_box_entry_set_text_column( GTK_COMBO_BOX_ENTRY(target
), 0);
932 anjuta_shell_get_value (this->plugin
->shell
, "project_root_uri", &value
, NULL
);
933 project_root_uri
= G_VALUE_HOLDS_STRING (&value
) ? g_value_get_string (&value
) : NULL
;
934 if (project_root_uri
!= NULL
)
936 /* One project loaded, get all executable target */
937 IAnjutaProjectManager
*pm
;
938 GList
*exec_targets
= NULL
;
940 pm
= anjuta_shell_get_interface (this->plugin
->shell
,
941 IAnjutaProjectManager
, NULL
);
944 exec_targets
= ianjuta_project_manager_get_targets (pm
,
945 IANJUTA_PROJECT_MANAGER_TARGET_EXECUTABLE
,
948 if (exec_targets
!= NULL
)
952 for (node
= exec_targets
; node
; node
= g_list_next (node
))
954 if ((this->target_uri
== NULL
) || (strcmp(this->target_uri
, node
->data
) != 0))
956 gtk_list_store_append (GTK_LIST_STORE (model
), &iter
);
957 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
, 0, node
->data
, -1);
961 g_list_free (exec_targets
);
964 g_object_unref (model
);
966 if (this->target_uri
!= NULL
)
968 gtk_list_store_prepend (GTK_LIST_STORE (model
), &iter
);
969 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
, 0, this->target_uri
, -1);
970 gtk_entry_set_text (GTK_ENTRY (GTK_BIN (target
)->child
), this->target_uri
);
972 else if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model
), &iter
))
976 gtk_tree_model_get (GTK_TREE_MODEL (model
), &iter
, 0, &txt
, -1);
977 gtk_entry_set_text (GTK_ENTRY (GTK_BIN (target
)->child
), txt
);
981 /* Set terminal option */
982 if (this->run_in_terminal
) gtk_toggle_button_set_active (term
, TRUE
);
983 if (this->stop_at_beginning
) gtk_toggle_button_set_active (stop_at_beginning
, TRUE
);
985 gtk_window_set_transient_for (GTK_WINDOW (dlg
), parent
);
990 response
= gtk_dialog_run (GTK_DIALOG (dlg
));
993 case GTK_RESPONSE_OK
:
994 case GTK_RESPONSE_APPLY
:
999 if (this->program_args
!= NULL
) g_free (this->program_args
);
1000 arg
= gtk_entry_get_text (GTK_ENTRY (GTK_BIN (params
)->child
));
1001 this->program_args
= g_strdup (arg
);
1003 uri
= gtk_entry_get_text (GTK_ENTRY (GTK_BIN (target
)->child
));
1004 if (this->target_uri
!= NULL
)
1006 if (strcmp(uri
, this->target_uri
) != 0)
1008 g_free (this->target_uri
);
1009 this->target_uri
= g_strdup (uri
);
1014 this->target_uri
= g_strdup (uri
);
1017 this->run_in_terminal
= gtk_toggle_button_get_active (term
);
1018 this->stop_at_beginning
= gtk_toggle_button_get_active (stop_at_beginning
);
1021 case ANJUTA_RESPONSE_SELECT_TARGET
:
1023 GtkWidget
*sel_dlg
= gtk_file_chooser_dialog_new (
1024 _("Load Target to debug"), GTK_WINDOW (dlg
),
1025 GTK_FILE_CHOOSER_ACTION_OPEN
,
1026 GTK_STOCK_OPEN
, GTK_RESPONSE_OK
,
1027 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
, NULL
);
1028 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(sel_dlg
), FALSE
);
1029 gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (sel_dlg
), TRUE
);
1031 GtkFileFilter
*filter
= gtk_file_filter_new ();
1032 gtk_file_filter_set_name (filter
, _("All files"));
1033 gtk_file_filter_add_pattern (filter
, "*");
1034 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (sel_dlg
), filter
);
1036 //gtk_window_set_transient_for (GTK_WINDOW (dlg), parent);
1038 response
= gtk_dialog_run (GTK_DIALOG (sel_dlg
));
1040 if (response
== GTK_RESPONSE_OK
)
1042 gchar
* uri
= gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (sel_dlg
));
1044 if (this->target_uri
!= NULL
)
1046 if (strcmp(uri
, this->target_uri
) != 0)
1048 g_free (this->target_uri
);
1049 this->target_uri
= uri
;
1058 this->target_uri
= uri
;
1061 gtk_entry_set_text (GTK_ENTRY (GTK_BIN (target
)->child
), this->target_uri
);
1064 gtk_widget_destroy (GTK_WIDGET (sel_dlg
));
1073 gtk_widget_destroy (dlg
);
1075 return response
== GTK_RESPONSE_OK
;
1078 /* Add source dialog
1079 *---------------------------------------------------------------------------*/
1082 on_add_source_in_list (GtkTreeModel
*model
, GtkTreePath
*path
, GtkTreeIter
*iter
, gpointer user_data
)
1084 GList
** list
= (GList
**)user_data
;
1088 gtk_tree_model_get (model
, iter
, 0, &dir
, -1);
1089 uri
= gnome_vfs_get_uri_from_local_path (dir
);
1090 *list
= g_list_prepend (*list
, uri
);
1097 on_add_source_in_model (gpointer data
, gpointer user_data
)
1099 GtkListStore
* model
= (GtkListStore
*)user_data
;
1103 local
= gnome_vfs_get_local_path_from_uri ((const char *)data
);
1104 gtk_list_store_append (model
, &iter
);
1105 gtk_list_store_set (model
, &iter
, 0, local
, -1);
1110 on_source_add_button (GtkButton
*button
, AddSourceDialog
*dlg
)
1115 path
= gtk_file_chooser_get_filename (dlg
->entry
);
1116 if ((path
!= NULL
) && (*path
!= '\0'))
1118 gtk_list_store_append (dlg
->model
, &iter
);
1119 gtk_list_store_set (dlg
->model
, &iter
, 0, path
, -1);
1124 on_source_remove_button (GtkButton
*button
, AddSourceDialog
*dlg
)
1127 GtkTreeSelection
* sel
;
1129 sel
= gtk_tree_view_get_selection (dlg
->tree
);
1130 if (gtk_tree_selection_get_selected (sel
, NULL
, &iter
))
1132 gtk_list_store_remove (dlg
->model
, &iter
);
1137 on_source_up_button (GtkButton
*button
, AddSourceDialog
*dlg
)
1140 GtkTreeSelection
* sel
;
1142 sel
= gtk_tree_view_get_selection (dlg
->tree
);
1143 if (gtk_tree_selection_get_selected (sel
, NULL
, &iter
))
1147 path
= gtk_tree_model_get_path(GTK_TREE_MODEL (dlg
->model
), &iter
);
1148 if (gtk_tree_path_prev(path
))
1152 gtk_tree_model_get_iter(GTK_TREE_MODEL (dlg
->model
), &pos
, path
);
1153 gtk_list_store_move_before (dlg
->model
, &iter
, &pos
);
1159 on_source_down_button (GtkButton
*button
, AddSourceDialog
*dlg
)
1162 GtkTreeSelection
* sel
;
1164 sel
= gtk_tree_view_get_selection (dlg
->tree
);
1165 if (gtk_tree_selection_get_selected (sel
, NULL
, &iter
))
1167 GtkTreeIter pos
= iter
;
1169 if (gtk_tree_model_iter_next (GTK_TREE_MODEL (dlg
->model
), &pos
))
1171 gtk_list_store_move_after (dlg
->model
, &iter
, &pos
);
1177 add_source_show (DmaStart
*this)
1179 AddSourceDialog dlg
;
1183 GtkCellRenderer
*renderer
;
1184 GtkTreeViewColumn
*column
;
1187 parent
= GTK_WINDOW (this->plugin
->shell
);
1188 gxml
= glade_xml_new (GLADE_FILE
, ADD_SOURCE_DIALOG
, NULL
);
1191 anjuta_util_dialog_error(parent
, _("Missing file %s"), GLADE_FILE
);
1195 widget
= glade_xml_get_widget (gxml
, ADD_SOURCE_DIALOG
);
1196 dlg
.tree
= GTK_TREE_VIEW (glade_xml_get_widget (gxml
, SOURCE_LIST
));
1197 dlg
.entry
= GTK_FILE_CHOOSER (glade_xml_get_widget (gxml
, SOURCE_ENTRY
));
1199 /* Connect signals */
1200 button
= G_OBJECT (glade_xml_get_widget (gxml
, ADD_BUTTON
));
1201 g_signal_connect (button
, "clicked", G_CALLBACK (on_source_add_button
), &dlg
);
1202 button
= G_OBJECT (glade_xml_get_widget (gxml
, REMOVE_BUTTON
));
1203 g_signal_connect (button
, "clicked", G_CALLBACK (on_source_remove_button
), &dlg
);
1204 button
= G_OBJECT (glade_xml_get_widget (gxml
, UP_BUTTON
));
1205 g_signal_connect (button
, "clicked", G_CALLBACK (on_source_up_button
), &dlg
);
1206 button
= G_OBJECT (glade_xml_get_widget (gxml
, DOWN_BUTTON
));
1207 g_signal_connect (button
, "clicked", G_CALLBACK (on_source_down_button
), &dlg
);
1209 g_object_unref (gxml
);
1211 renderer
= gtk_cell_renderer_text_new ();
1212 column
= gtk_tree_view_column_new_with_attributes (_("Path"), renderer
, "text", 0, NULL
);
1213 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
1214 gtk_tree_view_append_column (dlg
.tree
, column
);
1215 gtk_tree_view_set_expander_column(dlg
.tree
, column
);
1217 dlg
.model
= gtk_list_store_new (1, GTK_TYPE_STRING
);
1218 gtk_tree_view_set_model (dlg
.tree
, GTK_TREE_MODEL (dlg
.model
));
1220 gtk_window_set_transient_for (GTK_WINDOW (widget
), parent
);
1222 /* Initialize source path list */
1223 g_list_foreach (this->source_dirs
, on_add_source_in_model
, dlg
.model
);
1228 gint response
= gtk_dialog_run (GTK_DIALOG (widget
));
1232 case GTK_RESPONSE_DELETE_EVENT
:
1233 case GTK_RESPONSE_CLOSE
:
1234 g_list_foreach (this->source_dirs
, (GFunc
)g_free
, NULL
);
1235 g_list_free (this->source_dirs
);
1236 this->source_dirs
= NULL
;
1237 gtk_tree_model_foreach (GTK_TREE_MODEL (dlg
.model
), on_add_source_in_list
, &this->source_dirs
);
1238 this->source_dirs
= g_list_reverse (this->source_dirs
);
1240 case GTK_RESPONSE_CANCEL
:
1241 gtk_list_store_clear (dlg
.model
);
1242 g_list_foreach (this->source_dirs
, on_add_source_in_model
, dlg
.model
);
1249 gtk_widget_destroy (widget
);
1253 *---------------------------------------------------------------------------*/
1256 dma_quit_debugger (DmaStart
* this)
1258 if (dma_debugger_queue_get_state (this->debugger
) > IANJUTA_DEBUGGER_PROGRAM_LOADED
)
1260 gchar
*msg
= _("The program is running.\n"
1261 "Do you still want to stop the debugger?");
1263 if (!anjuta_util_dialog_boolean_question (GTK_WINDOW (this->plugin
->shell
), msg
)) return FALSE
;
1266 dma_queue_interrupt (this->debugger
);
1267 dma_queue_quit (this->debugger
);
1273 dma_add_source_path (DmaStart
*self
)
1275 add_source_show (self
);
1279 dma_attach_to_process (DmaStart
* this)
1283 AttachProcess
*attach_process
= NULL
;
1285 if (!dma_quit_debugger (this)) return;
1287 parent
= GTK_WINDOW (ANJUTA_PLUGIN (this->plugin
)->shell
);
1288 attach_process
= attach_process_new();
1290 selected_pid
= attach_process_show (attach_process
, parent
);
1291 if (selected_pid
> 0)
1293 long lpid
= selected_pid
;
1296 search_dirs
= get_source_directories (this->plugin
);
1298 dma_queue_attach (this->debugger
, lpid
, this->source_dirs
);
1299 free_source_directories (search_dirs
);
1301 attach_process_destroy(attach_process
);
1305 dma_run_target (DmaStart
*this)
1307 if (dma_set_parameters (this) == TRUE
)
1309 dma_start_load_uri (this);
1310 dma_queue_start (this->debugger
, this->program_args
== NULL
? "" : this->program_args
, this->run_in_terminal
, this->stop_at_beginning
);
1313 return this->target_uri
!= NULL
;
1317 dma_rerun_target (DmaStart
*this)
1319 if (this->target_uri
== NULL
) return FALSE
;
1321 dma_start_load_uri (this);
1322 dma_queue_start (this->debugger
, this->program_args
== NULL
? "" : this->program_args
, this->run_in_terminal
, this->stop_at_beginning
);
1327 /* Constructor & Destructor
1328 *---------------------------------------------------------------------------*/
1331 dma_start_new (DebugManagerPlugin
*plugin
)
1335 self
= g_new0 (DmaStart
, 1);
1337 self
->plugin
= ANJUTA_PLUGIN (plugin
);
1338 self
->debugger
= dma_debug_manager_get_queue (plugin
);
1339 self
->source_dirs
= NULL
;
1341 g_signal_connect (self
->plugin
->shell
, "save-session",
1342 G_CALLBACK (on_session_save
), self
);
1343 g_signal_connect (self
->plugin
->shell
, "load-session",
1344 G_CALLBACK (on_session_load
), self
);
1350 dma_start_free (DmaStart
*this)
1352 g_signal_handlers_disconnect_by_func (this->plugin
->shell
, G_CALLBACK (on_session_save
), this);
1353 g_signal_handlers_disconnect_by_func (this->plugin
->shell
, G_CALLBACK (on_session_load
), this);
1354 if (this->source_dirs
!= NULL
)
1356 g_list_foreach (this->source_dirs
, (GFunc
)g_free
, NULL
);
1357 g_list_free (this->source_dirs
);
1359 if (this->program_args
!= NULL
) g_free (this->program_args
);
1360 if (this->target_uri
!= NULL
) g_free (this->target_uri
);