]> Pileus Git - ~andy/gtk/blob - gtk/gtktextmark.c
Add hidden aliases for exported symbols which are used internally in order
[~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 <config.h>
52 #include "gtkalias.h"
53 #include "gtktextbtree.h"
54
55 static void gtk_text_mark_init       (GtkTextMark      *mark);
56 static void gtk_text_mark_class_init (GtkTextMarkClass *klass);
57 static void gtk_text_mark_finalize   (GObject          *obj);
58
59
60 static gpointer parent_class = NULL;
61
62 GType
63 gtk_text_mark_get_type (void)
64 {
65   static GType object_type = 0;
66
67   if (!object_type)
68     {
69       static const GTypeInfo object_info =
70       {
71         sizeof (GtkTextMarkClass),
72         (GBaseInitFunc) NULL,
73         (GBaseFinalizeFunc) NULL,
74         (GClassInitFunc) gtk_text_mark_class_init,
75         NULL,           /* class_finalize */
76         NULL,           /* class_data */
77         sizeof (GtkTextMark),
78         0,              /* n_preallocs */
79         (GInstanceInitFunc) gtk_text_mark_init,
80       };
81
82       object_type = g_type_register_static (G_TYPE_OBJECT, "GtkTextMark",
83                                             &object_info, 0);
84     }
85
86   return object_type;
87 }
88
89 static void
90 gtk_text_mark_init (GtkTextMark *mark)
91 {
92   mark->segment = NULL;
93 }
94
95 static void
96 gtk_text_mark_class_init (GtkTextMarkClass *klass)
97 {
98   GObjectClass *object_class = G_OBJECT_CLASS (klass);
99
100   parent_class = g_type_class_peek_parent (klass);
101
102   object_class->finalize = gtk_text_mark_finalize;
103 }
104
105 static void
106 gtk_text_mark_finalize (GObject *obj)
107 {
108   GtkTextMark *mark;
109   GtkTextLineSegment *seg;
110
111   mark = GTK_TEXT_MARK (obj);
112
113   seg = mark->segment;
114
115   if (seg)
116     {
117       if (seg->body.mark.tree != NULL)
118         g_warning ("GtkTextMark being finalized while still in the buffer; "
119                    "someone removed a reference they didn't own! Crash "
120                    "impending");
121
122       g_free (seg->body.mark.name);
123       g_free (seg);
124
125       mark->segment = NULL;
126     }
127
128   /* chain parent_class' handler */
129   G_OBJECT_CLASS (parent_class)->finalize (obj);
130 }
131
132 /**
133  * gtk_text_mark_get_visible:
134  * @mark: a #GtkTextMark
135  * 
136  * Returns %TRUE if the mark is visible (i.e. a cursor is displayed
137  * for it)
138  * 
139  * Return value: %TRUE if visible
140  **/
141 gboolean
142 gtk_text_mark_get_visible (GtkTextMark *mark)
143 {
144   GtkTextLineSegment *seg;
145
146   seg = mark->segment;
147
148   return seg->body.mark.visible;
149 }
150
151 /**
152  * gtk_text_mark_get_name:
153  * @mark: a #GtkTextMark
154  * 
155  * Returns the mark name; returns NULL for anonymous marks.
156  * 
157  * Return value: mark name
158  **/
159 const char *
160 gtk_text_mark_get_name (GtkTextMark *mark)
161 {
162   GtkTextLineSegment *seg;
163
164   seg = mark->segment;
165
166   return seg->body.mark.name;
167 }
168
169 /**
170  * gtk_text_mark_get_deleted:
171  * @mark: a #GtkTextMark
172  * 
173  * Returns %TRUE if the mark has been removed from its buffer
174  * with gtk_text_buffer_delete_mark(). Marks can't be used
175  * once deleted.
176  * 
177  * Return value: whether the mark is deleted
178  **/
179 gboolean
180 gtk_text_mark_get_deleted (GtkTextMark *mark)
181 {
182   GtkTextLineSegment *seg;
183
184   g_return_val_if_fail (GTK_IS_TEXT_MARK (mark), FALSE);
185
186   seg = mark->segment;
187
188   if (seg == NULL)
189     return TRUE;
190
191   return seg->body.mark.tree == NULL;
192 }
193
194 /**
195  * gtk_text_mark_get_buffer:
196  * @mark: a #GtkTextMark
197  * 
198  * Gets the buffer this mark is located inside,
199  * or NULL if the mark is deleted.
200  * 
201  * Return value: the mark's #GtkTextBuffer
202  **/
203 GtkTextBuffer*
204 gtk_text_mark_get_buffer (GtkTextMark *mark)
205 {
206   GtkTextLineSegment *seg;
207
208   g_return_val_if_fail (GTK_IS_TEXT_MARK (mark), NULL);
209
210   seg = mark->segment;
211
212   if (seg->body.mark.tree == NULL)
213     return NULL;
214   else
215     return _gtk_text_btree_get_buffer (seg->body.mark.tree);
216 }
217
218 /**
219  * gtk_text_mark_get_left_gravity:
220  * @mark: a #GtkTextMark
221  * 
222  * Determines whether the mark has left gravity.
223  * 
224  * Return value: %TRUE if the mark has left gravity, %FALSE otherwise
225  **/
226 gboolean
227 gtk_text_mark_get_left_gravity (GtkTextMark *mark)
228 {
229   GtkTextLineSegment *seg;
230
231   g_return_val_if_fail (GTK_IS_TEXT_MARK (mark), FALSE);
232   
233   seg = mark->segment;
234
235   return seg->type == &gtk_text_left_mark_type;
236 }
237
238 /*
239  * Macro that determines the size of a mark segment:
240  */
241
242 #define MSEG_SIZE ((unsigned) (G_STRUCT_OFFSET (GtkTextLineSegment, body) \
243         + sizeof (GtkTextMarkBody)))
244
245
246 GtkTextLineSegment*
247 _gtk_mark_segment_new (GtkTextBTree *tree,
248                        gboolean      left_gravity,
249                        const gchar  *name)
250 {
251   GtkTextLineSegment *mark;
252
253   mark = (GtkTextLineSegment *) g_malloc0 (MSEG_SIZE);
254   mark->body.mark.name = g_strdup (name);
255
256   if (left_gravity)
257     mark->type = &gtk_text_left_mark_type;
258   else
259     mark->type = &gtk_text_right_mark_type;
260
261   mark->byte_count = 0;
262   mark->char_count = 0;
263
264   mark->body.mark.obj = g_object_new (GTK_TYPE_TEXT_MARK, NULL);
265   mark->body.mark.obj->segment = mark;
266
267   mark->body.mark.tree = tree;
268   mark->body.mark.line = NULL;
269   mark->next = NULL;
270
271   mark->body.mark.visible = FALSE;
272   mark->body.mark.not_deleteable = FALSE;
273
274   return mark;
275 }
276
277 static int                 mark_segment_delete_func  (GtkTextLineSegment *segPtr,
278                                                       GtkTextLine        *line,
279                                                       int                 treeGone);
280 static GtkTextLineSegment *mark_segment_cleanup_func (GtkTextLineSegment *segPtr,
281                                                       GtkTextLine        *line);
282 static void                mark_segment_check_func   (GtkTextLineSegment *segPtr,
283                                                       GtkTextLine        *line);
284
285
286 /*
287  * The following structures declare the "mark" segment types.
288  * There are actually two types for marks, one with left gravity
289  * and one with right gravity.  They are identical except for
290  * their gravity property.
291  */
292
293 GtkTextLineSegmentClass gtk_text_right_mark_type = {
294   "mark",                                               /* name */
295   FALSE,                                                /* leftGravity */
296   NULL,                                         /* splitFunc */
297   mark_segment_delete_func,                             /* deleteFunc */
298   mark_segment_cleanup_func,                            /* cleanupFunc */
299   NULL,                                         /* lineChangeFunc */
300   mark_segment_check_func                               /* checkFunc */
301 };
302
303 GtkTextLineSegmentClass gtk_text_left_mark_type = {
304   "mark",                                               /* name */
305   TRUE,                                         /* leftGravity */
306   NULL,                                         /* splitFunc */
307   mark_segment_delete_func,                             /* deleteFunc */
308   mark_segment_cleanup_func,                            /* cleanupFunc */
309   NULL,                                         /* lineChangeFunc */
310   mark_segment_check_func                               /* checkFunc */
311 };
312
313 /*
314  *--------------------------------------------------------------
315  *
316  * mark_segment_delete_func --
317  *
318  *      This procedure is invoked by the text B-tree code whenever
319  *      a mark lies in a range of characters being deleted.
320  *
321  * Results:
322  *      Returns 1 to indicate that deletion has been rejected,
323  *      or 0 otherwise
324  *
325  * Side effects:
326  *      Frees mark if tree is going away
327  *
328  *--------------------------------------------------------------
329  */
330
331 static gboolean
332 mark_segment_delete_func (GtkTextLineSegment *seg,
333                           GtkTextLine        *line,
334                           gboolean            tree_gone)
335 {
336   if (tree_gone)
337     {
338       _gtk_text_btree_release_mark_segment (seg->body.mark.tree, seg);
339       return FALSE;
340     }
341   else
342     return TRUE;
343 }
344
345 /*
346  *--------------------------------------------------------------
347  *
348  * mark_segment_cleanup_func --
349  *
350  *      This procedure is invoked by the B-tree code whenever a
351  *      mark segment is moved from one line to another.
352  *
353  * Results:
354  *      None.
355  *
356  * Side effects:
357  *      The line field of the segment gets updated.
358  *
359  *--------------------------------------------------------------
360  */
361
362 static GtkTextLineSegment *
363 mark_segment_cleanup_func (GtkTextLineSegment *seg,
364                            GtkTextLine        *line)
365 {
366   /* not sure why Tk did this here and not in LineChangeFunc */
367   seg->body.mark.line = line;
368   return seg;
369 }
370
371 /*
372  *--------------------------------------------------------------
373  *
374  * mark_segment_check_func --
375  *
376  *      This procedure is invoked by the B-tree code to perform
377  *      consistency checks on mark segments.
378  *
379  * Results:
380  *      None.
381  *
382  * Side effects:
383  *      The procedure panics if it detects anything wrong with
384  *      the mark.
385  *
386  *--------------------------------------------------------------
387  */
388
389 static void
390 mark_segment_check_func (GtkTextLineSegment *seg,
391                          GtkTextLine        *line)
392 {
393   if (seg->body.mark.line != line)
394     g_error ("mark_segment_check_func: seg->body.mark.line bogus");
395 }