Пример #1
0
/*
 * env tree view name changed hadler 
 */
static void on_name_changed(GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer user_data)
{
	GtkTreeIter  iter;
	GtkTreePath *tree_path = gtk_tree_path_new_from_string (path);
	GtkTreePath *empty_path = gtk_tree_row_reference_get_path(empty_row);
    
	gboolean empty = !gtk_tree_path_compare(tree_path, empty_path);

	gtk_tree_model_get_iter (
		 model,
		 &iter,
		 tree_path);
	
	gchar* oldvalue;
	gtk_tree_model_get (
		model,
		&iter,
		NAME, &oldvalue,
       -1);
    
	gchar *striped = g_strstrip(g_strdup(new_text));

	if (!strlen(striped))
	{
		/* if name is empty - offer to delete variable */
		if (!empty && dialogs_show_question(_("Delete variable?")))
		{
			delete_selected_rows();
			config_set_debug_changed();

			gtk_widget_grab_focus(tree);
		}
	}
	else if (strcmp(oldvalue, striped))
    {
		gtk_list_store_set(store, &iter, NAME, striped, -1);
		if (empty)
		{
			/* if it was a new row - move cursor to a value cell */
			entering_new_var = TRUE;
			gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(tree), tree_path, column_value, renderer_value, TRUE);
		}
		if (!empty)
		{
			config_set_debug_changed();
		}
	}
	
	gtk_tree_path_free(tree_path);
	gtk_tree_path_free(empty_path);
	g_free(oldvalue);
	g_free(striped);
}
Пример #2
0
/*
 * Set breakpoints condition.
 * arguments:
 * 		file - breakpoints filename
 * 		line - breakpoints line
 * 		condition - breakpoints line
 */
void breaks_set_condition(const char* file, int line, const char* condition)
{
	/* do not process async break manipulation on modules
	that do not support async interuppt */
	enum dbs state = debug_get_state();
	if (DBS_RUNNING == state &&  !debug_supports_async_breaks())
		return;

	/* lookup for breakpoint */
	breakpoint* bp = NULL;
	if (!(bp = breaks_lookup_breakpoint(file, line)))
		return;
	
	/* change condition */
	strcpy(bp->condition, condition);
	
	/* handle setting condition instantly if debugger is idle or stopped
	and request debug module interruption overwise */
	if (state == DBS_IDLE)
	{
		on_set_condition(bp);
		config_set_debug_changed();
	}
	else if (state == DBS_STOPPED)
		breaks_set_condition_debug(bp);
	else if (state != DBS_STOP_REQUESTED)
		debug_request_interrupt((bs_callback)breaks_set_condition_debug, (gpointer)bp);
}
Пример #3
0
/*
 * Add new breakpoint.
 * arguments:
 * 		file - breakpoints filename
 * 		line - breakpoints line
 * 		condition - breakpoints line
 * 		enabled - is new breakpoint enabled
 * 		hitscount - breakpoints hitscount
 */
void breaks_add(const char* file, int line, char* condition, int enabled, int hitscount)
{
	/* do not process async break manipulation on modules
	that do not support async interuppt */
	enum dbs state = debug_get_state();
	if (DBS_RUNNING == state &&  !debug_supports_async_breaks())
		return;
	
	/* allocate memory */
	breakpoint* bp = break_new_full(file, line, condition, enabled, hitscount);
	
	/* check whether GTree for this file exists and create if doesn't */
	GTree *tree;
	if (!(tree = g_hash_table_lookup(files, bp->file)))
	{
		char *newfile = g_strdup(bp->file);
		tree = g_tree_new_full(compare_func, NULL, NULL, (GDestroyNotify)g_free);
		g_hash_table_insert(files, newfile, tree);
	}
	
	/* insert to internal storage */
	g_tree_insert(tree, GINT_TO_POINTER(bp->line), bp);

	/* handle creation instantly if debugger is idle or stopped
	and request debug module interruption overwise */
	if (DBS_IDLE == state)
	{
		on_add(bp);
		config_set_debug_changed();
	}
	else if (DBS_STOPPED == state)
		breaks_add_debug(bp);
	else if (DBS_STOP_REQUESTED != state)
		debug_request_interrupt((bs_callback)breaks_add_debug, (gpointer)bp);
}
Пример #4
0
/*
 * Switch breakpoints state.
 * arguments:
 * 		file - breakpoints filename
 * 		line - breakpoints line
 */
