]> Pileus Git - ~andy/gtk/blob - gtk/gtktextmark.c
Docs (gtk_text_tag_table_size): return a signed int
[~andy/gtk] / gtk / gtktextmark.c
1 /* gtktextmark.c - mark segments
2  *
3  * Copyright (c) 1994 The Regents of the University of California.
4  * Copyright (c) 1994-1997 Sun Microsystems, Inc.
5  * Copyright (c) 2000      Red Hat, Inc.
6  * Tk -> Gtk port by Havoc Pennington <hp@redhat.com>
7  *
8  * This software is copyrighted by the Regents of the University of
9  * California, Sun Microsystems, Inc., and other parties.  The
10  * following terms apply to all files associated with the software
11  * unless explicitly disclaimed in individual files.
12  *
13  * The authors hereby grant permission to use, copy, modify,
14  * distribute, and license this software and its documentation for any
15  * purpose, provided that existing copyright notices are retained in
16  * all copies and that this notice is included verbatim in any
17  * distributions. No written agreement, license, or royalty fee is
18  * required for any of the authorized uses.  Modifications to this
19  * software may be copyrighted by their authors and need not follow
20  * the licensing terms described here, provided that the new terms are
21  * clearly indicated on the first page of each file where they apply.
22  *
23  * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY
24  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
25  * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION,
26  * OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED
27  * OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
30  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
31  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
32  * NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
33  * AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
34  * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
35  *
36  * GOVERNMENT USE: If you are acquiring this software on behalf of the
37  * U.S. government, the Government shall have only "Restricted Rights"
38  * in the software and related documentation as defined in the Federal
39  * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
40  * are acquiring the software on behalf of the Department of Defense,
41  * the software shall be classified as "Commercial Computer Software"
42  * and the Government shall have only "Restricted Rights" as defined
43  * in Clause 252.227-7013 (c) (1) of DFARs.  Notwithstanding the
44  * foregoing, the authors grant the U.S. Government and others acting
45  * in its behalf permission to use and distribute the software in
46  * accordance with the terms specified in this license.
47  *
48  */
49
50
51 #include "gtktextbtree.h"
52
53 static void gtk_text_mark_init       (GtkTextMark      *mark);
54 static void gtk_text_mark_class_init (GtkTextMarkClass *klass);
55 static void gtk_text_mark_finalize   (GObject          *obj);
56
57
58 static gpointer parent_class = NULL;
59
60 GType
61 gtk_text_mark_get_type (void)
62 {
63   static GType object_type = 0;
64
65   if (!object_type)
66     {
67       static const GTypeInfo object_info =
68       {
69         sizeof (GtkTextMarkClass),
70         (GBaseInitFunc) NULL,
71         (GBaseFinalizeFunc) NULL,
72         (GClassInitFunc) gtk_text_mark_class_init,
73         NULL,           /* class_finalize */
74         NULL,           /* class_data */
75         sizeof (GtkTextMark),
76         0,              /* n_preallocs */
77         (GInstanceInitFunc) gtk_text_mark_init,
78       };
79
80       object_type = g_type_register_static (G_TYPE_OBJECT,
81                                             "GtkTextMark",
82                                             &object_info, 0);
83     }
84
85   return object_type;
86 }
87
88 static void
89 gtk_text_mark_init (GtkTextMark *mark)
90 {
91   mark->segment = NULL;
92 }
93
94 static void
95 gtk_text_mark_class_init (GtkTextMarkClass *klass)
96 {
97   GObjectClass *object_class = G_OBJECT_CLASS (klass);
98
99   parent_class = g_type_class_peek_parent (klass);
100
101   object_class->finalize = gtk_text_mark_finalize;
102 }
103
104 static void
105 gtk_text_mark_finalize (GObject *obj)
106 {
107   GtkTextMark *mark;
108   GtkTextLineSegment *seg;
109
110   mark = GTK_TEXT_MARK (obj);
111
112   seg = mark->segment;
113
114   if (seg)
115     {
116       g_return_if_fail (seg->body.mark.tree == NULL);
117
118       if (seg->body.mark.tree != NULL)
119         g_warning ("GtkTextMark being finalized while still in the buffer; "
120                    "someone removed a reference they didn't own! Crash "
121                    "impending");
122
123       g_free (seg->body.mark.name);
124       g_free (seg);
125
126       mark->segment = NULL;
127     }
128 }
129
130 /**
131  * gtk_text_mark_is_visible:
132  * @mark: a #GtkTextMark
133  * 
134  * Returns %TRUE if the mark is visible (i.e. a cursor is displayed
135  * for it)
136  * 
137  * Return value: %TRUE if visible
138  **/
139 gboolean
140 gtk_text_mark_is_visible (GtkTextMark *mark)
141 {
142   GtkTextLineSegment *seg;
143
144   seg = mark->segment;
145
146   return seg->body.mark.visible;
147 }
148
149 /**
150  * gtk_text_mark_get_name:
151  * @mark: a #GtkTextMark
152  * 
153  * Returns the mark name; returns NULL for anonymous marks.
154  * 
155  * Return value: mark name
156  **/
157 const char *
158 gtk_text_mark_get_name (GtkTextMark *mark)
159 {
160   GtkTextLineSegment *seg;
161
162   seg = mark->segment;
163
164   return seg->body.mark.name;
165 }
166
167 /**
168  * gtk_text_mark_get_deleted:
169  * @mark: a #GtkTextMark
170  * 
171  * Returns %TRUE if the mark has been removed from its buffer
172  * with gtk_text_buffer_delete_mark(). Marks can't be used
173  * once deleted.
174  * 
175  * Return value: whether the mark is deleted
176  **/
177 gboolean
178 gtk_text_mark_get_deleted (GtkTextMark *mark)
179 {
180   GtkTextLineSegment *seg;
181
182   g_return_val_if_fail (mark != NULL, FALSE);
183
184   seg = mark->segment;
185
186   if (seg == NULL)
187     return TRUE;
188
189   return seg->body.mark.tree == NULL;
190 }
191
192 /*
193  * Macro that determines the size of a mark segment:
194  */
195
196 #define MSEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
197         + sizeof (GtkTextMarkBody)))
198
199
200 GtkTextLineSegment*
201 _gtk_mark_segment_new (GtkTextBTree *tree,
202                        gboolean      left_gravity,
203                        const gchar  *name)
204 {
205   GtkTextLineSegment *mark;
206
207   mark = (GtkTextLineSegment *) g_malloc0 (MSEG_SIZE);
208   mark->body.mark.name = g_strdup (name);
209
210   if (left_gravity)
211     mark->type = &gtk_text_left_mark_type;
212   else
213     mark->type = &gtk_text_right_mark_type;
214
215   mark->byte_count = 0;
216   mark->char_count = 0;
217
218   mark->body.mark.obj = g_object_new (GTK_TYPE_TEXT_MARK, NULL);
219   mark->body.mark.obj->segment = mark;
220
221   mark->body.mark.tree = tree;
222   mark->body.mark.line = NULL;
223   mark->next = NULL;
224
225   mark->body.mark.visible = FALSE;
226   mark->body.mark.not_deleteable = FALSE;
227
228   return mark;
229 }
230
231 static int                 mark_segment_delete_func  (GtkTextLineSegment *segPtr,
232                                                       GtkTextLine        *line,
233                                                       int                 treeGone);
234 static GtkTextLineSegment *mark_segment_cleanup_func (GtkTextLineSegment *segPtr,
235                                                       GtkTextLine        *line);
236 static void                mark_segment_check_func   (GtkTextLineSegment *segPtr,
237                                                       GtkTextLine        *line);
238
239
240 /*
241  * The following structures declare the "mark" segment types.
242  * There are actually two types for marks, one with left gravity
243  * and one with right gravity.  They are identical except for
244  * their gravity property.
245  */
246
247 GtkTextLineSegmentClass gtk_text_right_mark_type = {
248   "mark",                                               /* name */
249   FALSE,                                                /* leftGravity */
250   NULL,                                         /* splitFunc */
251   mark_segment_delete_func,                             /* deleteFunc */
252   mark_segment_cleanup_func,                            /* cleanupFunc */
253   NULL,                                         /* lineChangeFunc */
254   mark_segment_check_func                               /* checkFunc */
255 };
256
257 GtkTextLineSegmentClass gtk_text_left_mark_type = {
258   "mark",                                               /* name */
259   TRUE,                                         /* leftGravity */
260   NULL,                                         /* splitFunc */
261   mark_segment_delete_func,                             /* deleteFunc */
262   mark_segment_cleanup_func,                            /* cleanupFunc */
263   NULL,                                         /* lineChangeFunc */
264   mark_segment_check_func                               /* checkFunc */
265 };
266
267 /*
268  *--------------------------------------------------------------
269  *
270  * mark_segment_delete_func --
271  *
272  *      This procedure is invoked by the text B-tree code whenever
273  *      a mark lies in a range of characters being deleted.
274  *
275  * Results:
276  *      Returns 1 to indicate that deletion has been rejected.
277  *
278  * Side effects:
279  *      None (even if the whole tree is being deleted we don't
280  *      free up the mark;  it will be done elsewhere).
281  *
282  *--------------------------------------------------------------
283  */
284
285 static gboolean
286 mark_segment_delete_func (GtkTextLineSegment *segPtr,
287                           GtkTextLine        *line,
288                           gboolean            tree_gone)
289 {
290   return TRUE;
291 }
292
293 /*
294  *--------------------------------------------------------------
295  *
296  * mark_segment_cleanup_func --
297  *
298  *      This procedure is invoked by the B-tree code whenever a
299  *      mark segment is moved from one line to another.
300  *
301  * Results:
302  *      None.
303  *
304  * Side effects:
305  *      The line field of the segment gets updated.
306  *
307  *--------------------------------------------------------------
308  */
309
310 static GtkTextLineSegment *
311 mark_segment_cleanup_func (GtkTextLineSegment *seg,
312                            GtkTextLine        *line)
313 {
314   /* not sure why Tk did this here and not in LineChangeFunc */
315   seg->body.mark.line = line;
316   return seg;
317 }
318
319 /*
320  *--------------------------------------------------------------
321  *
322  * mark_segment_check_func --
323  *
324  *      This procedure is invoked by the B-tree code to perform
325  *      consistency checks on mark segments.
326  *
327  * Results:
328  *      None.
329  *
330  * Side effects:
331  *      The procedure panics if it detects anything wrong with
332  *      the mark.
333  *
334  *--------------------------------------------------------------
335  */
336
337 static void
338 mark_segment_check_func (GtkTextLineSegment *seg,
339                          GtkTextLine        *line)
340 {
341   if (seg->body.mark.line != line)
342     g_error ("mark_segment_check_func: seg->body.mark.line bogus");
343 }