1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
2 /* gtksourcemark.c
3  * This file is part of GtkSourceView
4  *
5  * Copyright (C) 2007 - Johannes Schmid <jhs@gnome.org>
6  *
7  * GtkSourceView is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * GtkSourceView is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 
26 #include "gtksourcemark.h"
27 #include "gtksourcebuffer.h"
28 #include "gtksourcebuffer-private.h"
29 #include "gtksourceview-i18n.h"
30 
31 /**
32  * SECTION:mark
33  * @Short_description: Mark object for GtkSourceBuffer
34  * @Title: GtkSourceMark
35  * @See_also: #GtkSourceBuffer
36  *
37  * A #GtkSourceMark marks a position in the text where you want to display
38  * additional info. It is based on #GtkTextMark and thus is still valid after
39  * the text has changed though its position may change.
40  *
41  * #GtkSourceMark<!-- -->s are organised in categories which you have to set
42  * when you create the mark. Each category can have a priority, a pixbuf and
43  * other associated attributes. See gtk_source_view_set_mark_attributes().
44  * The pixbuf will be displayed in the margin at the line where the mark
45  * residents if the #GtkSourceView:show-line-marks property is set to %TRUE. If
46  * there are multiple marks in the same line, the pixbufs will be drawn on top
47  * of each other. The mark with the highest priority will be drawn on top.
48  */
49 
50 enum
51 {
52 	PROP_0,
53 	PROP_CATEGORY
54 };
55 
56 struct _GtkSourceMarkPrivate
57 {
58 	gchar *category;
59 };
60 
61 G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceMark, gtk_source_mark, GTK_TYPE_TEXT_MARK);
62 
63 static void
gtk_source_mark_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)64 gtk_source_mark_set_property (GObject      *object,
65 			      guint         prop_id,
66 			      const GValue *value,
67 			      GParamSpec   *pspec)
68 {
69 	GtkSourceMarkPrivate *priv;
70 
71 	g_return_if_fail (GTK_SOURCE_IS_MARK (object));
72 
73 	priv = GTK_SOURCE_MARK (object)->priv;
74 
75 	switch (prop_id)
76 	{
77 		case PROP_CATEGORY:
78 			g_return_if_fail (g_value_get_string (value) != NULL);
79 			g_free (priv->category);
80 			priv->category = g_value_dup_string (value);
81 			break;
82 		default:
83 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
84 							   prop_id,
85 							   pspec);
86 	}
87 }
88 
89 static void
gtk_source_mark_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)90 gtk_source_mark_get_property (GObject    *object,
91 			      guint       prop_id,
92 			      GValue     *value,
93 			      GParamSpec *pspec)
94 {
95 	GtkSourceMark *mark;
96 
97 	g_return_if_fail (GTK_SOURCE_IS_MARK (object));
98 
99 	mark = GTK_SOURCE_MARK (object);
100 
101 	switch (prop_id)
102 	{
103 		case PROP_CATEGORY:
104 			g_value_set_string (value,
105 					    gtk_source_mark_get_category (mark));
106 			break;
107 		default:
108 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
109 							   prop_id,
110 							   pspec);
111 	}
112 }
113 
114 static void
gtk_source_mark_finalize(GObject * object)115 gtk_source_mark_finalize (GObject *object)
116 {
117 	GtkSourceMark *mark = GTK_SOURCE_MARK (object);
118 
119 	g_free (mark->priv->category);
120 
121 	G_OBJECT_CLASS (gtk_source_mark_parent_class)->finalize (object);
122 }
123 
124 static void
gtk_source_mark_class_init(GtkSourceMarkClass * klass)125 gtk_source_mark_class_init (GtkSourceMarkClass *klass)
126 {
127 	GObjectClass *object_class;
128 
129 	object_class = G_OBJECT_CLASS (klass);
130 
131 	object_class->set_property = gtk_source_mark_set_property;
132 	object_class->get_property = gtk_source_mark_get_property;
133 	object_class->finalize = gtk_source_mark_finalize;
134 
135 	/**
136 	 * GtkSourceMark:category:
137 	 *
138 	 * The category of the #GtkSourceMark, classifies the mark and controls
139 	 * which pixbuf is used and with which priority it is drawn.
140 	 */
141 	g_object_class_install_property (object_class,
142 					 PROP_CATEGORY,
143 					 g_param_spec_string ("category",
144 							      "Category",
145 							      "The mark category",
146 							      NULL,
147 							      G_PARAM_READWRITE |
148 							      G_PARAM_CONSTRUCT_ONLY |
149 							      G_PARAM_STATIC_STRINGS));
150 }
151 
152 static void
gtk_source_mark_init(GtkSourceMark * mark)153 gtk_source_mark_init (GtkSourceMark *mark)
154 {
155 	mark->priv = gtk_source_mark_get_instance_private (mark);
156 }
157 
158 /**
159  * gtk_source_mark_new:
160  * @name: Name of the #GtkSourceMark, can be NULL when not using a name
161  * @category: is used to classify marks according to common characteristics
162  * (e.g. all the marks representing a bookmark could belong to the "bookmark"
163  * category, or all the marks representing a compilation error could belong to
164  * "error" category).
165  *
166  * Creates a text mark. Add it to a buffer using gtk_text_buffer_add_mark().
167  * If name is NULL, the mark is anonymous; otherwise, the mark can be retrieved
168  * by name using gtk_text_buffer_get_mark().
169  * Normally marks are created using the utility function
170  * gtk_source_buffer_create_source_mark().
171  *
172  * Returns: a new #GtkSourceMark that can be added using gtk_text_buffer_add_mark().
173  *
174  * Since: 2.2
175  */
176 GtkSourceMark *
gtk_source_mark_new(const gchar * name,const gchar * category)177 gtk_source_mark_new (const gchar *name,
178 		     const gchar *category)
179 {
180 	g_return_val_if_fail (category != NULL, NULL);
181 
182 	return GTK_SOURCE_MARK (g_object_new (GTK_SOURCE_TYPE_MARK,
183 					      "category", category,
184 					      "name", name,
185 					      "left-gravity", TRUE,
186 					       NULL));
187 }
188 
189 /**
190  * gtk_source_mark_get_category:
191  * @mark: a #GtkSourceMark.
192  *
193  * Returns the mark category.
194  *
195  * Returns: the category of the #GtkSourceMark.
196  *
197  * Since: 2.2
198  */
199 const gchar *
gtk_source_mark_get_category(GtkSourceMark * mark)200 gtk_source_mark_get_category (GtkSourceMark *mark)
201 {
202 	g_return_val_if_fail (GTK_SOURCE_IS_MARK (mark), NULL);
203 
204 	return mark->priv->category;
205 }
206 
207 /**
208  * gtk_source_mark_next:
209  * @mark: a #GtkSourceMark.
210  * @category: (nullable): a string specifying the mark category, or %NULL.
211  *
212  * Returns the next #GtkSourceMark in the buffer or %NULL if the mark
213  * was not added to a buffer. If there is no next mark, %NULL will be returned.
214  *
215  * If @category is %NULL, looks for marks of any category.
216  *
217  * Returns: (nullable) (transfer none): the next #GtkSourceMark, or %NULL.
218  *
219  * Since: 2.2
220  */
221 GtkSourceMark *
gtk_source_mark_next(GtkSourceMark * mark,const gchar * category)222 gtk_source_mark_next (GtkSourceMark *mark,
223 		      const gchar   *category)
224 {
225 	GtkTextBuffer *buffer;
226 
227 	g_return_val_if_fail (GTK_SOURCE_IS_MARK (mark), NULL);
228 
229 	buffer = gtk_text_mark_get_buffer (GTK_TEXT_MARK (mark));
230 
231 	if (buffer == NULL)
232 	{
233 		return NULL;
234 	}
235 
236 	return _gtk_source_buffer_source_mark_next (GTK_SOURCE_BUFFER (buffer),
237 						    mark,
238 						    category);
239 }
240 
241 /**
242  * gtk_source_mark_prev:
243  * @mark: a #GtkSourceMark.
244  * @category: a string specifying the mark category, or %NULL.
245  *
246  * Returns the previous #GtkSourceMark in the buffer or %NULL if the mark
247  * was not added to a buffer. If there is no previous mark, %NULL is returned.
248  *
249  * If @category is %NULL, looks for marks of any category
250  *
251  * Returns: (nullable) (transfer none): the previous #GtkSourceMark, or %NULL.
252  *
253  * Since: 2.2
254  */
255 GtkSourceMark *
gtk_source_mark_prev(GtkSourceMark * mark,const gchar * category)256 gtk_source_mark_prev (GtkSourceMark *mark,
257 		      const gchar   *category)
258 {
259 	GtkTextBuffer *buffer;
260 
261 	g_return_val_if_fail (GTK_SOURCE_IS_MARK (mark), NULL);
262 
263 	buffer = gtk_text_mark_get_buffer (GTK_TEXT_MARK (mark));
264 
265 	if (buffer == NULL)
266 	{
267 		return NULL;
268 	}
269 
270 	return _gtk_source_buffer_source_mark_prev (GTK_SOURCE_BUFFER (buffer),
271 						    mark,
272 						    category);
273 }
274 
275