void breaks_switch(const char* file, int line)
{
	/* do not process async break manipulation on modules
	that do not support async interuppt */
	enum dbs state = debug_get_state();
	if (DBS_RUNNING == state &&  !debug_supports_async_breaks())
		return;

	/* lookup for breakpoint */
	breakpoint* bp = NULL;
	if (!(bp = breaks_lookup_breakpoint(file, line)))
		return;
	
	/* change activeness */
	bp->enabled = !bp->enabled;
	
	/* handle switching instantly if debugger is idle or stopped
	and request debug module interruption overwise */
	if (DBS_IDLE == state)
	{
		on_switch(bp);
		config_set_debug_changed();
	}
	else if (DBS_STOPPED == state)
		breaks_switch_debug(bp);
	else if (DBS_STOP_REQUESTED != state)
		debug_request_interrupt((bs_callback)breaks_switch_debug, (gpointer)bp);
}
Пример #5
0
/* 
 * text has been dragged into the watch tree view
 */
static void on_watch_dragged_callback(GtkWidget *wgt, GdkDragContext *context, int x, int y,
	GtkSelectionData *seldata, guint info, guint _time,
    gpointer userdata)
{
	/* string that is dragged */
	gchar *expression = (gchar*)seldata->data;
	GtkTreePath *path = NULL;
	GtkTreeViewDropPosition pos;
	GtkTreePath *empty_path;
	GtkTreeIter newvar;

	/* lookup for where the text has been dropped */
	gtk_tree_view_get_dest_row_at_pos(GTK_TREE_VIEW(wtree), x, y, &path, &pos);

	/* if dropped into last row - insert before it */
	empty_path = wtree_empty_path();
	if (!gtk_tree_path_compare(empty_path, path))
		pos = GTK_TREE_VIEW_DROP_BEFORE;
	gtk_tree_path_free(empty_path);
	
	/* if dropped into children area - insert before parent */
	if (gtk_tree_path_get_depth(path) > 1)
	{
		while (gtk_tree_path_get_depth(path) > 1)
			gtk_tree_path_up(path);
		pos = GTK_TREE_VIEW_DROP_BEFORE;
	}
	
	/* insert new row */
	if (path)
	{
		GtkTreeIter sibling;
		gtk_tree_model_get_iter(wmodel, &sibling, path);
		
		if (GTK_TREE_VIEW_DROP_BEFORE == pos || GTK_TREE_VIEW_DROP_INTO_OR_BEFORE == pos)
			gtk_tree_store_insert_before(wstore, &newvar, NULL, &sibling);
		else
			gtk_tree_store_insert_after(wstore, &newvar, NULL, &sibling);
	}
	else
	{
		GtkTreeIter empty;

		wtree_empty_row(&empty);
		gtk_tree_store_insert_before(wstore, &newvar, NULL, &empty);
	}
	
	/* if debugger is active (in stopped condition) - add to run-time watch list
	 *  if not - just set new expession in the tree view */ 
	if (DBS_STOPPED == debug_state)
	{
		variable *var = active_module->add_watch(expression);
		change_watch(GTK_TREE_VIEW(wtree), &newvar, var);
	}
	else
		variable_set_name_only(wstore, &newvar, expression);

	config_set_debug_changed();
}
Пример #6
0
static void breaks_set_hits_count_debug(breakpoint* bp)
{
	if (debug_set_break(bp, BSA_UPDATE_HITS_COUNT))
	{
		on_set_hits_count(bp);
		/* mark config for saving */
		config_set_debug_changed();
	}
	else
		dialogs_show_msgbox(GTK_MESSAGE_ERROR, "%s", debug_error_message());
}
Пример #7
0
/*
 * functions that are called when a breakpoint is altered while debuginng session is active.
 * Therefore, these functions try to alter break in debug session first and if successful -
 * do what on_... do or simply call on_... function directly
 */
