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