/* * key pressed event */ static gboolean on_key_pressed(GtkWidget *widget, GdkEvent *event, gpointer user_data) { guint keyval = ((GdkEventKey*)event)->keyval; GtkTreeSelection *selection; GList *rows; /* do not process event is page is readonly (debug is running) */ if (readonly) return FALSE; /* get selected rows */ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)); rows = gtk_tree_selection_get_selected_rows(selection, &model); rows = g_list_sort(rows, (GCompareFunc)gtk_tree_path_compare); if (keyval == GDK_Delete && rows && g_list_length(rows)) { GList *breaks, *iter; GtkTreeRowReference *new_selection = NULL; GtkTreePath *first_path = (GtkTreePath*)rows->data; /* "delete selected rows" */ /* get new selection */ if (gtk_tree_path_get_depth(first_path) > 1) { new_selection = get_unselected_sibling(first_path); } if (!new_selection) { GtkTreePath *file_path = gtk_tree_path_copy(first_path); if (gtk_tree_path_get_depth(file_path) > 1) { gtk_tree_path_up(file_path); } new_selection = get_unselected_sibling(file_path); gtk_tree_path_free(file_path); } /* collect GList of breakpoints to remove if file row is met - add all unselected breaks to the list as well */ breaks = NULL; for (iter = rows; iter; iter = iter->next) { GtkTreePath *path = (GtkTreePath*)iter->data; GtkTreeIter titer; gtk_tree_model_get_iter(model, &titer, path); if (1 == gtk_tree_path_get_depth(path)) { GtkTreeIter citer; gtk_tree_model_iter_children(model, &citer, &titer); do { if (!gtk_tree_selection_iter_is_selected(selection, &citer)) { gchar *file = NULL; gint line; breakpoint *bp; gtk_tree_model_get(model, &titer, FILEPATH, &file, -1); gtk_tree_model_get(model, &citer, LINE, &line, -1); bp = breaks_lookup_breakpoint(file, line); breaks = g_list_append(breaks, bp); g_free(file); } } while(gtk_tree_model_iter_next(model, &citer)); } else { GtkTreeIter piter; gchar *file = NULL; gint line; breakpoint *bp; gtk_tree_model_iter_parent(model, &piter, &titer); gtk_tree_model_get(model, &piter, FILEPATH, &file, -1); gtk_tree_model_get(model, &titer, LINE, &line, -1); bp = breaks_lookup_breakpoint(file, line); breaks = g_list_append(breaks, bp); g_free(file); } } if (1 == g_list_length(breaks)) { breakpoint *bp = (breakpoint*)breaks->data; g_list_free(breaks); breaks_remove(bp->file, bp->line); } else { breaks_remove_list(breaks); } if (new_selection) { /* get path to select */ GtkTreePath *path = NULL; path = gtk_tree_row_reference_get_path(new_selection); gtk_tree_selection_select_path(selection, path); gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(widget), path, NULL, TRUE, 0.5, 0.5); gtk_tree_path_free(path); gtk_tree_row_reference_free(new_selection); } } /* free rows list */ g_list_foreach (rows, (GFunc)gtk_tree_path_free, NULL); g_list_free (rows); return FALSE; }
/* * Occures on notify from editor. * Handles margin click to set/remove breakpoint */ gboolean on_editor_notify( GObject *object, GeanyEditor *editor, SCNotification *nt, gpointer data) { if (!editor->document->real_path) { /* no other way to handle removing a file from outside of geany */ markers_remove_all(editor->document); } switch (nt->nmhdr.code) { case SCN_MARGINCLICK: { char* file; int line; break_state bs; if (!editor->document->real_path || 1 != nt->margin) break; file = editor->document->file_name; line = sci_get_line_from_position(editor->sci, nt->position) + 1; bs = breaks_get_state(file, line); if (BS_NOT_SET == bs) breaks_add(file, line, NULL, TRUE, 0); else if (BS_ENABLED == bs) breaks_remove(file, line); else if (BS_DISABLED == bs) breaks_switch(file, line); scintilla_send_message(editor->sci, SCI_SETFOCUS, TRUE, 0); return TRUE; } case SCN_DWELLSTART: { GString *word; if (DBS_STOPPED != debug_get_state ()) break; /* get a word under the cursor */ word = get_word_at_position(editor->sci, nt->position); if (word->len) { gchar *calltip = debug_get_calltip_for_expression(word->str); if (calltip) { leave_signal = g_signal_connect(G_OBJECT(editor->sci), "leave-notify-event", G_CALLBACK(on_mouse_leave), NULL); scintilla_send_message (editor->sci, SCI_CALLTIPSHOW, nt->position, (long)calltip); } } g_string_free(word, TRUE); break; } case SCN_DWELLEND: { if (DBS_STOPPED != debug_get_state ()) break; if (scintilla_send_message (editor->sci, SCI_CALLTIPACTIVE, 0, 0)) { g_signal_handler_disconnect(G_OBJECT(editor->sci), leave_signal); scintilla_send_message (editor->sci, SCI_CALLTIPCANCEL, 0, 0); } break; } case SCN_MODIFYATTEMPTRO: { dialogs_show_msgbox(GTK_MESSAGE_INFO, _("To edit source files stop debugging session")); break; } case SCN_MODIFIED: { if(((SC_MOD_INSERTTEXT & nt->modificationType) || (SC_MOD_DELETETEXT && nt->modificationType)) && editor->document->file_name && nt->linesAdded) { int line = sci_get_line_from_position(editor->sci, nt->position) + 1; GList *breaks = breaks_get_for_document(editor->document->file_name); if (breaks) { GList *iter = breaks; while (iter) { breakpoint *bp = (breakpoint*)iter->data; if (nt->linesAdded > 0 && bp->line >= line) { breaks_move_to_line(bp->file, bp->line, bp->line + nt->linesAdded); bptree_update_breakpoint(bp); } else if (nt->linesAdded < 0 && bp->line >= line) { if (bp->line < line - nt->linesAdded) { breaks_remove(bp->file, bp->line); } else { breaks_move_to_line(bp->file, bp->line, bp->line + nt->linesAdded); bptree_update_breakpoint(bp); } } iter = iter->next; } config_set_debug_changed(); g_list_free(breaks); } } break; } } return FALSE; }
/* * Occures when key is pressed. * Handles debug Run/Stop/... and add/remove breakpoint activities */ gboolean keys_callback(guint key_id) { switch (key_id) { case KEY_RUN: debug_run(); break; case KEY_STOP: debug_stop(); break; case KEY_RESTART: debug_restart(); break; case KEY_STEP_OVER: debug_step_over(); break; case KEY_STEP_INTO: debug_step_into(); break; case KEY_STEP_OUT: debug_step_out(); break; case KEY_EXECUTE_UNTIL: { GeanyDocument *doc = document_get_current(); if (doc) { int line = sci_get_current_line(doc->editor->sci) + 1; debug_execute_until(DOC_FILENAME(doc), line); } break; } case KEY_BREAKPOINT: { GeanyDocument *doc = document_get_current(); if (doc) { int line = sci_get_current_line(doc->editor->sci) + 1; break_state bs = breaks_get_state(DOC_FILENAME(doc), line); if (BS_NOT_SET == bs) breaks_add(DOC_FILENAME(doc), line, NULL, TRUE, 0); else if (BS_ENABLED == bs) breaks_remove(DOC_FILENAME(doc), line); else if (BS_DISABLED == bs) breaks_switch(DOC_FILENAME(doc), line); scintilla_send_message(doc->editor->sci, SCI_SETFOCUS, TRUE, 0); } break; } case KEY_CURRENT_INSTRUCTION: { if (DBS_STOPPED == debug_get_state() && debug_current_instruction_have_sources()) { debug_jump_to_current_instruction(); gtk_widget_set_sensitive(tab_call_stack, FALSE); stree_select_first_frame(FALSE); gtk_widget_set_sensitive(tab_call_stack, TRUE); } } } return TRUE; }
/* * function to remove a break when loading config and iterating through * existing breaks */ void removebreak(void *p) { breakpoint *bp = (breakpoint*)p; breaks_remove(bp->file, bp->line); }