static void breaks_add_debug(breakpoint* bp)
{
	if (debug_set_break(bp, BSA_NEW_BREAK))
	{
		/* add markers, update treeview */
		on_add(bp);
		/* mark config for saving */
		config_set_debug_changed();
	}
	else
		dialogs_show_msgbox(GTK_MESSAGE_ERROR, "%s", debug_error_message());
}
Пример #8
0
static void breaks_remove_debug(breakpoint* bp)
{
	if (debug_remove_break(bp))
	{
		/* remove markers, update treeview */
		on_remove(bp);
		/* mark config for saving */
		config_set_debug_changed();
	}
	else
		dialogs_show_msgbox(GTK_MESSAGE_ERROR, "%s", debug_error_message());
}
Пример #9
0
static void breaks_switch_debug(breakpoint* bp)
{
	if (debug_set_break(bp, BSA_UPDATE_ENABLE))
	{
		on_switch(bp);
		/* mark config for saving */
		config_set_debug_changed();
	}
	else
	{
		bp->enabled = !bp->enabled;
		dialogs_show_msgbox(GTK_MESSAGE_ERROR, "%s", debug_error_message());
	}
}
Пример #10
0
static void breaks_remove_list_debug(GList *list)
{
	GList *iter;
	for (iter = list; iter; iter = iter->next)
	{
		breakpoint *bp = (breakpoint*)iter->data;
		if (debug_remove_break(bp))
		{
			on_remove((breakpoint*)iter->data);
		}
	}
	g_list_free(list);

	config_set_debug_changed();
}
Пример #11
0
static void breaks_set_condition_debug(breakpoint* bp)
{
	if (debug_set_break(bp, BSA_UPDATE_CONDITION))
	{
		on_set_condition(bp);
		/* mark config for saving */
		config_set_debug_changed();
	}
	else
	{
		/* revert to old condition (taken from tree) */
		gchar* oldcondition = bptree_get_condition(bp);
		strcpy(bp->condition, oldcondition);
		g_free(oldcondition);
		/* show error message */
		dialogs_show_msgbox(GTK_MESSAGE_ERROR, "%s", debug_error_message());
	}
}
Пример #12
0
/*
 * env tree key pressed handler 
 */
static gboolean on_envtree_keypressed(GtkWidget *widget, GdkEvent  *event, gpointer user_data)
{
	/* do not allow deleting while debugging */
	if(page_read_only)
		return FALSE;
	
	/* handling only Delete button pressing
	that means "delete selected rows" */
	guint keyval = ((GdkEventKey*)event)->keyval;
	
	if (GDK_Delete == keyval)
	{
		delete_selected_rows();
		config_set_debug_changed();
	}

	return GDK_Tab == keyval;
}
Пример #13
0
/* 
 * mouse button has been pressed while being in watch(autos) tree view
 */
static gboolean on_watch_button_pressed_callback(GtkWidget *treeview, GdkEventButton *event, gpointer userdata)
{
    if (event->type == GDK_2BUTTON_PRESS  &&  event->button == 1)
	{
		GtkTreePath *path = NULL;
		if (gtk_tree_view_get_path_at_pos(
			GTK_TREE_VIEW(treeview),
		    (int)event->x, (int)event->y, &path, NULL, NULL, NULL))
		{
			gchar *expression = NULL;
			GtkTreeIter iter;
			GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
			gtk_tree_model_get_iter (model, &iter, path);

			gtk_tree_model_get(model, &iter,
				W_EXPRESSION, &expression,
			    -1);

			if (strlen(expression))
			{
				GtkTreeIter newvar, empty;

				wtree_empty_row(&empty);
				gtk_tree_store_insert_before(wstore, &newvar, NULL, &empty);
			
				/* if debugger is active (in stopped condition) - add to run-time watch list
				 *  if not - just set new expession in the tree view */ 
				if (DBS_STOPPED == debug_state)
				{
					variable *var = active_module->add_watch(expression);
					change_watch(GTK_TREE_VIEW(wtree), &newvar, var);
				}
				else
					variable_set_name_only(wstore, &newvar, expression);

				config_set_debug_changed();
			}

			g_free(expression);
		}
	}
	
	return FALSE;
}
Пример #14
0
/*
 * Moves a breakpoint from to another line
 * arguments:
 * 		file - breakpoints filename
 * 		line_from - old line number
 * 		line_to - new line number
 */
