diff --git a/debugger/ChangeLog b/debugger/ChangeLog index 7413c4c02..0a8f91b55 100644 --- a/debugger/ChangeLog +++ b/debugger/ChangeLog @@ -1,3 +1,7 @@ +29-01-2022 Pascal Martin + + * add remote and cross development debugging mode. + 14-06-2012 Alexander Petukhov * fixed reverse children order in watch/autos diff --git a/debugger/README b/debugger/README index d11621033..047c88747 100644 --- a/debugger/README +++ b/debugger/README @@ -31,6 +31,7 @@ Features * Saving debug session data in a Geany project (can be switched through settings) * Double or single panel modes * Hotkeys +* Remote and cross development debug sessions. Usage ----- diff --git a/debugger/src/dbm_gdb.c b/debugger/src/dbm_gdb.c index a6f6e6559..1732c1b0b 100644 --- a/debugger/src/dbm_gdb.c +++ b/debugger/src/dbm_gdb.c @@ -79,7 +79,11 @@ enum sr { static dbg_callbacks* dbg_cbs; /* GDB command line arguments*/ -static const gchar *gdb_args[] = { "gdb", "-i=mi", NULL }; +static const gchar *gdb_args_local[] = { "gdb", "-i=mi", NULL }; +static const gchar *gdb_args_multi[] = { "gdb-multiarch", "-i=mi", NULL }; + +static gboolean remote_session = FALSE; +static gboolean detected_prompt = FALSE; /* Async commands */ /* GDB pid*/ static GPid gdb_pid = 0; @@ -197,6 +201,18 @@ static void on_gdb_exit(GPid pid, gint status, gpointer data) dbg_cbs->set_exited(0); } +static void discard_until_prompt (void) +{ + gchar *line = NULL; + + while (G_IO_STATUS_NORMAL == g_io_channel_read_line(gdb_ch_out, &line, NULL, NULL, NULL)) + { + int prompted = !strcmp(GDB_PROMPT, line); + g_free(line); + if (prompted) return; + } +} + /* * reads gdb_out until "(gdb)" prompt met */ @@ -209,12 +225,14 @@ static GList* read_until_prompt(void) while (G_IO_STATUS_NORMAL == g_io_channel_read_line(gdb_ch_out, &line, NULL, &terminator, NULL)) { if (!strcmp(GDB_PROMPT, line)) + { + g_free (line); break; + } line[terminator] = '\0'; lines = g_list_prepend (lines, line); } - return g_list_reverse(lines); } @@ -319,7 +337,6 @@ static gboolean on_read_async_output(GIOChannel * src, GIOCondition cond, gpoint { /* got some result */ - GList *lines; GList *commands = (GList*)data; if (gdb_id_out) @@ -328,9 +345,7 @@ static gboolean on_read_async_output(GIOChannel * src, GIOCondition cond, gpoint gdb_id_out = 0; } - lines = read_until_prompt(); - g_list_foreach(lines, (GFunc)g_free, NULL); - g_list_free (lines); + discard_until_prompt(); if (!strcmp(record->klass, "done")) { @@ -369,7 +384,10 @@ static gboolean on_read_async_output(GIOChannel * src, GIOCondition cond, gpoint update_files(); /* -exec-run */ - exec_async_command("-exec-run"); + if (remote_session) + exec_async_command("-exec-continue"); + else + exec_async_command("-exec-run"); } } else @@ -419,6 +437,21 @@ static gboolean on_read_from_gdb(GIOChannel * src, GIOCondition cond, gpointer d if (G_IO_STATUS_NORMAL != g_io_channel_read_line(src, &line, NULL, &length, NULL)) return TRUE; + /* When the target program stops, gdb sometimes sends the "(gdb)" prompt + * before sending in the "stopped" event. There might be some timing.. + * It is important to make sure that we received the prompt before + * issuing any new command, or else a leftover prompt will cause + * the next commands to be off by one prompt, and nothing works. + * The solution is to detect the prompt asynchronously. When the target + * is stopped, wait for the prompt only if it has not been received yet. + */ + if (!strcmp(GDB_PROMPT, line)) + { + g_free(line); + detected_prompt = TRUE; + return TRUE; + } + record = gdb_mi_record_parse(line); if (! record || record->type != GDB_MI_TYPE_PROMPT) @@ -475,6 +508,8 @@ static gboolean on_read_from_gdb(GIOChannel * src, GIOCondition cond, gpointer d gdb_id_out = 0; } + if (!detected_prompt) discard_until_prompt(); + /* looking for a reason to stop */ if ((reason = gdb_mi_result_var(record->first, "reason", GDB_MI_VAL_STRING)) != NULL) { @@ -575,15 +610,18 @@ static gboolean on_read_from_gdb(GIOChannel * src, GIOCondition cond, gpointer d } /* reading until prompt */ - lines = read_until_prompt(); - for (iter = lines; iter; iter = iter->next) - { - gchar *l = (gchar*)iter->data; - if (strcmp(l, GDB_PROMPT)) - colorize_message(l); - g_free(l); + if (!detected_prompt) + { + lines = read_until_prompt(); + for (iter = lines; iter; iter = iter->next) + { + gchar *l = (gchar*)iter->data; + if (strcmp(l, GDB_PROMPT)) + colorize_message(l); + g_free(l); + } + g_list_free (lines); } - g_list_free (lines); /* send error message */ dbg_cbs->report_error(msg); @@ -610,6 +648,7 @@ static void exec_async_command(const gchar* command) gdb_input_write_line(command); /* connect read callback to the output chanel */ + detected_prompt = FALSE; gdb_id_out = g_io_add_watch(gdb_ch_out, G_IO_IN, on_read_from_gdb, NULL); } @@ -715,7 +754,7 @@ static gchar *escape_string(const gchar *str) /* * starts gdb, collects commands and start the first one */ -static gboolean run(const gchar* file, const gchar* commandline, GList* env, GList *witer, GList *biter, const gchar* terminal_device, dbg_callbacks* callbacks) +static gboolean run(gint dbgmode, const gchar* file, const gchar* commandline, GList* env, GList *witer, GList *biter, const gchar* terminal_device, dbg_callbacks* callbacks) { const gchar *exclude[] = { "LANG", NULL }; gchar **gdb_env = utils_copy_environment(exclude, "LANG", "C", NULL); @@ -726,9 +765,21 @@ static gboolean run(const gchar* file, const gchar* commandline, GList* env, GLi gchar *escaped; int bp_index; queue_item *item; + const gchar **gdb_args = gdb_args_local; dbg_cbs = callbacks; + remote_session = FALSE; + switch (dbgmode) + { + case 1: + remote_session = TRUE; + break; + case 2: + remote_session = TRUE; + gdb_args = gdb_args_multi; + } + /* spawn GDB */ if (!g_spawn_async_with_pipes(working_directory, (gchar**)gdb_args, gdb_env, GDB_SPAWN_FLAGS, NULL, @@ -778,12 +829,17 @@ static gboolean run(const gchar* file, const gchar* commandline, GList* env, GLi /* collect commands */ - /* loading file */ - escaped = escape_string(file); - command = g_strdup_printf("-file-exec-and-symbols \"%s\"", escaped); - commands = add_to_queue(commands, _("~\"Loading target file.\\n\""), command, _("Error loading file"), FALSE); - g_free(command); - g_free(escaped); + if (file && file[0]) /* File is optional in remote mode. */ + { + /* loading file (Only for symbols in remote mode) */ + const gchar *keyword = + remote_session ? "-file-symbol-file" : "-file-exec-and-symbols"; + escaped = escape_string(file); + command = g_strdup_printf("%s \"%s\"", keyword, escaped); + commands = add_to_queue(commands, _("~\"Loading target file.\\n\""), command, _("Error loading file"), FALSE); + g_free(command); + g_free(escaped); + } /* setting asyncronous mode */ commands = add_to_queue(commands, NULL, "-gdb-set target-async 1", _("Error configuring GDB"), FALSE); @@ -800,11 +856,27 @@ static gboolean run(const gchar* file, const gchar* commandline, GList* env, GLi g_free(command); /* set arguments */ - command = g_strdup_printf("-exec-arguments %s", commandline); + if (remote_session) + { + /* (remote sessions handle the progran name on debugserver side) */ + if (strchr(commandline, ':') == NULL) + { + /* Use gdbserver's default port. */ + command = g_strdup_printf("target remote %s:3278", commandline); + } + else + { + command = g_strdup_printf("target remote %s", commandline); + } + } + else + { + command = g_strdup_printf("-exec-arguments %s", commandline); + } commands = add_to_queue(commands, NULL, command, NULL, FALSE); g_free(command); - /* set passed evironment */ + /* set passed environment */ iter = env; while (iter) { diff --git a/debugger/src/dconfig.c b/debugger/src/dconfig.c index fe532fb92..cf62f3583 100644 --- a/debugger/src/dconfig.c +++ b/debugger/src/dconfig.c @@ -108,6 +108,7 @@ static void debug_load_from_keyfile(GKeyFile *keyfile) g_free(value); /* debugger */ tpage_set_debugger(value = g_key_file_get_string(keyfile, DEBUGGER_GROUP, "debugger", NULL)); + tpage_set_debugger_mode(value = g_key_file_get_string(keyfile, DEBUGGER_GROUP, "debugger_mode", NULL)); g_free(value); /* arguments */ tpage_set_commandline(value = g_key_file_get_string(keyfile, DEBUGGER_GROUP, "arguments", NULL)); @@ -186,6 +187,7 @@ static void save_to_keyfile(GKeyFile *keyfile) g_key_file_set_string(keyfile, DEBUGGER_GROUP, "target", tpage_get_target()); g_key_file_set_string(keyfile, DEBUGGER_GROUP, "debugger", tpage_get_debugger()); + g_key_file_set_string(keyfile, DEBUGGER_GROUP, "debugger_mode", tpage_get_debugger_mode()); g_key_file_set_string(keyfile, DEBUGGER_GROUP, "arguments", tpage_get_commandline()); /* environment */ @@ -404,6 +406,7 @@ static void config_set_debug_defaults(GKeyFile *keyfile) { g_key_file_set_string(keyfile, DEBUGGER_GROUP, "target", ""); g_key_file_set_string(keyfile, DEBUGGER_GROUP, "debugger", ""); + g_key_file_set_string(keyfile, DEBUGGER_GROUP, "debugger_mode", ""); g_key_file_set_string(keyfile, DEBUGGER_GROUP, "arguments", ""); g_key_file_set_integer(keyfile, DEBUGGER_GROUP, "envvar_count", 0); diff --git a/debugger/src/debug.c b/debugger/src/debug.c index 6a019c52d..595b252da 100644 --- a/debugger/src/debug.c +++ b/debugger/src/debug.c @@ -628,15 +628,8 @@ static void enable_sensitive_widgets(gboolean enable) * Debug state changed hanflers */ -/* - * called from debug module when debugger is being run - */ -static void on_debugger_run (void) +static void clear_stack (void) { - /* update debug state */ - debug_state = DBS_RUNNING; - - /* if curren instruction marker was set previously - remove it */ if (stack) { remove_stack_markers(); @@ -646,6 +639,20 @@ static void on_debugger_run (void) stree_remove_frames(); } +} + +/* + * called from debug module when debugger is being run + */ +static void on_debugger_run (void) +{ + /* update debug state */ + debug_state = DBS_RUNNING; + + /* Do not clear the stack yet. We do not want to loose the position + * if the target program stops at a new position with no source info. + * The previous position is better than some random editor cursor. + */ /* disable widgets */ enable_sensitive_widgets(FALSE); @@ -699,9 +706,35 @@ static void on_debugger_stopped (int thread_id) stree_set_active_thread_id(thread_id); /* get current stack trace and put in the tree view */ - stack = active_module->get_stack(); - stree_add (stack); - stree_select_first_frame(TRUE); + GList* new_stack = active_module->get_stack(); + if (new_stack) + { + /* Is this new stack referencing a source file that we can access? + * If not, it is better to keep the previous stack info, as it is + * closer to the truth than some random editor cursor. + */ + gboolean found_source = FALSE; + frame *current = (frame*)new_stack->data; + + if (current->have_source) + { + /* open current instruction position */ + found_source = editor_open_position_with_status(current->file, current->line); + } + + if (found_source) + { + /* clear previous stack tree view */ + clear_stack(); + stack = new_stack; + + stree_add (stack); + stree_select_first_frame(TRUE); + + /* add current instruction marker */ + add_stack_markers(); + } + } /* files */ files = active_module->get_files(); @@ -760,20 +793,6 @@ static void on_debugger_stopped (int thread_id) watches = active_module->get_watches(); update_variables(GTK_TREE_VIEW(wtree), NULL, watches); - if (stack) - { - frame *current = (frame*)stack->data; - - if (current->have_source) - { - /* open current instruction position */ - editor_open_position(current->file, current->line); - } - - /* add current instruction marker */ - add_stack_markers(); - } - /* enable widgets */ enable_sensitive_widgets(TRUE); @@ -1189,11 +1208,13 @@ void debug_run(void) { if (DBS_IDLE == debug_state) { + int mode; gchar *target, *commandline; GList *env, *watches, *breaks; target = g_strstrip(tpage_get_target()); - if (!strlen(target)) + mode = tpage_get_debug_mode_index(); + if ((!strlen(target)) && (!mode)) { g_free(target); return; @@ -1205,7 +1226,7 @@ void debug_run(void) /* init selected debugger module */ active_module = modules[tpage_get_debug_module_index()].module; - if(active_module->run(target, commandline, env, watches, breaks, ttyname(pty_slave), &callbacks)) + if(active_module->run(mode, target, commandline, env, watches, breaks, ttyname(pty_slave), &callbacks)) { /* set target page - readonly */ tpage_set_readonly(TRUE); diff --git a/debugger/src/debug_module.h b/debugger/src/debug_module.h index 77ce20d23..313e96b4e 100644 --- a/debugger/src/debug_module.h +++ b/debugger/src/debug_module.h @@ -105,7 +105,7 @@ typedef enum _break_set_activity { /* type to hold pointers to describe a debug module */ typedef struct _dbg_module { - gboolean (*run) (const gchar* target, const gchar* commandline, GList* env, GList *witer, GList *biter, const gchar* terminal_device, dbg_callbacks* callbacks); + gboolean (*run) (gint dbgmode, const gchar* target, const gchar* commandline, GList* env, GList *witer, GList *biter, const gchar* terminal_device, dbg_callbacks* callbacks); void (*restart) (void); void (*stop) (void); void (*resume) (void); diff --git a/debugger/src/stree.c b/debugger/src/stree.c index 5bbb4b34d..14ddc90e6 100644 --- a/debugger/src/stree.c +++ b/debugger/src/stree.c @@ -75,13 +75,14 @@ G_DEFINE_BOXED_TYPE(frame, frame, frame_ref, frame_unref) /* finds the iter for thread @thread_id */ static gboolean find_thread_iter (gint thread_id, GtkTreeIter *iter) { + static gboolean recursive = FALSE; gboolean found = FALSE; if (gtk_tree_model_get_iter_first(model, iter)) { do { - gint existing_thread_id; + gint existing_thread_id = -1; gtk_tree_model_get(model, iter, S_THREAD_ID, &existing_thread_id, -1); if (existing_thread_id == thread_id) @@ -90,6 +91,18 @@ static gboolean find_thread_iter (gint thread_id, GtkTreeIter *iter) while (! found && gtk_tree_model_iter_next(model, iter)); } + /* In cross development mode, gdb seems to experience issues with + * threads. It cannot use the native thread library and seems to + * not detect new threads. For the time being, any unknown thread + * is new.. + */ + if ((!found) && (!recursive)) + { + stree_add_thread (thread_id); + recursive = TRUE; + found = find_thread_iter (thread_id, iter); + recursive = FALSE; + } return found; } @@ -550,7 +563,6 @@ void stree_add_thread(int thread_id) void stree_remove_thread(int thread_id) { GtkTreeIter iter; - if (find_thread_iter (thread_id, &iter)) gtk_tree_store_remove(store, &iter); } diff --git a/debugger/src/tpage.c b/debugger/src/tpage.c index 9519d4ccc..ecceb6756 100644 --- a/debugger/src/tpage.c +++ b/debugger/src/tpage.c @@ -54,19 +54,21 @@ extern GeanyData *geany_data; /* root boxes border width */ #define ROOT_BORDER_WIDTH 10 -/* root boxes border width */ -#define BROWSE_BUTTON_WIDTH 65 - /* widgets */ /* target */ static GtkWidget *target_label = NULL; static GtkWidget *target_name = NULL; static GtkWidget *target_button_browse = NULL; +static GtkWidget *target_button_clear = NULL; /* debugger type */ static GtkWidget *debugger_label = NULL; static GtkWidget *debugger_cmb = NULL; +static GtkWidget *debugger_mode = NULL; + +static const gchar *debugger_supported_modes[] = {"Local Mode", "Remote Mode", "Cross Development Mode"}; +#define DEBUGGER_SUPPORTED_MODES_COUNT 3 /* argments */ static GtkWidget *args_frame = NULL; @@ -77,8 +79,8 @@ static GtkWidget *env_frame = NULL; /* widgets array for reference management when moving to another container */ static GtkWidget **widgets[] = { - &target_label, &target_name, &target_button_browse, - &debugger_label, &debugger_cmb, + &target_label, &target_name, &target_button_browse, &target_button_clear, + &debugger_label, &debugger_cmb, &debugger_mode, &args_frame, &env_frame, NULL @@ -132,6 +134,15 @@ static void on_target_browse_clicked(GtkButton *button, gpointer user_data) gtk_widget_destroy (dialog); } +/* + * target clear button clicked handler + */ +static void on_target_clear_clicked(GtkButton *button, gpointer user_data) +{ + gtk_entry_set_text(GTK_ENTRY(target_name), ""); + config_set_debug_changed(); +} + /* * packs widgets into page depending one tabbed mode state */ @@ -176,6 +187,7 @@ void tpage_pack_widgets(gboolean tabbed) gtk_box_pack_start(GTK_BOX(hbox), target_label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), target_name, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(hbox), target_button_browse, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), target_button_clear, FALSE, FALSE, 0); /* lower hbox */ #if GTK_CHECK_VERSION(3, 0, 0) @@ -211,6 +223,7 @@ void tpage_pack_widgets(gboolean tabbed) gtk_box_pack_start(GTK_BOX(hbox), debugger_label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), debugger_cmb, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(rbox), hbox, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(rbox), debugger_mode, FALSE, TRUE, 0); } else { @@ -246,6 +259,7 @@ void tpage_pack_widgets(gboolean tabbed) gtk_box_pack_start(GTK_BOX(hbox), target_label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), target_name, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(hbox), target_button_browse, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), target_button_clear, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(rbox), hbox, FALSE, FALSE, 0); /* arguments */ gtk_box_pack_start(GTK_BOX(rbox), args_frame, TRUE, TRUE, 0); @@ -258,6 +272,7 @@ void tpage_pack_widgets(gboolean tabbed) gtk_box_pack_start(GTK_BOX(hbox), debugger_label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), debugger_cmb, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(rbox), hbox, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(rbox), debugger_mode, FALSE, TRUE, 0); } if (oldroot) @@ -277,11 +292,25 @@ void tpage_pack_widgets(gboolean tabbed) gtk_widget_show_all(tab_target); } +static void on_debugger_mode_changed (GtkComboBox *box, gpointer data) +{ + if (tpage_get_debug_mode_index()) + { + gtk_frame_set_label (GTK_FRAME(args_frame), _("Remote Address")); + } + else + { + gtk_frame_set_label (GTK_FRAME(args_frame), _("Command Line Arguments")); + } + if (box != NULL) config_set_debug_changed(); +} + /* * create widgets */ static void tpage_create_widgets(void) { + int i; GList *modules, *iter; GtkWidget *hbox; GtkTextBuffer *buffer; @@ -293,12 +322,14 @@ static void tpage_create_widgets(void) #if GTK_CHECK_VERSION(3, 0, 0) gtk_editable_set_editable(GTK_EDITABLE(target_name), FALSE); target_button_browse = create_stock_button("document-open", _("Browse")); + target_button_clear = create_stock_button("edit-clear", _("Clear")); #else gtk_entry_set_editable(GTK_ENTRY(target_name), FALSE); target_button_browse = create_stock_button(GTK_STOCK_OPEN, _("Browse")); + target_button_clear = create_stock_button(GTK_STOCK_CLEAR, _("Clear")); #endif - gtk_widget_set_size_request(target_button_browse, BROWSE_BUTTON_WIDTH, 0); g_signal_connect(G_OBJECT(target_button_browse), "clicked", G_CALLBACK (on_target_browse_clicked), NULL); + g_signal_connect(G_OBJECT(target_button_clear), "clicked", G_CALLBACK (on_target_clear_clicked), NULL); /* debugger */ debugger_label = gtk_label_new(_("Debugger:")); @@ -311,6 +342,15 @@ static void tpage_create_widgets(void) g_list_free(modules); gtk_combo_box_set_active(GTK_COMBO_BOX(debugger_cmb), 0); + debugger_mode = gtk_combo_box_text_new(); + for (i = 0; i < DEBUGGER_SUPPORTED_MODES_COUNT; i++) + { + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(debugger_mode), (gchar*)_(debugger_supported_modes[i])); + } + gtk_combo_box_set_active(GTK_COMBO_BOX(debugger_mode), 0); + + g_signal_connect(G_OBJECT(debugger_mode), "changed", G_CALLBACK(on_debugger_mode_changed), NULL); + /* arguments */ args_frame = gtk_frame_new(_("Command Line Arguments")); hbox = gtk_scrolled_window_new(NULL, NULL); @@ -352,6 +392,22 @@ void tpage_set_debugger(const gchar *newvalue) gtk_combo_box_set_active(GTK_COMBO_BOX(debugger_cmb), module); } +/* + * set debugger mode + */ +void tpage_set_debugger_mode(const gchar *newvalue) +{ + int i = 0; + if (newvalue != NULL) { + for (i = DEBUGGER_SUPPORTED_MODES_COUNT - 1; i > 0; i--) + { + if (strcmp (newvalue, debugger_supported_modes[i]) == 0) break; + } + } + gtk_combo_box_set_active(GTK_COMBO_BOX(debugger_mode), i); + on_debugger_mode_changed (NULL, NULL); +} + /* * set command line */ @@ -381,6 +437,8 @@ void tpage_clear(void) /* reset debugger type */ gtk_combo_box_set_active(GTK_COMBO_BOX(debugger_cmb), 0); + gtk_combo_box_set_active(GTK_COMBO_BOX(debugger_mode), 0); + on_debugger_mode_changed (NULL, NULL); /* arguments */ buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(args_textview)); @@ -406,6 +464,14 @@ int tpage_get_debug_module_index(void) return gtk_combo_box_get_active(GTK_COMBO_BOX(debugger_cmb)); } +/* + * get selected debugger mode index + */ +int tpage_get_debug_mode_index(void) +{ + return gtk_combo_box_get_active(GTK_COMBO_BOX(debugger_mode)); +} + /* * get selected debugger name */ @@ -414,6 +480,17 @@ gchar* tpage_get_debugger(void) return gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(debugger_cmb)); } +/* + * get selected debugger mode + * (Do _not_ return a translated name.) + */ +gchar* tpage_get_debugger_mode(void) +{ + int index = tpage_get_debug_mode_index(); + if (index < 0 || index >= DEBUGGER_SUPPORTED_MODES_COUNT) index = 0; + return (gchar*)(debugger_supported_modes[index]); +} + /* * get command line */ @@ -464,7 +541,9 @@ void tpage_set_readonly(gboolean readonly) { gtk_text_view_set_editable (GTK_TEXT_VIEW (args_textview), !readonly); gtk_widget_set_sensitive (target_button_browse, !readonly); + gtk_widget_set_sensitive (target_button_clear, !readonly); gtk_widget_set_sensitive (debugger_cmb, !readonly); + gtk_widget_set_sensitive (debugger_mode, !readonly); envtree_set_readonly(readonly); } diff --git a/debugger/src/tpage.h b/debugger/src/tpage.h index 52d552082..39315ad2a 100644 --- a/debugger/src/tpage.h +++ b/debugger/src/tpage.h @@ -33,7 +33,11 @@ void tpage_set_target(const gchar *newvalue); gchar* tpage_get_debugger(void); void tpage_set_debugger(const gchar *newvalue); +gchar* tpage_get_debugger_mode(void); +void tpage_set_debugger_mode(const gchar *newvalue); + int tpage_get_debug_module_index(void); +int tpage_get_debug_mode_index(void); gchar* tpage_get_commandline(void); void tpage_set_commandline(const gchar *newvalue); diff --git a/debugger/src/utils.c b/debugger/src/utils.c index 3486b8a22..286cbe9ca 100644 --- a/debugger/src/utils.c +++ b/debugger/src/utils.c @@ -42,7 +42,7 @@ /* * opens position in a editor */ -void editor_open_position(const gchar *filename, int line) +gboolean editor_open_position_with_status(const gchar *filename, int line) { GeanyDocument* doc = NULL; gboolean already_open = (doc = document_get_current()) && !strcmp(DOC_FILENAME(doc), filename); @@ -65,7 +65,14 @@ void editor_open_position(const gchar *filename, int line) else { dialogs_show_msgbox(GTK_MESSAGE_ERROR, _("Can't find a source file \"%s\""), filename); + return FALSE; } + return TRUE; +} + +void editor_open_position(const gchar *filename, int line) +{ + editor_open_position_with_status (filename, line); } /* diff --git a/debugger/src/utils.h b/debugger/src/utils.h index 2d2a3c100..9ef58cb9d 100644 --- a/debugger/src/utils.h +++ b/debugger/src/utils.h @@ -25,6 +25,7 @@ #include void editor_open_position(const char* file, int line); +gboolean editor_open_position_with_status(const char* file, int line); GString* get_word_at_position(ScintillaObject *sci, int position); #endif /* guard */ diff --git a/po/fr.po b/po/fr.po index bc17b32a7..9bfa100ce 100644 --- a/po/fr.po +++ b/po/fr.po @@ -694,6 +694,26 @@ msgstr "Débogueur :" msgid "Command Line Arguments" msgstr "Arguments de la ligne de commande" +#. arguments +#: ../debugger/src/tpage.c:537 +msgid "Remote Address" +msgstr "Addresse de la machine distante" + +#. arguments +#: ../debugger/src/tpage.c:537 +msgid "Local Mode" +msgstr "Mode Local" + +#. arguments +#: ../debugger/src/tpage.c:537 +msgid "Remote Mode" +msgstr "Mode à Distance" + +#. arguments +#: ../debugger/src/tpage.c:537 +msgid "Cross Development Mode" +msgstr "Mode Dévelopement Croisé" + #. environment #: ../debugger/src/tpage.c:326 msgid "Environment Variables"