diff options
author | Matthias Clasen <mclasen@redhat.com> | 2007-05-26 04:10:42 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2007-05-26 04:10:42 +0000 |
commit | 6ac30db004c4a768aaf74286bcc21ff7123e0550 (patch) | |
tree | 15e8284ee1ef0b2905bf2c0f2d1f6ce60eea9c91 /gtk | |
parent | a7f95266a51e905b0fea0cfe43809023038a7428 (diff) | |
download | gtk+-6ac30db004c4a768aaf74286bcc21ff7123e0550.tar.gz |
Allow to separate GtkTextMark creation from buffer insertion. (#132818,
2007-05-25 Matthias Clasen <mclasen@redhat.com>
Allow to separate GtkTextMark creation from buffer insertion.
(#132818, Gustavo Giráldez, patch by Yevgen Muntyan)
* gtk/gtktextmarkprivate.h:
* gtk/gtktextmark.[hc] (gtk_text_mark_new): New function to
create a GtkTextMark.
* gtk/gtktextbuffer.[hc] (gtk_text_buffer_add_mark): New
function to add an existing mark to a buffer.
* gtk/gtktextbtree.c: Allow adding existing marks.
* gtk/gtk.symbols: Add new functions.
* tests/testtextbuffer.c: Add some tests for new mark
functionality.
svn path=/trunk/; revision=17922
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/gtk.symbols | 2 | ||||
-rw-r--r-- | gtk/gtktextbtree.c | 20 | ||||
-rw-r--r-- | gtk/gtktextbuffer.c | 50 | ||||
-rw-r--r-- | gtk/gtktextbuffer.h | 3 | ||||
-rw-r--r-- | gtk/gtktextmark.c | 170 | ||||
-rw-r--r-- | gtk/gtktextmark.h | 2 | ||||
-rw-r--r-- | gtk/gtktextmarkprivate.h | 5 |
7 files changed, 217 insertions, 35 deletions
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index 9f7e02fe15..5b28f13185 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -3552,6 +3552,7 @@ gtk_text_buffer_backspace gtk_text_buffer_begin_user_action gtk_text_buffer_copy_clipboard gtk_text_buffer_create_child_anchor +gtk_text_buffer_add_mark gtk_text_buffer_create_mark gtk_text_buffer_create_tag gtk_text_buffer_cut_clipboard @@ -3789,6 +3790,7 @@ gtk_text_line_segment_split #if IN_HEADER(__GTK_TEXT_MARK_H__) #if IN_FILE(__GTK_TEXT_MARK_C__) +gtk_text_mark_new gtk_text_mark_get_buffer gtk_text_mark_get_deleted gtk_text_mark_get_left_gravity diff --git a/gtk/gtktextbtree.c b/gtk/gtktextbtree.c index 7601803371..93f6b4b3d9 100644 --- a/gtk/gtktextbtree.c +++ b/gtk/gtktextbtree.c @@ -2692,7 +2692,12 @@ real_set_mark (GtkTextBTree *tree, g_return_val_if_fail (_gtk_text_iter_get_btree (where) == tree, NULL); if (existing_mark) - mark = existing_mark->segment; + { + if (gtk_text_mark_get_buffer (existing_mark) != NULL) + mark = existing_mark->segment; + else + mark = NULL; + } else if (name != NULL) mark = g_hash_table_lookup (tree->mark_table, name); @@ -2752,9 +2757,13 @@ real_set_mark (GtkTextBTree *tree, } else { - mark = _gtk_mark_segment_new (tree, - left_gravity, - name); + if (existing_mark) + g_object_ref (existing_mark); + else + existing_mark = gtk_text_mark_new (name, left_gravity); + + mark = existing_mark->segment; + _gtk_mark_segment_set_tree (mark, tree); mark->body.mark.line = _gtk_text_iter_get_text_line (&iter); @@ -2980,7 +2989,8 @@ gtk_text_mark_set_visible (GtkTextMark *mark, { seg->body.mark.visible = setting; - redisplay_mark (seg); + if (seg->body.mark.tree) + redisplay_mark (seg); } } diff --git a/gtk/gtktextbuffer.c b/gtk/gtktextbuffer.c index 20e34be08b..68364b60b1 100644 --- a/gtk/gtktextbuffer.c +++ b/gtk/gtktextbuffer.c @@ -2080,6 +2080,44 @@ gtk_text_buffer_create_mark (GtkTextBuffer *buffer, } /** + * gtk_text_buffer_add_mark: + * @buffer: a #GtkTextBuffer + * @mark: the mark to add + * @where: location to place mark + * + * Adds the mark at position @where. The mark must not be added to + * another buffer, and if its name is not %NULL then there must not + * be another mark in the buffer with the same name. + * + * Emits the "mark_set" signal as notification of the mark's initial + * placement. + * + * Since: 2.12 + **/ +void +gtk_text_buffer_add_mark (GtkTextBuffer *buffer, + GtkTextMark *mark, + const GtkTextIter *where) +{ + const gchar *name; + + g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer)); + g_return_if_fail (GTK_IS_TEXT_MARK (mark)); + g_return_if_fail (where != NULL); + g_return_if_fail (gtk_text_mark_get_buffer (mark) == NULL); + + name = gtk_text_mark_get_name (mark); + + if (name != NULL && gtk_text_buffer_get_mark (buffer, name) != NULL) + { + g_critical ("Mark %s already exists in the buffer", name); + return; + } + + gtk_text_buffer_set_mark (buffer, mark, NULL, where, FALSE, FALSE); +} + +/** * gtk_text_buffer_move_mark: * @buffer: a #GtkTextBuffer * @mark: a #GtkTextMark @@ -2129,13 +2167,13 @@ gtk_text_buffer_get_iter_at_mark (GtkTextBuffer *buffer, * * Deletes @mark, so that it's no longer located anywhere in the * buffer. Removes the reference the buffer holds to the mark, so if - * you haven't called g_object_ref () on the mark, it will be freed. Even + * you haven't called g_object_ref() on the mark, it will be freed. Even * if the mark isn't freed, most operations on @mark become - * invalid. There is no way to undelete a - * mark. gtk_text_mark_get_deleted () will return TRUE after this - * function has been called on a mark; gtk_text_mark_get_deleted () - * indicates that a mark no longer belongs to a buffer. The "mark_deleted" - * signal will be emitted as notification after the mark is deleted. + * invalid, until it gets added to a buffer again with + * gtk_text_buffer_add_mark(). Use gtk_text_mark_get_deleted() to + * find out if a mark has been removed from its buffer. + * The "mark_deleted" signal will be emitted as notification after + * the mark is deleted. **/ void gtk_text_buffer_delete_mark (GtkTextBuffer *buffer, diff --git a/gtk/gtktextbuffer.h b/gtk/gtktextbuffer.h index 715b514acf..9a0eb9d28e 100644 --- a/gtk/gtktextbuffer.h +++ b/gtk/gtktextbuffer.h @@ -247,6 +247,9 @@ GtkTextChildAnchor *gtk_text_buffer_create_child_anchor (GtkTextBuffer *buffer, GtkTextIter *iter); /* Mark manipulation */ +void gtk_text_buffer_add_mark (GtkTextBuffer *buffer, + GtkTextMark *mark, + const GtkTextIter *where); GtkTextMark *gtk_text_buffer_create_mark (GtkTextBuffer *buffer, const gchar *mark_name, const GtkTextIter *where, diff --git a/gtk/gtktextmark.c b/gtk/gtktextmark.c index 281538e3f9..febec6b4b3 100644 --- a/gtk/gtktextmark.c +++ b/gtk/gtktextmark.c @@ -50,18 +50,29 @@ #define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API #include <config.h> #include "gtktextbtree.h" +#include "gtkprivate.h" #include "gtkintl.h" #include "gtkalias.h" -static void gtk_text_mark_finalize (GObject *obj); +static void gtk_text_mark_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_text_mark_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void gtk_text_mark_finalize (GObject *object); + +static GtkTextLineSegment *gtk_mark_segment_new (GtkTextMark *mark_obj); G_DEFINE_TYPE (GtkTextMark, gtk_text_mark, G_TYPE_OBJECT) -static void -gtk_text_mark_init (GtkTextMark *mark) -{ - mark->segment = NULL; -} +enum { + PROP_0, + PROP_NAME, + PROP_LEFT_GRAVITY +}; static void gtk_text_mark_class_init (GtkTextMarkClass *klass) @@ -69,6 +80,30 @@ gtk_text_mark_class_init (GtkTextMarkClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = gtk_text_mark_finalize; + object_class->set_property = gtk_text_mark_set_property; + object_class->get_property = gtk_text_mark_get_property; + + g_object_class_install_property (object_class, + PROP_NAME, + g_param_spec_string ("name", + P_("Name"), + P_("Mark name"), + NULL, + GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, + PROP_LEFT_GRAVITY, + g_param_spec_boolean ("left-gravity", + P_("Left gravity"), + P_("Whether the mark has left gravity"), + FALSE, + GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + +static void +gtk_text_mark_init (GtkTextMark *mark) +{ + mark->segment = gtk_mark_segment_new (mark); } static void @@ -98,6 +133,88 @@ gtk_text_mark_finalize (GObject *obj) G_OBJECT_CLASS (gtk_text_mark_parent_class)->finalize (obj); } +static void +gtk_text_mark_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + gchar *tmp; + GtkTextMark *mark = GTK_TEXT_MARK (object); + GtkTextLineSegment *seg = mark->segment; + + switch (prop_id) + { + case PROP_NAME: + tmp = seg->body.mark.name; + seg->body.mark.name = g_value_dup_string (value); + g_free (tmp); + break; + + case PROP_LEFT_GRAVITY: + if (g_value_get_boolean (value)) + seg->type = >k_text_left_mark_type; + else + seg->type = >k_text_right_mark_type; + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +gtk_text_mark_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkTextMark *mark = GTK_TEXT_MARK (object); + + switch (prop_id) + { + case PROP_NAME: + g_value_set_string (value, gtk_text_mark_get_name (mark)); + break; + + case PROP_LEFT_GRAVITY: + g_value_set_boolean (value, gtk_text_mark_get_left_gravity (mark)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +/** + * gtk_text_mark_new: + * @name: mark name or %NULL + * @left_gravity: whether the mark should have left gravity + * + * Creates a text mark. Add it to a buffer using gtk_text_buffer_add_mark(). + * If @name is %NULL, the mark is anonymous; otherwise, the mark can be + * retrieved by name using gtk_text_buffer_get_mark(). If a mark has left + * gravity, and text is inserted at the mark's current location, the mark + * will be moved to the left of the newly-inserted text. If the mark has + * right gravity (@left_gravity = %FALSE), the mark will end up on the + * right of newly-inserted text. The standard left-to-right cursor is a + * mark with right gravity (when you type, the cursor stays on the right + * side of the text you're typing). + * + * Return value: new #GtkTextMark + * + * Since: 2.12 + **/ +GtkTextMark * +gtk_text_mark_new (const gchar *name, + gboolean left_gravity) +{ + return g_object_new (GTK_TYPE_TEXT_MARK, + "name", name, + "left-gravity", left_gravity, + NULL); +} + /** * gtk_text_mark_get_visible: * @mark: a #GtkTextMark @@ -140,8 +257,8 @@ gtk_text_mark_get_name (GtkTextMark *mark) * @mark: a #GtkTextMark * * Returns %TRUE if the mark has been removed from its buffer - * with gtk_text_buffer_delete_mark(). Marks can't be used - * once deleted. + * with gtk_text_buffer_delete_mark(). See gtk_text_buffer_add_mark() + * for a way to add it to a buffer again. * * Return value: whether the mark is deleted **/ @@ -212,28 +329,22 @@ gtk_text_mark_get_left_gravity (GtkTextMark *mark) + sizeof (GtkTextMarkBody))) -GtkTextLineSegment* -_gtk_mark_segment_new (GtkTextBTree *tree, - gboolean left_gravity, - const gchar *name) +static GtkTextLineSegment * +gtk_mark_segment_new (GtkTextMark *mark_obj) { GtkTextLineSegment *mark; mark = (GtkTextLineSegment *) g_malloc0 (MSEG_SIZE); - mark->body.mark.name = g_strdup (name); - - if (left_gravity) - mark->type = >k_text_left_mark_type; - else - mark->type = >k_text_right_mark_type; + mark->body.mark.name = NULL; + mark->type = >k_text_right_mark_type; mark->byte_count = 0; mark->char_count = 0; - mark->body.mark.obj = g_object_new (GTK_TYPE_TEXT_MARK, NULL); - mark->body.mark.obj->segment = mark; + mark->body.mark.obj = mark_obj; + mark_obj->segment = mark; - mark->body.mark.tree = tree; + mark->body.mark.tree = NULL; mark->body.mark.line = NULL; mark->next = NULL; @@ -243,6 +354,23 @@ _gtk_mark_segment_new (GtkTextBTree *tree, return mark; } +void +_gtk_mark_segment_set_tree (GtkTextLineSegment *mark, + GtkTextBTree *tree) +{ + g_assert (mark->body.mark.tree == NULL); + g_assert (mark->body.mark.obj != NULL); + + mark->byte_count = 0; + mark->char_count = 0; + + mark->body.mark.tree = tree; + mark->body.mark.line = NULL; + mark->next = NULL; + + mark->body.mark.not_deleteable = FALSE; +} + static int mark_segment_delete_func (GtkTextLineSegment *segPtr, GtkTextLine *line, int treeGone); diff --git a/gtk/gtktextmark.h b/gtk/gtktextmark.h index 851123c4ac..41bcb9492f 100644 --- a/gtk/gtktextmark.h +++ b/gtk/gtktextmark.h @@ -88,6 +88,8 @@ void gtk_text_mark_set_visible (GtkTextMark *mark, gboolean setting); gboolean gtk_text_mark_get_visible (GtkTextMark *mark); +GtkTextMark *gtk_text_mark_new (const gchar *name, + gboolean left_gravity); G_CONST_RETURN gchar* gtk_text_mark_get_name (GtkTextMark *mark); gboolean gtk_text_mark_get_deleted (GtkTextMark *mark); GtkTextBuffer* gtk_text_mark_get_buffer (GtkTextMark *mark); diff --git a/gtk/gtktextmarkprivate.h b/gtk/gtktextmarkprivate.h index 43e9797366..d2ff381371 100644 --- a/gtk/gtktextmarkprivate.h +++ b/gtk/gtktextmarkprivate.h @@ -49,9 +49,8 @@ struct _GtkTextMarkBody { guint not_deleteable : 1; }; -GtkTextLineSegment *_gtk_mark_segment_new (GtkTextBTree *tree, - gboolean left_gravity, - const gchar *name); +void _gtk_mark_segment_set_tree (GtkTextLineSegment *mark, + GtkTextBTree *tree); G_END_DECLS |