void breaks_move_to_line(const char* file, int line_from, int line_to)
{
	/* first look for the tree for the given file */
	GTree *tree = NULL;
	if ( (tree = g_hash_table_lookup(files, file)) )
	{
		/* lookup for the break in GTree*/
		breakpoint *bp = (breakpoint*)g_tree_lookup(tree, GINT_TO_POINTER(line_from));
		if (bp)
		{
			g_tree_steal(tree, GINT_TO_POINTER(line_from));
			bp->line = line_to;
			g_tree_insert(tree, GINT_TO_POINTER(line_to), bp);

			/* mark config for saving */
			config_set_debug_changed();
		}
	}
}
Пример #15
0
/*
 * Remove all breakpoints in the list.
 * arguments:
 * 		list - list f breakpoints
 */
void breaks_remove_list(GList *list)
{
	/* do not process async break manipulation on modules
	that do not support async interuppt */
	enum dbs state = debug_get_state();
	if (DBS_RUNNING == state &&  !debug_supports_async_breaks())
		return;

	/* handle removing instantly if debugger is idle or stopped
	and request debug module interruption overwise */
	if (DBS_IDLE == state)
	{
		on_remove_list(list);
		g_list_free(list);
		
		config_set_debug_changed();
	}
	else if (DBS_STOPPED == state)
		breaks_remove_list_debug(list);
	else if (DBS_STOP_REQUESTED != state)
		debug_request_interrupt((bs_callback)breaks_remove_list_debug, (gpointer)list);
}
Пример #16
0
static void breaks_set_enabled_list_debug(GList *list)
{
	GList *iter;
	for (iter = list; iter; iter = iter->next)
	{
		breakpoint *bp = (breakpoint*)iter->data;
		if (!bp->enabled)
		{
			bp->enabled = TRUE;
			if (debug_set_break(bp, BSA_UPDATE_ENABLE))
			{
				on_switch(bp);
			}
			else
			{
				bp->enabled = FALSE;
			}
		}
	}
	g_list_free(list);

	config_set_debug_changed();
}
Пример #17
0
/*
 * sets all breakpoints fo the file enabled or disabled.
 * arguments:
 * 		file - list of breakpoints
 * 		enabled - anble or disable breakpoints
 */
void breaks_set_enabled_for_file(const const char *file, gboolean enabled)
{
	/* do not process async break manipulation on modules
	that do not support async interuppt */
	enum dbs state = debug_get_state();
	if (DBS_RUNNING == state &&  !debug_supports_async_breaks())
		return;

	GList *breaks = breaks_get_for_document(file);

	/* handle switching instantly if debugger is idle or stopped
	and request debug module interruption overwise */
	if (DBS_IDLE == state)
	{
		on_set_enabled_list(breaks, enabled);
		g_list_free(breaks);
		config_set_debug_changed();
	}
	else if (DBS_STOPPED == state)
		enabled ? breaks_set_enabled_list_debug(breaks) : breaks_set_disabled_list_debug(breaks);
	else if (DBS_STOP_REQUESTED != state)
		debug_request_interrupt((bs_callback)(enabled ? breaks_set_enabled_list_debug : breaks_set_disabled_list_debug), (gpointer)breaks);
}
Пример #18
0
/* 
 * key has been pressed while being in watch tree view
 */
