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/interfaces/ianjuta-document-manager.h>
41 #include <libanjuta/interfaces/ianjuta-builder.h>
42 #include <libanjuta/interfaces/ianjuta-file-savable.h>
43 #include <libanjuta/anjuta-utils.h>
45 #include <libgnomevfs/gnome-vfs-mime-utils.h>
46 #include <libgnomevfs/gnome-vfs-utils.h>
48 #include <glade/glade-xml.h>
58 *---------------------------------------------------------------------------*/
60 typedef struct _AttachProcess AttachProcess
;
61 typedef struct _AddSourceDialog AddSourceDialog
;
62 typedef struct _LoadFileCallBack LoadFileCallBack
;
80 gboolean process_tree
;
84 gint iter_stack_level
;
85 gint num_spaces_to_skip
;
86 gint num_spaces_per_level
;
97 static char *column_names
[COLUMNS_NB
] = {
98 N_("Pid"), N_("User"), N_("Time"), N_("Command")
107 struct _AddSourceDialog
110 GtkFileChooser
*entry
;
114 struct _LoadFileCallBack
116 AnjutaPlugin
*plugin
;
117 DmaDebuggerQueue
*debugger
;
122 AnjutaPlugin
*plugin
;
124 DmaDebuggerQueue
*debugger
;
126 gboolean stop_at_beginning
;
130 IAnjutaBuilderHandle build_handle
;
133 /* Widgets found in glade file
134 *---------------------------------------------------------------------------*/
136 #define ADD_SOURCE_DIALOG "source_paths_dialog"
137 #define SOURCE_ENTRY "src_entry"
138 #define SOURCE_LIST "src_clist"
139 #define ADD_BUTTON "add_button"
140 #define REMOVE_BUTTON "remove_button"
141 #define UP_BUTTON "up_button"
142 #define DOWN_BUTTON "down_button"
145 *---------------------------------------------------------------------------*/
147 #define RUN_PROGRAM_URI "run_program_uri"
148 #define RUN_PROGRAM_ARGS "run_program_args"
149 #define RUN_PROGRAM_DIR "run_program_directory"
150 #define RUN_PROGRAM_ENV "run_program_environment"
151 #define RUN_PROGRAM_NEED_TERM "run_program_need_terminal"
153 #define RUN_PROGRAM_ACTION_GROUP "ActionGroupRun"
154 #define RUN_PROGRAM_PARAMETER_ACTION "ActionProgramParameters"
156 static void attach_process_clear (AttachProcess
* ap
, gint ClearRequest
);
159 *---------------------------------------------------------------------------*/
161 /* This functions get all directories of the current project containing
162 * static or shared library. Perhaps a more reliable way to find these
163 * directories is to really get the directories of all source files */
166 get_source_directories (AnjutaPlugin
*plugin
)
169 GList
*node
, *search_dirs
= NULL
;
170 GList
*slibs_dirs
= NULL
;
171 GList
*libs_dirs
= NULL
;
175 cwd
= g_get_current_dir();
176 search_dirs
= g_list_prepend (search_dirs
, gnome_vfs_get_uri_from_local_path(cwd
));
179 /* Check if a project is already open */
180 anjuta_shell_get_value (plugin
->shell
, "project_root_uri", &value
, NULL
);
182 /* Set source file search directories */
183 if (g_value_get_string (&value
) != NULL
)
185 IAnjutaProjectManager
*pm
;
186 pm
= anjuta_shell_get_interface (plugin
->shell
,
187 IAnjutaProjectManager
, NULL
);
191 ianjuta_project_manager_get_targets (pm
,
192 IANJUTA_PROJECT_MANAGER_TARGET_SHAREDLIB
,
195 ianjuta_project_manager_get_targets (pm
,
196 IANJUTA_PROJECT_MANAGER_TARGET_STATICLIB
,
200 slibs_dirs
= g_list_reverse (slibs_dirs
);
201 libs_dirs
= g_list_reverse (libs_dirs
);
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
);
216 dir_uri
= g_path_get_dirname (node
->data
);
217 search_dirs
= g_list_prepend (search_dirs
, dir_uri
);
218 node
= g_list_next (node
);
221 g_list_foreach (slibs_dirs
, (GFunc
)g_free
, NULL
);
222 g_list_free (slibs_dirs
);
223 g_list_foreach (libs_dirs
, (GFunc
)g_free
, NULL
);
224 g_list_free (libs_dirs
);
226 return g_list_reverse (search_dirs
);
230 free_source_directories (GList
*dirs
)
232 g_list_foreach (dirs
, (GFunc
)g_free
, NULL
);
236 /* Callback for saving session
237 *---------------------------------------------------------------------------*/
240 on_session_save (AnjutaShell
*shell
, AnjutaSessionPhase phase
, AnjutaSession
*session
, DmaStart
*self
)
242 if (phase
!= ANJUTA_SESSION_PHASE_NORMAL
)
245 anjuta_session_set_string_list (session
, "Debugger", "Source directories", self
->source_dirs
);
246 anjuta_session_set_int (session
, "Debugger", "Stop at beginning", self
->stop_at_beginning
+ 1);
249 static void on_session_load (AnjutaShell
*shell
, AnjutaSessionPhase phase
, AnjutaSession
*session
, DmaStart
*self
)
251 gint stop_at_beginning
;
253 if (phase
!= ANJUTA_SESSION_PHASE_NORMAL
)
256 /* Initialize source_dirs */
257 if (self
->source_dirs
!= NULL
)
259 g_list_foreach (self
->source_dirs
, (GFunc
)g_free
, NULL
);
260 g_list_free (self
->source_dirs
);
262 self
->source_dirs
= anjuta_session_get_string_list (session
, "Debugger", "Source directories");
264 stop_at_beginning
= anjuta_session_get_int (session
, "Debugger", "Stop at beginning");
265 if (stop_at_beginning
== 0)
266 self
->stop_at_beginning
= TRUE
; /* Default value */
268 self
->stop_at_beginning
= stop_at_beginning
- 1;
271 /* Attach to process private functions
272 *---------------------------------------------------------------------------*/
274 static AttachProcess
*
275 attach_process_new ()
278 ap
= g_new0 (AttachProcess
, 1);
279 attach_process_clear (ap
, CLEAR_INITIAL
);
284 attach_process_clear (AttachProcess
* ap
, gint ClearRequest
)
289 switch (ClearRequest
)
295 g_free (ap
->ps_output
);
298 ap
->ps_output
= NULL
;
302 switch (ClearRequest
)
308 ap
->iter_stack
= NULL
;
309 ap
->iter_stack_level
= -1;
310 ap
->num_spaces_to_skip
= -1;
314 switch (ClearRequest
)
319 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (ap
->treeview
));
320 gtk_tree_store_clear (GTK_TREE_STORE (model
));
324 if (ClearRequest
== CLEAR_FINAL
)
326 gtk_widget_destroy (ap
->dialog
);
331 static inline gchar
*
332 skip_spaces (gchar
*pos
)
339 static inline gchar
*
340 skip_token (gchar
*pos
)
349 skip_token_and_spaces (gchar
*pos
)
351 pos
= skip_token (pos
);
352 return skip_spaces (pos
);
356 iter_stack_push_new (AttachProcess
*ap
, GtkTreeStore
*store
)
358 GtkTreeIter
*new_iter
, *top_iter
;
359 new_iter
= g_new (GtkTreeIter
, 1);
360 top_iter
= (GtkTreeIter
*) (g_slist_nth_data (ap
->iter_stack
, 0));
362 g_slist_prepend (ap
->iter_stack
, (gpointer
) (new_iter
));
363 gtk_tree_store_append (store
, new_iter
, top_iter
);
364 ap
->iter_stack_level
++;
369 iter_stack_pop (AttachProcess
*ap
)
371 if (ap
->iter_stack_level
< 0)
375 (GtkTreeIter
*) (g_slist_nth_data (ap
->iter_stack
, 0));
377 g_slist_delete_link (ap
->iter_stack
, ap
->iter_stack
);
379 ap
->iter_stack_level
--;
384 iter_stack_clear (AttachProcess
*ap
)
386 while (iter_stack_pop (ap
));
390 calc_depth_and_get_iter (AttachProcess
*ap
, GtkTreeStore
*store
,
391 GtkTreeIter
**iter
, gchar
*pos
)
394 guint num_spaces
, depth
, i
;
400 num_spaces
= pos
- orig_pos
;
402 if (ap
->process_tree
)
404 if (ap
->num_spaces_to_skip
< 0)
406 // first process to be inserted
407 ap
->num_spaces_to_skip
= num_spaces
;
408 ap
->num_spaces_per_level
= -1;
409 *iter
= iter_stack_push_new (ap
, store
);
413 if (ap
->num_spaces_per_level
< 0)
415 if (num_spaces
== ap
->num_spaces_to_skip
)
417 // num_spaces_per_level still unknown
419 *iter
= iter_stack_push_new (ap
, store
);
423 // first time at level 1
424 ap
->num_spaces_per_level
=
425 num_spaces
- ap
->num_spaces_to_skip
;
426 *iter
= iter_stack_push_new (ap
, store
);
431 depth
= (num_spaces
- ap
->num_spaces_to_skip
) /
432 ap
->num_spaces_per_level
;
433 if (depth
== ap
->iter_stack_level
)
437 *iter
= iter_stack_push_new (ap
, store
);
440 if (depth
== ap
->iter_stack_level
+ 1)
441 *iter
= iter_stack_push_new (ap
, store
);
443 if (depth
< ap
->iter_stack_level
)
445 // jump some levels backward
446 depth
= ap
->iter_stack_level
- depth
;
447 for (i
= 0; i
<= depth
; i
++)
449 *iter
= iter_stack_push_new (ap
, store
);
453 // should never get here
454 g_warning("Unknown error");
456 *iter
= iter_stack_push_new (ap
, store
);
464 *iter
= iter_stack_push_new (ap
, store
);
471 skip_path (gchar
*pos
)
473 /* can't use g_path_get_basename() - wouldn't work for a processes
474 started with parameters containing '/' */
475 gchar c
, *final_pos
= pos
;
477 if (*pos
== G_DIR_SEPARATOR
)
481 if (c
== G_DIR_SEPARATOR
)
487 if (c
== ' ' || c
== '\0')
498 remove_params (gchar
*pos
)
509 attach_process_add_line (AttachProcess
*ap
, GtkTreeStore
*store
, gchar
*line
)
511 gchar
*pid
, *user
, *start
, *command
, *tmp
;
515 pid
= skip_spaces (line
); // skip leading spaces
516 user
= skip_token_and_spaces (pid
); // skip PID
517 start
= skip_token_and_spaces (user
); // skip USER
518 tmp
= skip_token (start
); // skip START (do not skip spaces)
520 command
= calc_depth_and_get_iter (ap
, store
, &iter
, tmp
);
524 command
= skip_path (command
);
529 remove_params(command
);
532 gtk_tree_store_set (store
, iter
,
536 COMMAND_COLUMN
, command
,
541 attach_process_review (AttachProcess
*ap
)
543 gchar
*ps_output
, *begin
, *end
;
547 g_return_if_fail (ap
);
548 g_return_if_fail (ap
->ps_output
);
549 store
= GTK_TREE_STORE (gtk_tree_view_get_model
550 (GTK_TREE_VIEW (ap
->treeview
)));
551 g_return_if_fail (store
);
553 ps_output
= g_strdup (ap
->ps_output
);
558 while (*end
&& *end
!= '\n') end
++;
559 if (++line_num
> 2) // skip description line & process 'init'
562 attach_process_add_line (ap
, store
, begin
);
568 iter_stack_clear (ap
);
569 gtk_tree_view_expand_all (GTK_TREE_VIEW (ap
->treeview
));
573 attach_process_update (AttachProcess
* ap
)
575 gchar
*tmp
, *tmp1
, *cmd
;
581 g_return_if_fail (ap
);
582 store
= GTK_TREE_STORE (gtk_tree_view_get_model
583 (GTK_TREE_VIEW (ap
->treeview
)));
584 g_return_if_fail (store
);
586 if (anjuta_util_prog_is_installed ("ps", TRUE
) == FALSE
)
589 tmp
= anjuta_util_get_a_tmp_file ();
590 #if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__)
591 cmd
= g_strconcat ("ps axw -o pid,user,lstart,args > ", tmp
, NULL
);
593 cmd
= g_strconcat ("ps axw -H -o pid,user,start_time,args > ", tmp
, NULL
);
595 shell
= anjuta_util_user_shell ();
599 execlp (shell
, shell
, "-c", cmd
, NULL
);
603 anjuta_util_dialog_error_system (NULL
, errno
,
604 _("Unable to execute: %s."), cmd
);
609 waitpid (ch_pid
, NULL
, 0);
612 result
= g_file_get_contents (tmp
, &tmp1
, NULL
, NULL
);
617 anjuta_util_dialog_error_system (NULL
, errno
,
618 _("Unable to open the file: %s\n"),
623 attach_process_clear (ap
, CLEAR_UPDATE
);
624 ap
->ps_output
= anjuta_util_convert_to_utf8 (tmp1
);
628 attach_process_review (ap
);
633 on_selection_changed (GtkTreeSelection
*selection
, AttachProcess
*ap
)
638 g_return_if_fail (ap
);
639 if (gtk_tree_selection_get_selected (selection
, &model
, &iter
))
642 gtk_tree_model_get (model
, &iter
, PID_COLUMN
, &text
, -1);
643 ap
->pid
= atoi (text
);
644 gtk_dialog_set_response_sensitive (GTK_DIALOG (ap
->dialog
),
645 GTK_RESPONSE_OK
, TRUE
);
649 gtk_dialog_set_response_sensitive (GTK_DIALOG (ap
->dialog
),
650 GTK_RESPONSE_OK
, FALSE
);
656 on_delete_event (GtkWidget
*dialog
, GdkEvent
*event
, AttachProcess
*ap
)
658 g_return_val_if_fail (ap
, FALSE
);
659 attach_process_clear (ap
, CLEAR_FINAL
);
664 sort_pid (GtkTreeModel
*model
, GtkTreeIter
*a
, GtkTreeIter
*b
,
670 gtk_tree_model_get (model
, a
, PID_COLUMN
, &nptr
, -1);
673 gtk_tree_model_get (model
, b
, PID_COLUMN
, &nptr
, -1);
680 on_toggle_hide_paths (GtkToggleButton
*togglebutton
, AttachProcess
* ap
)
682 ap
->hide_paths
= gtk_toggle_button_get_active (togglebutton
);
683 attach_process_clear (ap
, CLEAR_REVIEW
);
684 attach_process_review (ap
);
688 on_toggle_hide_params (GtkToggleButton
*togglebutton
, AttachProcess
* ap
)
690 ap
->hide_params
= gtk_toggle_button_get_active (togglebutton
);
691 attach_process_clear (ap
, CLEAR_REVIEW
);
692 attach_process_review (ap
);
696 on_toggle_process_tree (GtkToggleButton
*togglebutton
, AttachProcess
* ap
)
698 ap
->process_tree
= gtk_toggle_button_get_active (togglebutton
);
699 attach_process_clear (ap
, CLEAR_REVIEW
);
700 attach_process_review (ap
);
704 attach_process_show (AttachProcess
* ap
, GtkWindow
*parent
)
709 GtkCellRenderer
*renderer
;
710 GtkTreeSelection
*selection
;
711 GtkCheckButton
*checkb_hide_paths
;
712 GtkCheckButton
*checkb_hide_params
;
713 GtkCheckButton
*checkb_process_tree
;
715 pid_t selected_pid
= -1;
717 g_return_val_if_fail (ap
!= NULL
, -1);
721 gxml
= glade_xml_new (GLADE_FILE
, "attach_process_dialog", NULL
);
722 ap
->dialog
= glade_xml_get_widget (gxml
, "attach_process_dialog");
723 ap
->treeview
= glade_xml_get_widget (gxml
, "attach_process_tv");
724 checkb_hide_paths
= GTK_CHECK_BUTTON (
725 glade_xml_get_widget (gxml
, "checkb_hide_paths"));
726 checkb_hide_params
= GTK_CHECK_BUTTON (
727 glade_xml_get_widget (gxml
, "checkb_hide_params"));
728 checkb_process_tree
= GTK_CHECK_BUTTON (
729 glade_xml_get_widget (gxml
, "checkb_process_tree"));
730 g_object_unref (gxml
);
732 view
= GTK_TREE_VIEW (ap
->treeview
);
733 store
= gtk_tree_store_new (COLUMNS_NB
,
738 gtk_tree_view_set_model (view
, GTK_TREE_MODEL (store
));
739 gtk_tree_selection_set_mode (gtk_tree_view_get_selection (view
),
740 GTK_SELECTION_SINGLE
);
741 g_object_unref (G_OBJECT (store
));
743 renderer
= gtk_cell_renderer_text_new ();
745 for (i
= PID_COLUMN
; i
< COLUMNS_NB
; i
++) {
746 GtkTreeViewColumn
*column
;
748 column
= gtk_tree_view_column_new_with_attributes (column_names
[i
],
749 renderer
, "text", i
, NULL
);
750 gtk_tree_view_column_set_sort_column_id(column
, i
);
751 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
752 gtk_tree_view_append_column (view
, column
);
753 if (i
== COMMAND_COLUMN
)
754 gtk_tree_view_set_expander_column(view
, column
);
756 gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store
), PID_COLUMN
,
757 sort_pid
, NULL
, NULL
);
758 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store
),
759 START_COLUMN
, GTK_SORT_DESCENDING
);
761 ap
->hide_paths
= gtk_toggle_button_get_active (
762 GTK_TOGGLE_BUTTON (checkb_hide_paths
));
763 ap
->hide_params
= gtk_toggle_button_get_active (
764 GTK_TOGGLE_BUTTON (checkb_hide_params
));
765 ap
->process_tree
= gtk_toggle_button_get_active (
766 GTK_TOGGLE_BUTTON (checkb_process_tree
));
768 attach_process_update (ap
);
770 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (ap
->treeview
));
771 g_signal_connect (G_OBJECT (selection
), "changed",
772 G_CALLBACK (on_selection_changed
), ap
);
773 g_signal_connect (G_OBJECT (ap
->dialog
), "delete_event",
774 G_CALLBACK (on_delete_event
), ap
);
775 g_signal_connect (GTK_OBJECT (checkb_hide_paths
), "toggled",
776 G_CALLBACK (on_toggle_hide_paths
), ap
);
777 g_signal_connect (GTK_OBJECT (checkb_hide_params
), "toggled",
778 G_CALLBACK (on_toggle_hide_params
), ap
);
779 g_signal_connect (GTK_OBJECT (checkb_process_tree
), "toggled",
780 G_CALLBACK (on_toggle_process_tree
), ap
);
783 gtk_window_set_transient_for (GTK_WINDOW (ap
->dialog
),
784 GTK_WINDOW (parent
));
785 /* gtk_widget_show (ap->dialog); */
786 res
= gtk_dialog_run (GTK_DIALOG (ap
->dialog
));
787 while (res
== GTK_RESPONSE_APPLY
)
789 attach_process_update (ap
);
790 res
= gtk_dialog_run (GTK_DIALOG (ap
->dialog
));
792 if (res
== GTK_RESPONSE_OK
)
794 selected_pid
= ap
->pid
;
796 attach_process_clear (ap
, CLEAR_FINAL
);
801 attach_process_destroy (AttachProcess
* ap
)
803 g_return_if_fail (ap
);
807 /* Load file private functions
808 *---------------------------------------------------------------------------*/
811 show_parameters_dialog (DmaStart
*this)
816 ui
= anjuta_shell_get_ui (ANJUTA_PLUGIN (this->plugin
)->shell
, NULL
);
817 action
= anjuta_ui_get_action (ui
, RUN_PROGRAM_ACTION_GROUP
, RUN_PROGRAM_PARAMETER_ACTION
);
820 gtk_action_activate (action
);
825 start_target (DmaStart
*this)
831 gboolean run_in_terminal
;
833 anjuta_shell_get (ANJUTA_PLUGIN (this->plugin
)->shell
,
834 RUN_PROGRAM_DIR
, G_TYPE_STRING
, &dir_uri
,
835 RUN_PROGRAM_ARGS
, G_TYPE_STRING
, &args
,
836 RUN_PROGRAM_ENV
, G_TYPE_STRV
, &env
,
837 RUN_PROGRAM_NEED_TERM
, G_TYPE_BOOLEAN
, &run_in_terminal
,
842 dir
= gnome_vfs_get_local_path_from_uri (dir_uri
);
850 dma_queue_set_working_directory (this->debugger
, dir
);
853 dma_queue_set_environment (this->debugger
, env
);
856 dma_queue_start (this->debugger
, args
, run_in_terminal
, FALSE
);
864 load_target (DmaStart
*this, const gchar
*target
)
869 mime_type
= gnome_vfs_get_mime_type ((const gchar
*)target
);
870 if (mime_type
== NULL
)
872 anjuta_util_dialog_error(GTK_WINDOW (this->plugin
->shell
),
873 _("Unable to open %s. Debugger cannot start."), target
);
876 filename
= gnome_vfs_get_local_path_from_uri (target
);
878 dma_queue_load (this->debugger
, filename
, mime_type
, this->source_dirs
);
883 return start_target (this);
887 on_build_finished (GObject
*builder
, IAnjutaBuilderHandle handle
, GError
*err
, gpointer user_data
)
889 DmaStart
*this = (DmaStart
*)user_data
;
893 /* Up to date, start debugger */
894 load_target (this, this->build_target
);
897 g_free (this->build_target
);
898 this->build_target
= NULL
;
902 on_is_built_finished (GObject
*builder
, IAnjutaBuilderHandle handle
, GError
*err
, gpointer user_data
)
904 DmaStart
*this = (DmaStart
*)user_data
;
908 /* Up to date, start debugger */
909 load_target (this, this->build_target
);
911 else if (err
->code
== IANJUTA_BUILDER_FAILED
)
913 /* Target is not up to date */
914 this->build_handle
= ianjuta_builder_build (IANJUTA_BUILDER (builder
), this->build_target
, on_build_finished
, this, NULL
);
918 g_free (this->build_target
);
919 this->build_target
= NULL
;
923 check_target (DmaStart
*this, const gchar
*target
)
925 IAnjutaBuilder
*builder
;
927 builder
= anjuta_shell_get_interface (this->plugin
->shell
, IAnjutaBuilder
, NULL
);
930 if (this->build_target
)
932 /* a build operation is currently running */
933 if (strcmp (this->build_target
, target
) == 0)
935 /* It is the same one, just ignore */
940 /* Cancel old operation */
941 ianjuta_builder_cancel (builder
, this->build_handle
, NULL
);
945 this->build_target
= g_strdup (target
);
947 /* Check if target is up to date */
948 this->build_handle
= ianjuta_builder_is_built (builder
, target
, on_is_built_finished
, this, NULL
);
949 return this->build_handle
!= 0;
953 /* Unable to build target, just launch debugger */
954 return load_target (this, target
);
959 dma_start_load_and_start_uri (DmaStart
*this, const gchar
*target
)
961 GnomeVFSURI
*vfs_uri
;
963 if (!dma_quit_debugger (this)) return FALSE
;
965 vfs_uri
= gnome_vfs_uri_new (target
);
966 g_return_val_if_fail (vfs_uri
!= NULL
, TRUE
);
967 if (!gnome_vfs_uri_is_local (vfs_uri
)) return FALSE
;
968 gnome_vfs_uri_unref (vfs_uri
);
970 return check_target (this, target
);
974 *---------------------------------------------------------------------------*/
977 on_add_uri_in_model (gpointer data
, gpointer user_data
)
979 GtkListStore
* model
= (GtkListStore
*)user_data
;
983 local
= gnome_vfs_get_local_path_from_uri ((const char *)data
);
984 gtk_list_store_append (model
, &iter
);
985 gtk_list_store_set (model
, &iter
, 0, local
, -1);
990 on_add_source_in_list (GtkTreeModel
*model
, GtkTreePath
*path
, GtkTreeIter
*iter
, gpointer user_data
)
992 GList
** list
= (GList
**)user_data
;
996 gtk_tree_model_get (model
, iter
, 0, &dir
, -1);
997 uri
= gnome_vfs_get_uri_from_local_path (dir
);
998 *list
= g_list_prepend (*list
, uri
);
1005 on_source_add_button (GtkButton
*button
, AddSourceDialog
*dlg
)
1010 path
= gtk_file_chooser_get_filename (dlg
->entry
);
1011 if ((path
!= NULL
) && (*path
!= '\0'))
1013 gtk_list_store_append (dlg
->model
, &iter
);
1014 gtk_list_store_set (dlg
->model
, &iter
, 0, path
, -1);
1019 on_source_remove_button (GtkButton
*button
, AddSourceDialog
*dlg
)
1022 GtkTreeSelection
* sel
;
1024 sel
= gtk_tree_view_get_selection (dlg
->tree
);
1025 if (gtk_tree_selection_get_selected (sel
, NULL
, &iter
))
1027 gtk_list_store_remove (dlg
->model
, &iter
);
1032 on_source_up_button (GtkButton
*button
, AddSourceDialog
*dlg
)
1035 GtkTreeSelection
* sel
;
1037 sel
= gtk_tree_view_get_selection (dlg
->tree
);
1038 if (gtk_tree_selection_get_selected (sel
, NULL
, &iter
))
1042 path
= gtk_tree_model_get_path(GTK_TREE_MODEL (dlg
->model
), &iter
);
1043 if (gtk_tree_path_prev(path
))
1047 gtk_tree_model_get_iter(GTK_TREE_MODEL (dlg
->model
), &pos
, path
);
1048 gtk_list_store_move_before (dlg
->model
, &iter
, &pos
);
1054 on_source_down_button (GtkButton
*button
, AddSourceDialog
*dlg
)
1057 GtkTreeSelection
* sel
;
1059 sel
= gtk_tree_view_get_selection (dlg
->tree
);
1060 if (gtk_tree_selection_get_selected (sel
, NULL
, &iter
))
1062 GtkTreeIter pos
= iter
;
1064 if (gtk_tree_model_iter_next (GTK_TREE_MODEL (dlg
->model
), &pos
))
1066 gtk_list_store_move_after (dlg
->model
, &iter
, &pos
);
1072 add_source_show (DmaStart
*this)
1074 AddSourceDialog dlg
;
1078 GtkCellRenderer
*renderer
;
1079 GtkTreeViewColumn
*column
;
1082 parent
= GTK_WINDOW (this->plugin
->shell
);
1083 gxml
= glade_xml_new (GLADE_FILE
, ADD_SOURCE_DIALOG
, NULL
);
1086 anjuta_util_dialog_error(parent
, _("Missing file %s"), GLADE_FILE
);
1090 widget
= glade_xml_get_widget (gxml
, ADD_SOURCE_DIALOG
);
1091 dlg
.tree
= GTK_TREE_VIEW (glade_xml_get_widget (gxml
, SOURCE_LIST
));
1092 dlg
.entry
= GTK_FILE_CHOOSER (glade_xml_get_widget (gxml
, SOURCE_ENTRY
));
1094 /* Connect signals */
1095 button
= G_OBJECT (glade_xml_get_widget (gxml
, ADD_BUTTON
));
1096 g_signal_connect (button
, "clicked", G_CALLBACK (on_source_add_button
), &dlg
);
1097 button
= G_OBJECT (glade_xml_get_widget (gxml
, REMOVE_BUTTON
));
1098 g_signal_connect (button
, "clicked", G_CALLBACK (on_source_remove_button
), &dlg
);
1099 button
= G_OBJECT (glade_xml_get_widget (gxml
, UP_BUTTON
));
1100 g_signal_connect (button
, "clicked", G_CALLBACK (on_source_up_button
), &dlg
);
1101 button
= G_OBJECT (glade_xml_get_widget (gxml
, DOWN_BUTTON
));
1102 g_signal_connect (button
, "clicked", G_CALLBACK (on_source_down_button
), &dlg
);
1104 g_object_unref (gxml
);
1106 renderer
= gtk_cell_renderer_text_new ();
1107 column
= gtk_tree_view_column_new_with_attributes (_("Path"), renderer
, "text", 0, NULL
);
1108 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
1109 gtk_tree_view_append_column (dlg
.tree
, column
);
1110 gtk_tree_view_set_expander_column(dlg
.tree
, column
);
1112 dlg
.model
= gtk_list_store_new (1, GTK_TYPE_STRING
);
1113 gtk_tree_view_set_model (dlg
.tree
, GTK_TREE_MODEL (dlg
.model
));
1115 gtk_window_set_transient_for (GTK_WINDOW (widget
), parent
);
1117 /* Initialize source path list */
1118 g_list_foreach (this->source_dirs
, on_add_uri_in_model
, dlg
.model
);
1123 gint response
= gtk_dialog_run (GTK_DIALOG (widget
));
1127 case GTK_RESPONSE_DELETE_EVENT
:
1128 case GTK_RESPONSE_CLOSE
:
1129 g_list_foreach (this->source_dirs
, (GFunc
)g_free
, NULL
);
1130 g_list_free (this->source_dirs
);
1131 this->source_dirs
= NULL
;
1132 gtk_tree_model_foreach (GTK_TREE_MODEL (dlg
.model
), on_add_source_in_list
, &this->source_dirs
);
1133 this->source_dirs
= g_list_reverse (this->source_dirs
);
1135 case GTK_RESPONSE_CANCEL
:
1136 gtk_list_store_clear (dlg
.model
);
1137 g_list_foreach (this->source_dirs
, on_add_uri_in_model
, dlg
.model
);
1144 gtk_widget_destroy (widget
);
1148 *---------------------------------------------------------------------------*/
1151 dma_quit_debugger (DmaStart
* this)
1153 if (dma_debugger_queue_get_state (this->debugger
) > IANJUTA_DEBUGGER_PROGRAM_LOADED
)
1155 gchar
*msg
= _("The program is running.\n"
1156 "Do you still want to stop the debugger?");
1158 if (!anjuta_util_dialog_boolean_question (GTK_WINDOW (this->plugin
->shell
), msg
)) return FALSE
;
1161 dma_queue_interrupt (this->debugger
);
1162 dma_queue_quit (this->debugger
);
1168 dma_add_source_path (DmaStart
*self
)
1170 add_source_show (self
);
1174 dma_attach_to_process (DmaStart
* this)
1178 AttachProcess
*attach_process
= NULL
;
1180 if (!dma_quit_debugger (this)) return;
1182 parent
= GTK_WINDOW (ANJUTA_PLUGIN (this->plugin
)->shell
);
1183 attach_process
= attach_process_new();
1185 selected_pid
= attach_process_show (attach_process
, parent
);
1186 if (selected_pid
> 0)
1188 long lpid
= selected_pid
;
1191 search_dirs
= get_source_directories (this->plugin
);
1193 dma_queue_attach (this->debugger
, lpid
, this->source_dirs
);
1194 free_source_directories (search_dirs
);
1196 attach_process_destroy(attach_process
);
1200 dma_run_target (DmaStart
*this)
1204 anjuta_shell_get (ANJUTA_PLUGIN (this->plugin
)->shell
,
1205 RUN_PROGRAM_URI
, G_TYPE_STRING
, &target
, NULL
);
1209 /* Launch parameter dialog to get a target name */
1210 show_parameters_dialog (this);
1211 anjuta_shell_get (ANJUTA_PLUGIN (this->plugin
)->shell
,
1212 RUN_PROGRAM_URI
, G_TYPE_STRING
, &target
, NULL
);
1213 /* No target set by user */
1214 if (target
== NULL
) return FALSE
;
1217 if (!dma_start_load_and_start_uri (this, target
)) return FALSE
;
1223 /* Constructor & Destructor
1224 *---------------------------------------------------------------------------*/
1227 dma_start_new (DebugManagerPlugin
*plugin
)
1231 self
= g_new0 (DmaStart
, 1);
1233 self
->plugin
= ANJUTA_PLUGIN (plugin
);
1234 self
->debugger
= dma_debug_manager_get_queue (plugin
);
1235 self
->source_dirs
= NULL
;
1236 self
->build_target
= NULL
;
1238 g_signal_connect (self
->plugin
->shell
, "save-session",
1239 G_CALLBACK (on_session_save
), self
);
1240 g_signal_connect (self
->plugin
->shell
, "load-session",
1241 G_CALLBACK (on_session_load
), self
);
1247 dma_start_free (DmaStart
*this)
1249 g_signal_handlers_disconnect_by_func (this->plugin
->shell
, G_CALLBACK (on_session_save
), this);
1250 g_signal_handlers_disconnect_by_func (this->plugin
->shell
, G_CALLBACK (on_session_load
), this);
1251 g_list_foreach (this->source_dirs
, (GFunc
)g_free
, NULL
);
1252 g_list_free (this->source_dirs
);