[gtksourceview/wip/marks-sequence] Implement private class GtkSourceMarksSequence
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview/wip/marks-sequence] Implement private class GtkSourceMarksSequence
- Date: Sun, 8 Sep 2013 17:42:15 +0000 (UTC)
commit 45b34e31bebace3adb7a2843fae24d5b4e894d22
Author: Sébastien Wilmet <swilmet gnome org>
Date: Sun Sep 8 15:25:55 2013 +0200
Implement private class GtkSourceMarksSequence
docs/reference/Makefile.am | 1 +
gtksourceview/Makefile.am | 2 +
gtksourceview/gtksourcemarkssequence.c | 322 ++++++++++++++++++++++++++++++++
gtksourceview/gtksourcemarkssequence.h | 76 ++++++++
gtksourceview/gtksourcetypes-private.h | 1 +
5 files changed, 402 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
index 8acf0b3..1987d7f 100644
--- a/docs/reference/Makefile.am
+++ b/docs/reference/Makefile.am
@@ -36,6 +36,7 @@ IGNORE_HFILES = \
gtksourcegutterrenderermarks.h \
gtksourcegutterrenderer-private.h \
gtksourcelanguage-private.h \
+ gtksourcemarkssequence.h \
gtksourcepixbufhelper.h \
gtksourceregex.h \
gtksourcestyle-private.h \
diff --git a/gtksourceview/Makefile.am b/gtksourceview/Makefile.am
index 735bfb6..e27d220 100644
--- a/gtksourceview/Makefile.am
+++ b/gtksourceview/Makefile.am
@@ -61,6 +61,7 @@ libgtksourceview_private_headers = \
gtksourcegutterrenderermarks.h \
gtksourcegutterrenderer-private.h \
gtksourcelanguage-private.h \
+ gtksourcemarkssequence.h \
gtksourcepixbufhelper.h \
gtksourceregex.h \
gtksourcestyle-private.h \
@@ -79,6 +80,7 @@ libgtksourceview_private_c_files = \
gtksourcegutterrenderermarks.c \
gtksourcelanguage-parser-1.c \
gtksourcelanguage-parser-2.c \
+ gtksourcemarkssequence.c \
gtksourcepixbufhelper.c \
gtksourceregex.c \
gtksourceundomanager.c \
diff --git a/gtksourceview/gtksourcemarkssequence.c b/gtksourceview/gtksourcemarkssequence.c
new file mode 100644
index 0000000..2046f85
--- /dev/null
+++ b/gtksourceview/gtksourcemarkssequence.c
@@ -0,0 +1,322 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
+/* gtksourcemarkssequence.c
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2013 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "gtksourcemarkssequence.h"
+
+/* An object for storing GtkTextMarks. The text marks are sorted internally with
+ * a GSequence. Going to the previous or next text mark has a O(1) complexity.
+ * Finding a text mark in the neighborhood of a text iter has a O(log n)
+ * complexity, with 'n' the number of marks in the sequence.
+ *
+ * The GSequenceIter associated to a text mark is inserted into the text mark,
+ * with g_object_set_qdata(). So the text mark knows its position in the
+ * GSequence. This allows to use normal GtkTextMarks in the API, instead of
+ * using a subclass or a custom iter.
+ */
+
+enum
+{
+ PROP_0,
+ PROP_BUFFER,
+};
+
+struct _GtkSourceMarksSequencePrivate
+{
+ GtkTextBuffer *buffer;
+ GSequence *seq;
+
+ /* The quark used for storing the GSequenceIter into the text mark, with
+ * g_object_set_qdata().
+ */
+ GQuark quark;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceMarksSequence, _gtk_source_marks_sequence, G_TYPE_OBJECT)
+
+static void
+remove_qdata (GtkTextMark *mark,
+ GtkSourceMarksSequence *seq)
+{
+ g_object_set_qdata (G_OBJECT (mark),
+ seq->priv->quark,
+ NULL);
+}
+
+static void
+free_sequence (GtkSourceMarksSequence *seq)
+{
+ if (seq->priv->seq != NULL)
+ {
+ g_sequence_foreach (seq->priv->seq,
+ (GFunc)remove_qdata,
+ seq);
+
+ g_sequence_free (seq->priv->seq);
+ seq->priv->seq = NULL;
+ }
+}
+
+static gint
+compare_marks (GtkTextMark *mark1,
+ GtkTextMark *mark2)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter iter1;
+ GtkTextIter iter2;
+
+ g_assert (GTK_IS_TEXT_MARK (mark1));
+ g_assert (GTK_IS_TEXT_MARK (mark2));
+
+ buffer = gtk_text_mark_get_buffer (mark1);
+
+ g_assert (buffer == gtk_text_mark_get_buffer (mark2));
+
+ gtk_text_buffer_get_iter_at_mark (buffer, &iter1, mark1);
+ gtk_text_buffer_get_iter_at_mark (buffer, &iter2, mark2);
+
+ return gtk_text_iter_compare (&iter1, &iter2);
+}
+
+static void
+mark_set_cb (GtkTextBuffer *buffer,
+ GtkTextIter *location,
+ GtkTextMark *mark,
+ GtkSourceMarksSequence *seq)
+{
+ GSequenceIter *seq_iter;
+
+ seq_iter = g_object_get_qdata (G_OBJECT (mark), seq->priv->quark);
+
+ if (seq_iter != NULL)
+ {
+ g_sequence_sort_changed (seq_iter,
+ (GCompareDataFunc)compare_marks,
+ NULL);
+ }
+}
+
+static void
+set_buffer (GtkSourceMarksSequence *seq,
+ GtkTextBuffer *buffer)
+{
+ g_assert (seq->priv->buffer == NULL);
+
+ seq->priv->buffer = g_object_ref (buffer);
+
+ g_signal_connect_object (buffer,
+ "mark-set",
+ G_CALLBACK (mark_set_cb),
+ seq,
+ 0);
+}
+
+static void
+_gtk_source_marks_sequence_dispose (GObject *object)
+{
+ GtkSourceMarksSequence *seq = GTK_SOURCE_MARKS_SEQUENCE (object);
+
+ g_clear_object (&seq->priv->buffer);
+
+ free_sequence (seq);
+
+ G_OBJECT_CLASS (_gtk_source_marks_sequence_parent_class)->dispose (object);
+}
+
+static void
+_gtk_source_marks_sequence_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceMarksSequence *seq;
+
+ g_return_if_fail (GTK_SOURCE_IS_MARKS_SEQUENCE (object));
+
+ seq = GTK_SOURCE_MARKS_SEQUENCE (object);
+
+ switch (prop_id)
+ {
+ case PROP_BUFFER:
+ g_value_set_object (value, seq->priv->buffer);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+_gtk_source_marks_sequence_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceMarksSequence *seq;
+
+ g_return_if_fail (GTK_SOURCE_IS_MARKS_SEQUENCE (object));
+
+ seq = GTK_SOURCE_MARKS_SEQUENCE (object);
+
+ switch (prop_id)
+ {
+ case PROP_BUFFER:
+ set_buffer (seq, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+_gtk_source_marks_sequence_class_init (GtkSourceMarksSequenceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = _gtk_source_marks_sequence_dispose;
+ object_class->get_property = _gtk_source_marks_sequence_get_property;
+ object_class->set_property = _gtk_source_marks_sequence_set_property;
+
+ g_object_class_install_property (object_class,
+ PROP_BUFFER,
+ g_param_spec_object ("buffer",
+ "Buffer",
+ "The text buffer",
+ GTK_TYPE_TEXT_BUFFER,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+_gtk_source_marks_sequence_init (GtkSourceMarksSequence *seq)
+{
+ gchar *unique_str;
+
+ seq->priv = _gtk_source_marks_sequence_get_instance_private (seq);
+
+ seq->priv->seq = g_sequence_new ((GDestroyNotify)g_object_unref);
+
+ unique_str = g_strdup_printf ("gtk-source-marks-sequence-%p", seq);
+ seq->priv->quark = g_quark_from_string (unique_str);
+ g_free (unique_str);
+}
+
+GtkSourceMarksSequence *
+_gtk_source_marks_sequence_new (GtkTextBuffer *buffer)
+{
+ g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
+
+ return g_object_new (GTK_SOURCE_TYPE_MARKS_SEQUENCE,
+ "buffer", buffer,
+ NULL);
+}
+
+void
+_gtk_source_marks_sequence_add (GtkSourceMarksSequence *seq,
+ GtkTextMark *mark)
+{
+ GSequenceIter *seq_iter;
+
+ g_return_if_fail (GTK_SOURCE_IS_MARKS_SEQUENCE (seq));
+ g_return_if_fail (GTK_IS_TEXT_MARK (mark));
+ g_return_if_fail (gtk_text_mark_get_buffer (mark) == seq->priv->buffer);
+
+ seq_iter = g_object_get_qdata (G_OBJECT (mark), seq->priv->quark);
+
+ if (seq_iter != NULL)
+ {
+ /* The mark is already added. */
+ return;
+ }
+
+ seq_iter = g_sequence_insert_sorted (seq->priv->seq,
+ mark,
+ (GCompareDataFunc)compare_marks,
+ NULL);
+
+ g_object_ref (mark);
+ g_object_set_qdata (G_OBJECT (mark),
+ seq->priv->quark,
+ seq_iter);
+}
+
+void
+_gtk_source_marks_sequence_remove (GtkSourceMarksSequence *seq,
+ GtkTextMark *mark)
+{
+ GSequenceIter *seq_iter;
+
+ g_return_if_fail (GTK_SOURCE_IS_MARKS_SEQUENCE (seq));
+ g_return_if_fail (GTK_IS_TEXT_MARK (mark));
+ g_return_if_fail (gtk_text_mark_get_buffer (mark) == seq->priv->buffer);
+
+ seq_iter = g_object_get_qdata (G_OBJECT (mark), seq->priv->quark);
+
+ if (seq_iter != NULL)
+ {
+ g_object_set_qdata (G_OBJECT (mark), seq->priv->quark, NULL);
+ g_sequence_remove (seq_iter);
+ }
+}
+
+GtkTextMark *
+_gtk_source_marks_sequence_next (GtkSourceMarksSequence *seq,
+ GtkTextMark *mark)
+{
+ GSequenceIter *seq_iter;
+
+ g_return_val_if_fail (GTK_SOURCE_IS_MARKS_SEQUENCE (seq), NULL);
+ g_return_val_if_fail (GTK_IS_TEXT_MARK (mark), NULL);
+ g_return_val_if_fail (gtk_text_mark_get_buffer (mark) == seq->priv->buffer, NULL);
+
+ seq_iter = g_object_get_qdata (G_OBJECT (mark), seq->priv->quark);
+
+ g_return_val_if_fail (seq_iter != NULL, NULL);
+
+ seq_iter = g_sequence_iter_next (seq_iter);
+
+ return g_sequence_iter_is_end (seq_iter) ? NULL : g_sequence_get (seq_iter);
+}
+
+GtkTextMark *
+_gtk_source_marks_sequence_prev (GtkSourceMarksSequence *seq,
+ GtkTextMark *mark)
+{
+ GSequenceIter *seq_iter;
+
+ g_return_val_if_fail (GTK_SOURCE_IS_MARKS_SEQUENCE (seq), NULL);
+ g_return_val_if_fail (GTK_IS_TEXT_MARK (mark), NULL);
+ g_return_val_if_fail (gtk_text_mark_get_buffer (mark) == seq->priv->buffer, NULL);
+
+ seq_iter = g_object_get_qdata (G_OBJECT (mark), seq->priv->quark);
+
+ g_return_val_if_fail (seq_iter != NULL, NULL);
+
+ if (g_sequence_iter_is_begin (seq_iter))
+ {
+ return NULL;
+ }
+
+ seq_iter = g_sequence_iter_prev (seq_iter);
+
+ return g_sequence_get (seq_iter);
+}
diff --git a/gtksourceview/gtksourcemarkssequence.h b/gtksourceview/gtksourcemarkssequence.h
new file mode 100644
index 0000000..5bed4b0
--- /dev/null
+++ b/gtksourceview/gtksourcemarkssequence.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
+/* gtksourcemarkssequence.h
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2013 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __GTK_SOURCE_MARKS_SEQUENCE_H__
+#define __GTK_SOURCE_MARKS_SEQUENCE_H__
+
+#include <gtk/gtk.h>
+#include "gtksourcetypes-private.h"
+
+G_BEGIN_DECLS
+
+#define GTK_SOURCE_TYPE_MARKS_SEQUENCE (_gtk_source_marks_sequence_get_type ())
+#define GTK_SOURCE_MARKS_SEQUENCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
GTK_SOURCE_TYPE_MARKS_SEQUENCE, GtkSourceMarksSequence))
+#define GTK_SOURCE_MARKS_SEQUENCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),
GTK_SOURCE_TYPE_MARKS_SEQUENCE, GtkSourceMarksSequenceClass))
+#define GTK_SOURCE_IS_MARKS_SEQUENCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
GTK_SOURCE_TYPE_MARKS_SEQUENCE))
+#define GTK_SOURCE_IS_MARKS_SEQUENCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),
GTK_SOURCE_TYPE_MARKS_SEQUENCE))
+#define GTK_SOURCE_MARKS_SEQUENCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),
GTK_SOURCE_TYPE_MARKS_SEQUENCE, GtkSourceMarksSequenceClass))
+
+typedef struct _GtkSourceMarksSequenceClass GtkSourceMarksSequenceClass;
+typedef struct _GtkSourceMarksSequencePrivate GtkSourceMarksSequencePrivate;
+
+struct _GtkSourceMarksSequence
+{
+ GObject parent;
+
+ GtkSourceMarksSequencePrivate *priv;
+};
+
+struct _GtkSourceMarksSequenceClass
+{
+ GObjectClass parent_class;
+};
+
+G_GNUC_INTERNAL
+GType _gtk_source_marks_sequence_get_type (void) G_GNUC_CONST;
+
+G_GNUC_INTERNAL
+GtkSourceMarksSequence *_gtk_source_marks_sequence_new (GtkTextBuffer *buffer);
+
+G_GNUC_INTERNAL
+void _gtk_source_marks_sequence_add (GtkSourceMarksSequence *seq,
+ GtkTextMark *mark);
+
+G_GNUC_INTERNAL
+void _gtk_source_marks_sequence_remove (GtkSourceMarksSequence *seq,
+ GtkTextMark *mark);
+
+G_GNUC_INTERNAL
+GtkTextMark *_gtk_source_marks_sequence_next (GtkSourceMarksSequence *seq,
+ GtkTextMark *mark);
+
+G_GNUC_INTERNAL
+GtkTextMark *_gtk_source_marks_sequence_prev (GtkSourceMarksSequence *seq,
+ GtkTextMark *mark);
+
+G_END_DECLS
+
+#endif /* __GTK_SOURCE_MARKS_SEQUENCE_H__ */
diff --git a/gtksourceview/gtksourcetypes-private.h b/gtksourceview/gtksourcetypes-private.h
index 6b88c2c..afb1c8a 100644
--- a/gtksourceview/gtksourcetypes-private.h
+++ b/gtksourceview/gtksourcetypes-private.h
@@ -32,6 +32,7 @@ typedef struct _GtkSourceContextEngine GtkSourceContextEngine;
typedef struct _GtkSourceEngine GtkSourceEngine;
typedef struct _GtkSourceGutterRendererLines GtkSourceGutterRendererLines;
typedef struct _GtkSourceGutterRendererMarks GtkSourceGutterRendererMarks;
+typedef struct _GtkSourceMarksSequence GtkSourceMarksSequence;
typedef struct _GtkSourcePixbufHelper GtkSourcePixbufHelper;
typedef struct _GtkSourceRegex GtkSourceRegex;
typedef struct _GtkSourceUndoManagerDefault GtkSourceUndoManagerDefault;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]