static gboolean on_watch_key_pressed_callback(GtkWidget *widget, GdkEvent  *event, gpointer user_data)
{
	/* handling only Delete button pressing
	 * that means "delete selected rows" */
	int keyval = ((GdkEventKey*)event)->keyval;
	if (keyval != GDK_Delete)
		return FALSE;

	/* get selected rows */
	GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(wtree));
	GList *rows = gtk_tree_selection_get_selected_rows(selection, &wmodel);
	
	/* empty row path */
	GtkTreePath *empty_path = wtree_empty_path();

	/* check whether only empty row was selected */
	if (1 != gtk_tree_selection_count_selected_rows(selection) ||
	    gtk_tree_path_compare((GtkTreePath*)rows->data, empty_path))
	{
		/* path reference to select after deleteing finishes */
		GtkTreeRowReference *reference_to_select = NULL;

		/* get references to the rows */
		GList *references = NULL;
		GList *iter = rows;
		while (iter)
		{
			GtkTreePath *path = (GtkTreePath*)iter->data;

			/* move up paths to the root elements */
			while (gtk_tree_path_get_depth(path) > 1)
				gtk_tree_path_up(path);

			/* add path reference if it's not an empty row*/
			if (gtk_tree_path_compare(path, empty_path))
				references = g_list_append(references, gtk_tree_row_reference_new(wmodel, path));

			iter = iter->next;
		}

		/* iterate through references and remove */
		iter = references;
		while (iter)
		{
			GtkTreeRowReference *reference = (GtkTreeRowReference*)iter->data;
			/* check for valid reference because two or more equal
			refernces could be put in the list if several child items
			of the same node were selected and the path for the
			current reference was already deleted */
			if (gtk_tree_row_reference_valid(reference))
			{
				GtkTreePath *path = gtk_tree_row_reference_get_path(reference);

				if (!reference_to_select)
				{
					/* select upper sibling of the upper
					selected row that has unselected upper sibling */
					GtkTreePath *sibling = gtk_tree_path_copy(path);
					if(gtk_tree_path_prev(sibling))
					{
						if (!gtk_tree_selection_path_is_selected(selection, sibling))
							reference_to_select = gtk_tree_row_reference_new(gtk_tree_view_get_model(GTK_TREE_VIEW(wtree)), sibling);
					}
					else if (gtk_tree_path_next(sibling), gtk_tree_path_compare(path, sibling))
						reference_to_select = gtk_tree_row_reference_new(gtk_tree_view_get_model(GTK_TREE_VIEW(wtree)), sibling);
				}

				/* get iterator */
				GtkTreeIter titer;
				gtk_tree_model_get_iter(wmodel, &titer, path);

				/* remove from the debug session, if it's active */
				if (DBS_STOPPED == debug_state)
				{

					gchar *internal = NULL;
					gtk_tree_model_get (
						wmodel,
						&titer,
						W_INTERNAL, &internal,
						-1);

					active_module->remove_watch(internal);

					g_free(internal);
				}


				gtk_tree_store_remove(wstore, &titer);

				gtk_tree_path_free(path);
			}
			
			iter = iter->next;
		}

		/* if all (with or without empty row) was selected - set empty row
		as a path to be selected after deleting */
		if (!reference_to_select)
		{
			GtkTreePath *path = wtree_empty_path();
			reference_to_select = gtk_tree_row_reference_new (gtk_tree_view_get_model(GTK_TREE_VIEW(wtree)), path);
			gtk_tree_path_free(path);
		}

		/* set selection */
		gtk_tree_selection_unselect_all(selection);
		GtkTreePath *path_to_select = gtk_tree_row_reference_get_path(reference_to_select);
		gtk_tree_selection_select_path(selection, path_to_select);
		gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(widget), path_to_select, NULL, TRUE, 0.5, 0.5);
		gtk_tree_path_free(path_to_select);	

		/* free references list */
		g_list_foreach (references, (GFunc)gtk_tree_row_reference_free, NULL);
		g_list_free (references);

		config_set_debug_changed();
	}

	gtk_tree_path_free(empty_path);

	/* free rows list */
	g_list_foreach (rows, (GFunc)gtk_tree_path_free, NULL);
	g_list_free (rows);

	return FALSE;
}
Пример #19
0
/* 
 * watch expression has been changed
 */
