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