+#include "gtkprivate.h"
+#include "gtkintl.h"
+
+
+/**
+ * SECTION:gtktextmark
+ * @Short_description: A position in the buffer preserved across buffer modifications
+ * @Title: GtkTextMark
+ *
+ * You may wish to begin by reading the <link linkend="TextWidget">text widget
+ * conceptual overview</link> which gives an overview of all the objects and data
+ * types related to the text widget and how they work together.
+ *
+ * A #GtkTextMark is like a bookmark in a text buffer; it preserves a position in
+ * the text. You can convert the mark to an iterator using
+ * gtk_text_buffer_get_iter_at_mark(). Unlike iterators, marks remain valid across
+ * buffer mutations, because their behavior is defined when text is inserted or
+ * deleted. When text containing a mark is deleted, the mark remains in the
+ * position originally occupied by the deleted text. When text is inserted at a
+ * mark, a mark with <firstterm>left gravity</firstterm> will be moved to the
+ * beginning of the newly-inserted text, and a mark with <firstterm>right
+ * gravity</firstterm> will be moved to the end.
+ *
+ * <footnote>
+ * "left" and "right" here refer to logical direction (left is the toward the start
+ * of the buffer); in some languages such as Hebrew the logically-leftmost text is
+ * not actually on the left when displayed.
+ * </footnote>
+ *
+ * Marks are reference counted, but the reference count only controls the validity
+ * of the memory; marks can be deleted from the buffer at any time with
+ * gtk_text_buffer_delete_mark(). Once deleted from the buffer, a mark is
+ * essentially useless.
+ *
+ * Marks optionally have names; these can be convenient to avoid passing the
+ * #GtkTextMark object around.
+ *
+ * Marks are typically created using the gtk_text_buffer_create_mark() function.
+ */
+
+
+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)
+
+enum {
+ PROP_0,
+ PROP_NAME,
+ PROP_LEFT_GRAVITY
+};
+
+static void
+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
+gtk_text_mark_finalize (GObject *obj)
+{
+ GtkTextMark *mark;
+ GtkTextLineSegment *seg;
+
+ mark = GTK_TEXT_MARK (obj);
+
+ seg = mark->segment;
+
+ if (seg)
+ {
+ if (seg->body.mark.tree != NULL)
+ g_warning ("GtkTextMark being finalized while still in the buffer; "
+ "someone removed a reference they didn't own! Crash "
+ "impending");
+
+ g_free (seg->body.mark.name);
+ g_free (seg);
+
+ mark->segment = NULL;
+ }
+
+ /* chain parent_class' handler */
+ 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;