r1327@localhost: muntyan | 2005-12-10 13:57:46 -0600

Made moving/deleting line marks more safe
This commit is contained in:
Yevgen Muntyan 2005-12-11 04:29:21 +00:00
parent ce6049cb8c
commit b7fea6f2cd
3 changed files with 72 additions and 58 deletions

View File

@ -57,6 +57,8 @@ static void moo_line_mark_changed (MooLineMark *mark);
static void update_background_gc (MooLineMark *mark);
static void update_pixbuf (MooLineMark *mark);
static void moo_line_mark_deleted_real (MooLineMark *mark);
enum {
CHANGED,
@ -73,8 +75,6 @@ enum {
PROP_BACKGROUND_SET,
PROP_PIXBUF,
PROP_STOCK_ID,
PROP_BUFFER,
PROP_LINE,
PROP_NAME,
PROP_VISIBLE
};
@ -93,6 +93,8 @@ moo_line_mark_class_init (MooLineMarkClass *klass)
gobject_class->get_property = moo_line_mark_get_property;
gobject_class->finalize = moo_line_mark_finalize;
klass->deleted = moo_line_mark_deleted_real;
g_object_class_install_property (gobject_class,
PROP_BACKGROUND,
g_param_spec_string ("background",
@ -117,22 +119,6 @@ moo_line_mark_class_init (MooLineMarkClass *klass)
FALSE,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_BUFFER,
g_param_spec_object ("buffer",
"buffer",
"buffer",
MOO_TYPE_TEXT_BUFFER,
G_PARAM_READABLE));
g_object_class_install_property (gobject_class,
PROP_LINE,
g_param_spec_int ("line",
"line",
"line",
0, 10000000, 0,
G_PARAM_READABLE));
g_object_class_install_property (gobject_class,
PROP_NAME,
g_param_spec_string ("name",
@ -269,14 +255,6 @@ moo_line_mark_get_property (GObject *object,
g_value_set_boolean (value, mark->priv->background_set != 0);
break;
case PROP_BUFFER:
g_value_set_object (value, mark->priv->buffer);
break;
case PROP_LINE:
g_value_set_int (value, mark->priv->line_no);
break;
case PROP_NAME:
g_value_set_string (value, mark->priv->name);
break;
@ -431,20 +409,12 @@ _moo_line_mark_set_line (MooLineMark *mark,
int line_no,
guint stamp)
{
gboolean moved = FALSE;
g_assert (MOO_IS_LINE_MARK (mark));
g_assert (mark->priv->buffer != NULL);
if (mark->priv->line_no != line_no)
moved = TRUE;
g_assert (!line || mark->priv->buffer != NULL);
mark->priv->line = line;
mark->priv->line_no = line_no;
mark->priv->stamp = stamp;
if (moved)
g_object_notify (G_OBJECT (mark), "line");
}
@ -463,9 +433,12 @@ _moo_line_mark_set_buffer (MooLineMark *mark,
{
g_assert (MOO_IS_LINE_MARK (mark));
g_assert (!buffer || mark->priv->buffer == NULL);
mark->priv->buffer = buffer;
mark->priv->line_buf = line_buf;
g_object_notify (G_OBJECT (mark), "buffer");
if (!buffer)
_moo_line_mark_set_line (mark, NULL, -1, 0);
}
@ -477,15 +450,26 @@ moo_line_mark_get_buffer (MooLineMark *mark)
}
static void
moo_line_mark_deleted_real (MooLineMark *mark)
{
_moo_line_mark_set_buffer (mark, NULL, NULL);
}
void
_moo_line_mark_deleted (MooLineMark *mark)
{
g_assert (MOO_IS_LINE_MARK (mark));
mark->priv->buffer = NULL;
mark->priv->line_buf = NULL;
mark->priv->line = NULL;
mark->priv->line_no = -1;
g_object_notify (G_OBJECT (mark), "buffer");
MOO_LINE_MARK_GET_CLASS (mark)->deleted (mark);
}
gboolean
moo_line_mark_get_deleted (MooLineMark *mark)
{
g_return_val_if_fail (MOO_IS_LINE_MARK (mark), TRUE);
return mark->priv->buffer == NULL;
}

View File

@ -43,7 +43,12 @@ struct _MooLineMark
struct _MooLineMarkClass
{
GObjectClass parent_class;
/* signal */
void (*changed) (MooLineMark *mark);
/* method */
void (*deleted) (MooLineMark *mark);
};
@ -62,6 +67,8 @@ int moo_line_mark_get_line (MooLineMark *mark);
MooTextBuffer *moo_line_mark_get_buffer (MooLineMark *mark);
gboolean moo_line_mark_get_visible (MooLineMark *mark);
gboolean moo_line_mark_get_deleted (MooLineMark *mark);
void moo_line_mark_set_stock_id (MooLineMark *mark,
const char *stock_id);
void moo_line_mark_set_pixbuf (MooLineMark *mark,

View File

@ -478,7 +478,7 @@ moo_text_buffer_insert_text (GtkTextBuffer *text_buffer,
first_line, last_line - first_line,
tag);
/* XXX btree can do it better */
/* XXX btree can do it better ? i guess it can't */
if (starts_line && ins_line)
{
GSList *l, *marks;
@ -503,6 +503,36 @@ moo_text_buffer_insert_text (GtkTextBuffer *text_buffer,
}
static void
marks_moved_or_deleted (MooTextBuffer *buffer,
GSList *moved,
GSList *deleted)
{
GSList *l;
if (!moved && !deleted)
return;
g_slist_foreach (moved, (GFunc) g_object_ref, NULL);
g_slist_foreach (deleted, (GFunc) g_object_ref, NULL);
for (l = deleted; l != NULL; l = l->next)
_moo_line_mark_set_buffer (l->data, NULL, NULL);
for (l = deleted; l != NULL; l = l->next)
{
line_mark_deleted (buffer, l->data);
g_object_unref (l->data);
}
for (l = moved; l != NULL; l = l->next)
if (!moo_line_mark_get_deleted (l->data))
line_mark_moved (buffer, l->data);
g_slist_foreach (deleted, (GFunc) g_object_unref, NULL);
g_slist_foreach (moved, (GFunc) g_object_unref, NULL);
}
static void
moo_text_buffer_delete_range (GtkTextBuffer *text_buffer,
GtkTextIter *start,
@ -511,7 +541,7 @@ moo_text_buffer_delete_range (GtkTextBuffer *text_buffer,
MooTextBuffer *buffer = MOO_TEXT_BUFFER (text_buffer);
int first_line, last_line;
gboolean starts_line;
GSList *deleted_marks = NULL, *moved_marks = NULL, *l;
GSList *deleted_marks = NULL, *moved_marks = NULL;
gtk_text_iter_order (start, end);
@ -556,18 +586,14 @@ moo_text_buffer_delete_range (GtkTextBuffer *text_buffer,
first_line);
}
/* XXX */
for (l = deleted_marks; l != NULL; l = l->next)
line_mark_deleted (buffer, l->data);
for (l = deleted_marks; l != NULL; l = l->next)
g_object_unref (l->data);
/* It would be better if marks were moved/deleted before deleting text, but it
could cause problems with invalidated iters. if they were deleted after
deleting text, it would be even worse since our btree and gtk btree would not
be syncronized when callbacks are called. So doing it here is safest (though
not most simple or clean) */
marks_moved_or_deleted (buffer, moved_marks, deleted_marks);
g_slist_free (deleted_marks);
while (moved_marks)
{
line_mark_moved (buffer, moved_marks->data);
moved_marks = g_slist_delete_link (moved_marks, moved_marks);
}
g_slist_free (moved_marks);
if (last_line - first_line < 2)
_moo_text_buffer_ensure_highlight (buffer, first_line, last_line);
@ -1742,14 +1768,10 @@ moo_text_buffer_remove_line_mark (MooTextBuffer *buffer,
g_return_if_fail (MOO_IS_LINE_MARK (mark));
g_return_if_fail (moo_line_mark_get_buffer (mark) == buffer);
g_object_freeze_notify (G_OBJECT (mark));
line = moo_line_mark_get_line (mark);
moo_line_buffer_remove_mark (buffer->priv->line_buf, mark);
line_mark_deleted (buffer, mark);
g_object_thaw_notify (G_OBJECT (mark));
g_object_unref (mark);
}
@ -1766,6 +1788,7 @@ static void
line_mark_deleted (MooTextBuffer *buffer,
MooLineMark *mark)
{
_moo_line_mark_set_buffer (mark, NULL, NULL);
_moo_line_mark_deleted (mark);
g_signal_emit (buffer, signals[LINE_MARK_DELETED], 0, mark);
}