1 /***************************************************************************
2  *            sourceview-cell.c
3  *
4  *  So Mai 21 14:44:13 2006
5  *  Copyright  2006  Johannes Schmid
6  *  jhs@cvs.gnome.org
7  ***************************************************************************/
8 
9 /*
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU Library General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  */
24 
25 #include "sourceview-cell.h"
26 
27 #include <libanjuta/interfaces/ianjuta-editor-cell.h>
28 #include <libanjuta/interfaces/ianjuta-editor-cell-style.h>
29 #include <libanjuta/interfaces/ianjuta-iterable.h>
30 #include <libanjuta/anjuta-utils.h>
31 #include <libanjuta/anjuta-debug.h>
32 
33 #include <gtk/gtk.h>
34 #include <string.h>
35 #include <gtksourceview/gtksource.h>
36 
37 static void sourceview_cell_class_init(SourceviewCellClass *klass);
38 static void sourceview_cell_instance_init(SourceviewCell *sp);
39 static void sourceview_cell_finalize(GObject *object);
40 
41 struct _SourceviewCellPrivate {
42 	GtkTextView* view;
43 	GtkTextBuffer* buffer;
44 
45 	gint offset;
46 };
47 
48 static gpointer sourceview_cell_parent_class = NULL;
49 
50 /**
51  * sourceview_cell_update_offset:
52  * @cell: self
53  *
54  * Update the internal offset
55  */
56 static void
sourceview_cell_update_offset(SourceviewCell * cell,GtkTextIter * iter)57 sourceview_cell_update_offset (SourceviewCell* cell, GtkTextIter* iter)
58 {
59 	cell->priv->offset = gtk_text_iter_get_offset (iter);
60 }
61 
62 /**
63  * sourceview_cell_get_iter:
64  * @cell: self
65  * @iter: iterator to set
66  * Get the iterator for cell
67  */
68 void
sourceview_cell_get_iter(SourceviewCell * cell,GtkTextIter * iter)69 sourceview_cell_get_iter (SourceviewCell* cell, GtkTextIter* iter)
70 {
71 	gtk_text_buffer_get_iter_at_offset (cell->priv->buffer,
72 	                                    iter,
73 	                                    cell->priv->offset);
74 }
75 
76 static void
sourceview_cell_class_init(SourceviewCellClass * klass)77 sourceview_cell_class_init(SourceviewCellClass *klass)
78 {
79 	GObjectClass *object_class = G_OBJECT_CLASS(klass);
80 	sourceview_cell_parent_class = g_type_class_peek_parent(klass);
81 
82 
83 	object_class->finalize = sourceview_cell_finalize;
84 }
85 
86 static void
sourceview_cell_instance_init(SourceviewCell * obj)87 sourceview_cell_instance_init(SourceviewCell *obj)
88 {
89 	obj->priv = g_slice_new0(SourceviewCellPrivate);
90 
91 	/* Initialize private members, etc. */
92 }
93 
94 static void
sourceview_cell_finalize(GObject * object)95 sourceview_cell_finalize(GObject *object)
96 {
97 	SourceviewCell *cobj;
98 	cobj = SOURCEVIEW_CELL(object);
99 
100 	g_slice_free(SourceviewCellPrivate, cobj->priv);
101 	G_OBJECT_CLASS(sourceview_cell_parent_class)->finalize(object);
102 }
103 
104 SourceviewCell *
sourceview_cell_new(GtkTextIter * iter,GtkTextView * view)105 sourceview_cell_new(GtkTextIter* iter, GtkTextView* view)
106 {
107 	SourceviewCell *obj;
108 
109 	obj = SOURCEVIEW_CELL(g_object_new(SOURCEVIEW_TYPE_CELL, NULL));
110 
111 	obj->priv->buffer = gtk_text_view_get_buffer(view);
112 	obj->priv->view = view;
113 	obj->priv->offset = gtk_text_iter_get_offset (iter);
114 
115 	return obj;
116 }
117 
118 static gchar*
icell_get_character(IAnjutaEditorCell * icell,GError ** e)119 icell_get_character(IAnjutaEditorCell* icell, GError** e)
120 {
121 	SourceviewCell* cell = SOURCEVIEW_CELL(icell);
122 	GtkTextIter iter;
123 	sourceview_cell_get_iter (cell, &iter);
124 	gunichar c = gtk_text_iter_get_char (&iter);
125 	gchar* outbuf = g_new0(gchar, 6);
126 	g_unichar_to_utf8 (c, outbuf);
127 	return outbuf;
128 }
129 
130 static gint
icell_get_length(IAnjutaEditorCell * icell,GError ** e)131 icell_get_length(IAnjutaEditorCell* icell, GError** e)
132 {
133 	gchar* text = icell_get_character(icell, e);
134 	gint retval = 0;
135 	if (text)
136 		retval = g_utf8_strlen (text, -1);
137 	g_free(text);
138 	return retval;
139 }
140 
141 static gchar
icell_get_char(IAnjutaEditorCell * icell,gint index,GError ** e)142 icell_get_char(IAnjutaEditorCell* icell, gint index, GError** e)
143 {
144 	SourceviewCell* cell = SOURCEVIEW_CELL(icell);
145 	GtkTextIter iter;
146 	sourceview_cell_get_iter (cell, &iter);
147 	gunichar c = gtk_text_iter_get_char (&iter);
148 	gchar* outbuf = g_new0(gchar, 6);
149 	gint len = g_unichar_to_utf8 (c, outbuf);
150 	gchar retval;
151 	if (index < len)
152 		retval = outbuf[index];
153 	else
154 		retval = 0;
155 	g_free (outbuf);
156 	return retval;
157 }
158 
159 static IAnjutaEditorAttribute
icell_get_attribute(IAnjutaEditorCell * icell,GError ** e)160 icell_get_attribute (IAnjutaEditorCell* icell, GError **e)
161 {
162 	IAnjutaEditorAttribute attrib = IANJUTA_EDITOR_TEXT;
163 	GtkTextIter iter;
164 	SourceviewCell* cell = SOURCEVIEW_CELL(icell);
165 
166 	sourceview_cell_get_iter (cell, &iter);
167 
168 	if (gtk_source_buffer_iter_has_context_class (GTK_SOURCE_BUFFER(cell->priv->buffer), &iter, "string"))
169 		attrib = IANJUTA_EDITOR_STRING;
170 	else if (gtk_source_buffer_iter_has_context_class (GTK_SOURCE_BUFFER(cell->priv->buffer), &iter, "comment"))
171 		attrib = IANJUTA_EDITOR_COMMENT;
172 	else if (gtk_source_buffer_iter_has_context_class (GTK_SOURCE_BUFFER(cell->priv->buffer), &iter, "keyword"))
173 		attrib = IANJUTA_EDITOR_KEYWORD;
174 
175 	return attrib;
176 }
177 
178 static void
icell_iface_init(IAnjutaEditorCellIface * iface)179 icell_iface_init(IAnjutaEditorCellIface* iface)
180 {
181 	iface->get_character = icell_get_character;
182 	iface->get_char = icell_get_char;
183 	iface->get_length = icell_get_length;
184 	iface->get_attribute = icell_get_attribute;
185 }
186 
187 static gboolean
iiter_first(IAnjutaIterable * iiter,GError ** e)188 iiter_first(IAnjutaIterable* iiter, GError** e)
189 {
190 	SourceviewCell* cell = SOURCEVIEW_CELL(iiter);
191 	cell->priv->offset = 0;
192 	return TRUE;
193 }
194 
195 static gboolean
iiter_next(IAnjutaIterable * iiter,GError ** e)196 iiter_next(IAnjutaIterable* iiter, GError** e)
197 {
198 	SourceviewCell* cell = SOURCEVIEW_CELL(iiter);
199 	GtkTextIter iter;
200 	gboolean retval;
201 	sourceview_cell_get_iter (cell, &iter);
202 	retval = gtk_text_iter_forward_char (&iter);
203 	sourceview_cell_update_offset (cell, &iter);
204 
205 	return retval;
206 }
207 
208 static gboolean
iiter_previous(IAnjutaIterable * iiter,GError ** e)209 iiter_previous(IAnjutaIterable* iiter, GError** e)
210 {
211 	SourceviewCell* cell = SOURCEVIEW_CELL(iiter);
212 	if (cell->priv->offset > 0)
213 	{
214 		cell->priv->offset--;
215 		return TRUE;
216 	}
217 
218 	return FALSE;
219 }
220 
221 static gboolean
iiter_last(IAnjutaIterable * iiter,GError ** e)222 iiter_last(IAnjutaIterable* iiter, GError** e)
223 {
224 	SourceviewCell* cell = SOURCEVIEW_CELL(iiter);
225 	cell->priv->offset = -1;
226 	return TRUE;
227 }
228 
229 static void
iiter_foreach(IAnjutaIterable * iiter,GFunc callback,gpointer data,GError ** e)230 iiter_foreach(IAnjutaIterable* iiter, GFunc callback, gpointer data, GError** e)
231 {
232 	SourceviewCell* cell = SOURCEVIEW_CELL(iiter);
233 	gint old_offset = cell->priv->offset;
234 
235 	iiter_first (IANJUTA_ITERABLE(cell), NULL);
236 
237 	while (iiter_next(IANJUTA_ITERABLE(cell), NULL))
238 	{
239 		(*callback)(cell, data);
240 	}
241 	cell->priv->offset = old_offset;
242 }
243 
244 static gboolean
iiter_set_position(IAnjutaIterable * iiter,gint position,GError ** e)245 iiter_set_position (IAnjutaIterable* iiter, gint position, GError** e)
246 {
247 	SourceviewCell* cell = SOURCEVIEW_CELL(iiter);
248 	cell->priv->offset = position;
249 	return TRUE;
250 }
251 
252 static gint
iiter_get_position(IAnjutaIterable * iiter,GError ** e)253 iiter_get_position(IAnjutaIterable* iiter, GError** e)
254 {
255 	SourceviewCell* cell = SOURCEVIEW_CELL(iiter);
256 	return cell->priv->offset;
257 }
258 
259 static gint
iiter_get_length(IAnjutaIterable * iiter,GError ** e)260 iiter_get_length(IAnjutaIterable* iiter, GError** e)
261 {
262 	SourceviewCell* cell = SOURCEVIEW_CELL(iiter);
263 
264 	return gtk_text_buffer_get_char_count (cell->priv->buffer);
265 }
266 
267 static IAnjutaIterable *
iiter_clone(IAnjutaIterable * iiter,GError ** e)268 iiter_clone (IAnjutaIterable *iiter, GError **e)
269 {
270 	SourceviewCell* cell = SOURCEVIEW_CELL(iiter);
271 	GtkTextIter iter;
272 	sourceview_cell_get_iter (cell, &iter);
273 	return IANJUTA_ITERABLE (sourceview_cell_new (&iter, cell->priv->view));
274 }
275 
276 static void
iiter_assign(IAnjutaIterable * iiter,IAnjutaIterable * src_iter,GError ** e)277 iiter_assign (IAnjutaIterable *iiter, IAnjutaIterable *src_iter, GError **e)
278 {
279 	SourceviewCell* cell = SOURCEVIEW_CELL(iiter);
280 	SourceviewCell* src_cell = SOURCEVIEW_CELL(src_iter);
281 	cell->priv->offset = src_cell->priv->offset;
282 }
283 
284 static gint
iiter_compare(IAnjutaIterable * iiter,IAnjutaIterable * iother_iter,GError ** e)285 iiter_compare (IAnjutaIterable *iiter, IAnjutaIterable *iother_iter, GError **e)
286 {
287 	SourceviewCell* cell = SOURCEVIEW_CELL(iiter);
288 	SourceviewCell* other_cell = SOURCEVIEW_CELL(iother_iter);
289 
290 	GtkTextIter iter;
291 	GtkTextIter other_iter;
292 
293 	sourceview_cell_get_iter (cell, &iter);
294 	sourceview_cell_get_iter (other_cell, &other_iter);
295 
296 	return gtk_text_iter_compare (&iter, &other_iter);
297 }
298 
299 static gint
iiter_diff(IAnjutaIterable * iiter,IAnjutaIterable * iother_iter,GError ** e)300 iiter_diff (IAnjutaIterable *iiter, IAnjutaIterable *iother_iter, GError **e)
301 {
302 	SourceviewCell* cell = SOURCEVIEW_CELL(iiter);
303 	SourceviewCell* other_cell = SOURCEVIEW_CELL(iother_iter);
304 
305 	return (other_cell->priv->offset - cell->priv->offset);
306 }
307 
308 static void
iiter_iface_init(IAnjutaIterableIface * iface)309 iiter_iface_init(IAnjutaIterableIface* iface)
310 {
311 	iface->first = iiter_first;
312 	iface->next = iiter_next;
313 	iface->previous = iiter_previous;
314 	iface->last = iiter_last;
315 	iface->foreach = iiter_foreach;
316 	iface->set_position = iiter_set_position;
317 	iface->get_position = iiter_get_position;
318 	iface->get_length = iiter_get_length;
319 	iface->assign = iiter_assign;
320 	iface->clone = iiter_clone;
321 	iface->diff = iiter_diff;
322 	iface->compare = iiter_compare;
323 }
324 
325 
326 ANJUTA_TYPE_BEGIN(SourceviewCell, sourceview_cell, G_TYPE_OBJECT);
327 ANJUTA_TYPE_ADD_INTERFACE(icell, IANJUTA_TYPE_EDITOR_CELL);
328 ANJUTA_TYPE_ADD_INTERFACE(iiter, IANJUTA_TYPE_ITERABLE);
329 ANJUTA_TYPE_END;
330