]> Pileus Git - ~andy/gtk/blob - gtk/gtktextmark.c
Deprecation cleanup
[~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 #define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
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, "GtkTextMark",
81                                             &object_info, 0);
82     }
83
84   return object_type;
85 }
86
87 static void
88 gtk_text_mark_init (GtkTextMark *mark)
89 {
90   mark->segment = NULL;
91 }
92
93 static void
94 gtk_text_mark_class_init (GtkTextMarkClass *klass)
95 {
96   GObjectClass *object_class = G_OBJECT_CLASS (klass);
97
98   parent_class = g_type_class_peek_parent (klass);
99
100   object_class->finalize = gtk_text_mark_finalize;
101 }
102
103 static void
104 gtk_text_mark_finalize (GObject *obj)
105 {
106   GtkTextMark *mark;
107   GtkTextLineSegment *seg;
108
109   mark = GTK_TEXT_MARK (obj);
110
111   seg = mark->segment;
112
113   if (seg)
114     {
115       if (seg->body.mark.tree != NULL)
116         g_warning ("GtkTextMark being finalized while still in the buffer; "
117                    "someone removed a reference they didn't own! Crash "
118                    "impending");
119
120       g_free (seg->body.mark.name);
121       g_free (seg);
122
123       mark->segment = NULL;
124     }
125
126   /* chain parent_class' handler */
127   G_OBJECT_CLASS (parent_class)->finalize (obj);
128 }
129
130 /**
131  * gtk_text_mark_get_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_get_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 (GTK_IS_TEXT_MARK (mark), 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  * gtk_text_mark_get_buffer:
194  * @mark: a #GtkTextMark
195  * 
196  * Gets the buffer this mark is located inside,
197  * or NULL if the mark is deleted.
198  * 
199  * Return value: the mark's #GtkTextBuffer
200  **/
201 GtkTextBuffer*
202 gtk_text_mark_get_buffer (GtkTextMark *mark)
203 {
204   GtkTextLineSegment *seg;
205
206   g_return_val_if_fail (GTK_IS_TEXT_MARK (mark), FALSE);
207
208   seg = mark->segment;
209
210   if (seg->body.mark.tree == NULL)
211     return NULL;
212   else
213     return _gtk_text_btree_get_buffer (seg->body.mark.tree);
214 }
215
216 /**
217  * gtk_text_mark_get_left_gravity:
218  * @mark: a #GtkTextMark
219  * 
220  * Determines whether the mark has left gravity.
221  * 
222  * Return value: %TRUE if the mark has left gravity, %FALSE otherwise
223  **/
224 gboolean
225 gtk_text_mark_get_left_gravity (GtkTextMark *mark)
226 {
227   GtkTextLineSegment *seg;
228
229   g_return_val_if_fail (GTK_IS_TEXT_MARK (mark), FALSE);
230   
231   seg = mark->segment;
232
233   return seg->type == &gtk_text_left_mark_type;
234 }
235
236 /*
237  * Macro that determines the size of a mark segment:
238  */
239
240 #define MSEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
241         + sizeof (GtkTextMarkBody)))
242
243
244 GtkTextLineSegment*
245 _gtk_mark_segment_new (GtkTextBTree *tree,
246                        gboolean      left_gravity,
247                        const gchar  *name)
248 {
249   GtkTextLineSegment *mark;
250
251   mark = (GtkTextLineSegment *) g_malloc0 (MSEG_SIZE);
252   mark->body.mark.name = g_strdup (name);
253
254   if (left_gravity)
255     mark->type = &gtk_text_left_mark_type;
256   else
257     mark->type = &gtk_text_right_mark_type;
258
259   mark->byte_count = 0;
260   mark->char_count = 0;
261
262   mark->body.mark.obj = g_object_new (GTK_TYPE_TEXT_MARK, NULL);
263   mark->body.mark.obj->segment = mark;
264
265   mark->body.mark.tree = tree;
266   mark->body.mark.line = NULL;
267   mark->next = NULL;
268
269   mark->body.mark.visible = FALSE;
270   mark->body.mark.not_deleteable = FALSE;
271
272   return mark;
273 }
274
275 static int                 mark_segment_delete_func  (GtkTextLineSegment *segPtr,
276                                                       GtkTextLine        *line,
277                                                       int                 treeGone);
278 static GtkTextLineSegment *mark_segment_cleanup_func (GtkTextLineSegment *segPtr,
279                                                       GtkTextLine        *line);
280 static void                mark_segment_check_func   (GtkTextLineSegment *segPtr,
281                                                       GtkTextLine        *line);
282
283
284 /*
285  * The following structures declare the "mark" segment types.
286  * There are actually two types for marks, one with left gravity
287  * and one with right gravity.  They are identical except for
288  * their gravity property.
289  */
290
291 GtkTextLineSegmentClass gtk_text_right_mark_type = {
292   "mark",                                               /* name */
293   FALSE,                                                /* leftGravity */
294   NULL,                                         /* splitFunc */
295   mark_segment_delete_func,                             /* deleteFunc */
296   mark_segment_cleanup_func,                            /* cleanupFunc */
297   NULL,                                         /* lineChangeFunc */
298   mark_segment_check_func                               /* checkFunc */
299 };
300
301 GtkTextLineSegmentClass gtk_text_left_mark_type = {
302   "mark",                                               /* name */
303   TRUE,                                         /* leftGravity */
304   NULL,                                         /* splitFunc */
305   mark_segment_delete_func,                             /* deleteFunc */
306   mark_segment_cleanup_func,                            /* cleanupFunc */
307   NULL,                                         /* lineChangeFunc */
308   mark_segment_check_func                               /* checkFunc */
309 };
310
311 /*
312  *--------------------------------------------------------------
313  *
314  * mark_segment_delete_func --
315  *
316  *      This procedure is invoked by the text B-tree code whenever
317  *      a mark lies in a range of characters being deleted.
318  *
319  * Results:
320  *      Returns 1 to indicate that deletion has been rejected,
321  *      or 0 otherwise
322  *
323  * Side effects:
324  *      Frees mark if tree is going away
325  *
326  *--------------------------------------------------------------
327  */
328
329 static gboolean
330 mark_segment_delete_func (GtkTextLineSegment *seg,
331                           GtkTextLine        *line,
332                           gboolean            tree_gone)
333 {
334   if (tree_gone)
335     {
336       _gtk_text_btree_release_mark_segment (seg->body.mark.tree, seg);
337       return FALSE;
338     }
339   else
340     return TRUE;
341 }
342
343 /*
344  *--------------------------------------------------------------
345  *
346  * mark_segment_cleanup_func --
347  *
348  *      This procedure is invoked by the B-tree code whenever a
349  *      mark segment is moved from one line to another.
350  *
351  * Results:
352  *      None.
353  *
354  * Side effects:
355  *      The line field of the segment gets updated.
356  *
357  *--------------------------------------------------------------
358  */
359
360 static GtkTextLineSegment *
361 mark_segment_cleanup_func (GtkTextLineSegment *seg,
362                            GtkTextLine        *line)
363 {
364   /* not sure why Tk did this here and not in LineChangeFunc */
365   seg->body.mark.line = line;
366   return seg;
367 }
368
369 /*
370  *--------------------------------------------------------------
371  *
372  * mark_segment_check_func --
373  *
374  *      This procedure is invoked by the B-tree code to perform
375  *      consistency checks on mark segments.
376  *
377  * Results:
378  *      None.
379  *
380  * Side effects:
381  *      The procedure panics if it detects anything wrong with
382  *      the mark.
383  *
384  *--------------------------------------------------------------
385  */
386
387 static void
388 mark_segment_check_func (GtkTextLineSegment *seg,
389                          GtkTextLine        *line)
390 {
391   if (seg->body.mark.line != line)
392     g_error ("mark_segment_check_func: seg->body.mark.line bogus");
393 }