static void on_watch_changed(GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer user_data)
{
	/* get iterator to the changed row */
	GtkTreeIter  iter;
	GtkTreePath *tree_path = gtk_tree_path_new_from_string (path);
	gtk_tree_model_get_iter (
		 gtk_tree_view_get_model(GTK_TREE_VIEW(wtree)),
		 &iter,
		 tree_path);
	
	/* get oldvalue */
	gchar* oldvalue;
	gtk_tree_model_get (
		wmodel,
		&iter,
		W_NAME, &oldvalue,
       -1);
	gchar *internal = NULL;
		gtk_tree_model_get (
		wmodel,
		&iter,
		W_INTERNAL, &internal,
		-1);

	/* check if it is empty row */
	GtkTreePath *empty_path = wtree_empty_path();
	gboolean is_empty_row = !gtk_tree_path_compare (tree_path, empty_path);
	gtk_tree_path_free(empty_path);

   	gchar *striped = g_strstrip(g_strdup(new_text));
	if (!strlen(striped) &&
		!is_empty_row &&
		dialogs_show_question(_("Delete variable?")))
	{
		/* if new value is empty string on non-empty row
		 * offer to delete watch */
		gtk_tree_store_remove(wstore, &iter);
		if (DBS_STOPPED == debug_state)
			active_module->remove_watch(internal);

		config_set_debug_changed();
	}
	else if (strcmp(oldvalue, striped))
    {
		/* new value is non empty */

		/* insert new row if changing was the last empty row */
		GtkTreeIter newiter;
		if (is_empty_row)
			gtk_tree_store_insert_before(wstore, &newiter, NULL, &iter);
		
		/* set expression */
		variable_set_name_only(wstore, is_empty_row ? &newiter : &iter, striped);

		/* if debug is active - remove old watch and add new one */
		if (DBS_STOPPED == debug_state)
		{
			active_module->remove_watch(internal);
			variable *newvar = active_module->add_watch(striped);
			change_watch(GTK_TREE_VIEW(wtree), is_empty_row ? &newiter : &iter, newvar);
		}
		
		/* if new watch has been added - set selection to the new created row */
		if (is_empty_row)
		{
			GtkTreePath *_path = gtk_tree_model_get_path(wmodel, &newiter);
			GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(wtree));
			gtk_tree_selection_unselect_all(selection);
			gtk_tree_selection_select_path(selection, _path);
			gtk_tree_path_free(_path);
		}

		config_set_debug_changed();
	}
	
	/* free resources */
	gtk_tree_path_free(tree_path);
	g_free(oldvalue);
	g_free(internal);
	g_free(striped);
}
Пример #20
0
/*
 * env tree view value changed handler 
 */
static void on_value_changed(GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer user_data)
{
	GtkTreeIter  iter;
	GtkTreePath *tree_path = gtk_tree_path_new_from_string (path);

    GtkTreePath *empty_path = gtk_tree_row_reference_get_path(empty_row);
	gboolean empty = !gtk_tree_path_compare(tree_path, empty_path);
	gtk_tree_path_free(empty_path);

	gtk_tree_model_get_iter (
		 model,
		 &iter,
		 tree_path);
	
	gchar *striped = g_strstrip(g_strdup(new_text));
	
	if (!strlen(striped))
	{
		/* if new value is empty string, if it's a new row - do nothig
		 otheerwise - offer to delete a variable */
		if (empty)
			gtk_list_store_set(store, &iter, NAME, "", -1);
		else
		{
			if (dialogs_show_question(_("Delete variable?")))
			{
				delete_selected_rows();
				config_set_debug_changed();

				gtk_widget_grab_focus(tree);
			}
		}
	}
	else
	{
		/* if old variable - change value, otherwise - add another empty row below */
		gchar* oldvalue;
		gtk_tree_model_get (
			model,
			&iter,
			VALUE, &oldvalue,
		   -1);

		if (strcmp(oldvalue, striped))
		{
			gtk_list_store_set(store, &iter, VALUE, striped, -1);
			if (empty)
				add_empty_row();
			
			g_object_set (renderer_value, "editable", FALSE, NULL);
			config_set_debug_changed();
		}
		
		g_free(oldvalue);
	}
	
	if (empty)
		entering_new_var = FALSE;

	gtk_tree_path_free(tree_path);
	g_free(striped);

	gtk_tree_path_free(being_edited_value);
}
Пример #21
0
/*
 * 	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;
}