]> Pileus Git - ~andy/gtk/blob - gtk/gtktexttag.c
Language improvements
[~andy/gtk] / gtk / gtktexttag.c
1 /* gtktexttag.c - text tag object
2  *
3  * Copyright (c) 1992-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  * SECTION:gtktexttag
52  * @Title: GtkTextTag
53  * @Short_description: A tag that can be applied to text in a GtkTextBuffer
54  *
55  * You may wish to begin by reading the <link linkend="TextWidget">text widget
56  * conceptual overview</link> which gives an overview of all the objects and
57  * data types related to the text widget and how they work together.
58  *
59  * Tags should be in the #GtkTextTagTable for a given #GtkTextBuffer
60  * before using them with that buffer.
61  *
62  * gtk_text_buffer_create_tag() is the best way to create tags.
63  * See <application>gtk3-demo</application> for numerous examples.
64  */
65
66 #include "config.h"
67
68 #include <stdlib.h>
69 #include <string.h>
70
71 #include "gtkmainprivate.h"
72 #include "gtktexttag.h"
73 #include "gtktexttypes.h"
74 #include "gtktexttagtable.h"
75 #include "gtkintl.h"
76 #include "gtkmarshalers.h"
77 #include "gtkprivate.h"
78 #include "gtktypebuiltins.h"
79
80 enum {
81   EVENT,
82   LAST_SIGNAL
83 };
84
85 enum {
86   PROP_0,
87   /* Construct args */
88   PROP_NAME,
89
90   /* Style args */
91   PROP_BACKGROUND,
92   PROP_FOREGROUND,
93   PROP_BACKGROUND_GDK,
94   PROP_FOREGROUND_GDK,
95   PROP_BACKGROUND_RGBA,
96   PROP_FOREGROUND_RGBA,
97   PROP_FONT,
98   PROP_FONT_DESC,
99   PROP_FAMILY,
100   PROP_STYLE,
101   PROP_VARIANT,
102   PROP_WEIGHT,
103   PROP_STRETCH,
104   PROP_SIZE,
105   PROP_SIZE_POINTS,
106   PROP_SCALE,
107   PROP_PIXELS_ABOVE_LINES,
108   PROP_PIXELS_BELOW_LINES,
109   PROP_PIXELS_INSIDE_WRAP,
110   PROP_EDITABLE,
111   PROP_WRAP_MODE,
112   PROP_JUSTIFICATION,
113   PROP_DIRECTION,
114   PROP_LEFT_MARGIN,
115   PROP_INDENT,
116   PROP_STRIKETHROUGH,
117   PROP_RIGHT_MARGIN,
118   PROP_UNDERLINE,
119   PROP_RISE,
120   PROP_BACKGROUND_FULL_HEIGHT,
121   PROP_LANGUAGE,
122   PROP_TABS,
123   PROP_INVISIBLE,
124   PROP_PARAGRAPH_BACKGROUND,
125   PROP_PARAGRAPH_BACKGROUND_GDK,
126   PROP_PARAGRAPH_BACKGROUND_RGBA,
127
128   /* Behavior args */
129   PROP_ACCUMULATIVE_MARGIN,
130   
131   /* Whether-a-style-arg-is-set args */
132   PROP_BACKGROUND_SET,
133   PROP_FOREGROUND_SET,
134   PROP_FAMILY_SET,
135   PROP_STYLE_SET,
136   PROP_VARIANT_SET,
137   PROP_WEIGHT_SET,
138   PROP_STRETCH_SET,
139   PROP_SIZE_SET,
140   PROP_SCALE_SET,
141   PROP_PIXELS_ABOVE_LINES_SET,
142   PROP_PIXELS_BELOW_LINES_SET,
143   PROP_PIXELS_INSIDE_WRAP_SET,
144   PROP_EDITABLE_SET,
145   PROP_WRAP_MODE_SET,
146   PROP_JUSTIFICATION_SET,
147   PROP_LEFT_MARGIN_SET,
148   PROP_INDENT_SET,
149   PROP_STRIKETHROUGH_SET,
150   PROP_RIGHT_MARGIN_SET,
151   PROP_UNDERLINE_SET,
152   PROP_RISE_SET,
153   PROP_BACKGROUND_FULL_HEIGHT_SET,
154   PROP_LANGUAGE_SET,
155   PROP_TABS_SET,
156   PROP_INVISIBLE_SET,
157   PROP_PARAGRAPH_BACKGROUND_SET,
158
159   LAST_ARG
160 };
161 static void gtk_text_tag_finalize     (GObject         *object);
162 static void gtk_text_tag_set_property (GObject         *object,
163                                        guint            prop_id,
164                                        const GValue    *value,
165                                        GParamSpec      *pspec);
166 static void gtk_text_tag_get_property (GObject         *object,
167                                        guint            prop_id,
168                                        GValue          *value,
169                                        GParamSpec      *pspec);
170
171 static guint signals[LAST_SIGNAL] = { 0 };
172
173 G_DEFINE_TYPE (GtkTextTag, gtk_text_tag, G_TYPE_OBJECT)
174
175 static void
176 gtk_text_tag_class_init (GtkTextTagClass *klass)
177 {
178   GObjectClass *object_class = G_OBJECT_CLASS (klass);
179
180   object_class->set_property = gtk_text_tag_set_property;
181   object_class->get_property = gtk_text_tag_get_property;
182   
183   object_class->finalize = gtk_text_tag_finalize;
184
185   /* Construct */
186   g_object_class_install_property (object_class,
187                                    PROP_NAME,
188                                    g_param_spec_string ("name",
189                                                         P_("Tag name"),
190                                                         P_("Name used to refer to the text tag. NULL for anonymous tags"),
191                                                         NULL,
192                                                         GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
193
194   /* Style args */
195
196   g_object_class_install_property (object_class,
197                                    PROP_BACKGROUND,
198                                    g_param_spec_string ("background",
199                                                         P_("Background color name"),
200                                                         P_("Background color as a string"),
201                                                         NULL,
202                                                         GTK_PARAM_WRITABLE));
203
204   g_object_class_install_property (object_class,
205                                    PROP_BACKGROUND_GDK,
206                                    g_param_spec_boxed ("background-gdk",
207                                                        P_("Background color"),
208                                                        P_("Background color as a GdkColor"),
209                                                        GDK_TYPE_COLOR,
210                                                        GTK_PARAM_READWRITE));
211
212   /**
213    * GtkTextTag:background-rgba:
214    *
215    * Background color as a #GdkRGBA.
216    *
217    * Since: 3.2
218    */
219   g_object_class_install_property (object_class,
220                                    PROP_BACKGROUND_RGBA,
221                                    g_param_spec_boxed ("background-rgba",
222                                                        P_("Background RGBA"),
223                                                        P_("Background color as a GdkRGBA"),
224                                                        GDK_TYPE_RGBA,
225                                                        GTK_PARAM_READWRITE));
226
227   g_object_class_install_property (object_class,
228                                    PROP_BACKGROUND_FULL_HEIGHT,
229                                    g_param_spec_boolean ("background-full-height",
230                                                          P_("Background full height"),
231                                                          P_("Whether the background color fills the entire line height or only the height of the tagged characters"),
232                                                          FALSE,
233                                                          GTK_PARAM_READWRITE));
234   
235   g_object_class_install_property (object_class,
236                                    PROP_FOREGROUND,
237                                    g_param_spec_string ("foreground",
238                                                         P_("Foreground color name"),
239                                                         P_("Foreground color as a string"),
240                                                         NULL,
241                                                         GTK_PARAM_WRITABLE));
242
243   g_object_class_install_property (object_class,
244                                    PROP_FOREGROUND_GDK,
245                                    g_param_spec_boxed ("foreground-gdk",
246                                                        P_("Foreground color"),
247                                                        P_("Foreground color as a GdkColor"),
248                                                        GDK_TYPE_COLOR,
249                                                        GTK_PARAM_READWRITE));
250
251   /**
252    * GtkTextTag:foreground-rgba:
253    *
254    * Foreground color as a #GdkRGBA.
255    *
256    * Since: 3.2
257    */
258   g_object_class_install_property (object_class,
259                                    PROP_FOREGROUND_RGBA,
260                                    g_param_spec_boxed ("foreground-rgba",
261                                                        P_("Foreground RGBA"),
262                                                        P_("Foreground color as a GdkRGBA"),
263                                                        GDK_TYPE_RGBA,
264                                                        GTK_PARAM_READWRITE));
265
266   g_object_class_install_property (object_class,
267                                    PROP_DIRECTION,
268                                    g_param_spec_enum ("direction",
269                                                       P_("Text direction"),
270                                                       P_("Text direction, e.g. right-to-left or left-to-right"),
271                                                       GTK_TYPE_TEXT_DIRECTION,
272                                                       GTK_TEXT_DIR_NONE,
273                                                       GTK_PARAM_READWRITE));
274
275   g_object_class_install_property (object_class,
276                                    PROP_EDITABLE,
277                                    g_param_spec_boolean ("editable",
278                                                          P_("Editable"),
279                                                          P_("Whether the text can be modified by the user"),
280                                                          TRUE,
281                                                          GTK_PARAM_READWRITE));
282
283   /**
284    * GtkTextTag:font:
285    *
286    * Font description as string, e.g. \"Sans Italic 12\". 
287    *
288    * Note that the initial value of this property depends on
289    * the internals of #PangoFontDescription.
290    */
291   g_object_class_install_property (object_class,
292                                    PROP_FONT,
293                                    g_param_spec_string ("font",
294                                                         P_("Font"),
295                                                         P_("Font description as a string, e.g. \"Sans Italic 12\""),
296                                                         NULL,
297                                                         GTK_PARAM_READWRITE));
298
299   g_object_class_install_property (object_class,
300                                    PROP_FONT_DESC,
301                                    g_param_spec_boxed ("font-desc",
302                                                        P_("Font"),
303                                                        P_("Font description as a PangoFontDescription struct"),
304                                                        PANGO_TYPE_FONT_DESCRIPTION,
305                                                        GTK_PARAM_READWRITE));
306   
307   g_object_class_install_property (object_class,
308                                    PROP_FAMILY,
309                                    g_param_spec_string ("family",
310                                                         P_("Font family"),
311                                                         P_("Name of the font family, e.g. Sans, Helvetica, Times, Monospace"),
312                                                         NULL,
313                                                         GTK_PARAM_READWRITE));
314
315   g_object_class_install_property (object_class,
316                                    PROP_STYLE,
317                                    g_param_spec_enum ("style",
318                                                       P_("Font style"),
319                                                       P_("Font style as a PangoStyle, e.g. PANGO_STYLE_ITALIC"),
320                                                       PANGO_TYPE_STYLE,
321                                                       PANGO_STYLE_NORMAL,
322                                                       GTK_PARAM_READWRITE));
323
324   g_object_class_install_property (object_class,
325                                    PROP_VARIANT,
326                                    g_param_spec_enum ("variant",
327                                                      P_("Font variant"),
328                                                      P_("Font variant as a PangoVariant, e.g. PANGO_VARIANT_SMALL_CAPS"),
329                                                       PANGO_TYPE_VARIANT,
330                                                       PANGO_VARIANT_NORMAL,
331                                                       GTK_PARAM_READWRITE));
332   
333   g_object_class_install_property (object_class,
334                                    PROP_WEIGHT,
335                                    g_param_spec_int ("weight",
336                                                      P_("Font weight"),
337                                                      P_("Font weight as an integer, see predefined values in PangoWeight; for example, PANGO_WEIGHT_BOLD"),
338                                                      0,
339                                                      G_MAXINT,
340                                                      PANGO_WEIGHT_NORMAL,
341                                                      GTK_PARAM_READWRITE));
342   
343
344   g_object_class_install_property (object_class,
345                                    PROP_STRETCH,
346                                    g_param_spec_enum ("stretch",
347                                                       P_("Font stretch"),
348                                                       P_("Font stretch as a PangoStretch, e.g. PANGO_STRETCH_CONDENSED"),
349                                                       PANGO_TYPE_STRETCH,
350                                                       PANGO_STRETCH_NORMAL,
351                                                       GTK_PARAM_READWRITE));
352   
353   g_object_class_install_property (object_class,
354                                    PROP_SIZE,
355                                    g_param_spec_int ("size",
356                                                      P_("Font size"),
357                                                      P_("Font size in Pango units"),
358                                                      0,
359                                                      G_MAXINT,
360                                                      0,
361                                                      GTK_PARAM_READWRITE));
362
363   g_object_class_install_property (object_class,
364                                    PROP_SCALE,
365                                    g_param_spec_double ("scale",
366                                                         P_("Font scale"),
367                                                         P_("Font size as a scale factor relative to the default font size. This properly adapts to theme changes etc. so is recommended. Pango predefines some scales such as PANGO_SCALE_X_LARGE"),
368                                                         0.0,
369                                                         G_MAXDOUBLE,
370                                                         1.0,
371                                                         GTK_PARAM_READWRITE));
372   
373   g_object_class_install_property (object_class,
374                                    PROP_SIZE_POINTS,
375                                    g_param_spec_double ("size-points",
376                                                         P_("Font points"),
377                                                         P_("Font size in points"),
378                                                         0.0,
379                                                         G_MAXDOUBLE,
380                                                         0.0,
381                                                         GTK_PARAM_READWRITE));  
382
383   g_object_class_install_property (object_class,
384                                    PROP_JUSTIFICATION,
385                                    g_param_spec_enum ("justification",
386                                                       P_("Justification"),
387                                                       P_("Left, right, or center justification"),
388                                                       GTK_TYPE_JUSTIFICATION,
389                                                       GTK_JUSTIFY_LEFT,
390                                                       GTK_PARAM_READWRITE));
391
392   /**
393    * GtkTextTag:language:
394    *
395    * The language this text is in, as an ISO code. Pango can use this as a 
396    * hint when rendering the text. If not set, an appropriate default will be 
397    * used.
398    *
399    * Note that the initial value of this property depends on the current
400    * locale, see also gtk_get_default_language().
401    */
402   g_object_class_install_property (object_class,
403                                    PROP_LANGUAGE,
404                                    g_param_spec_string ("language",
405                                                         P_("Language"),
406                                                         P_("The language this text is in, as an ISO code. Pango can use this as a hint when rendering the text. If not set, an appropriate default will be used."),
407                                                         NULL,
408                                                         GTK_PARAM_READWRITE));  
409
410   g_object_class_install_property (object_class,
411                                    PROP_LEFT_MARGIN,
412                                    g_param_spec_int ("left-margin",
413                                                      P_("Left margin"),
414                                                      P_("Width of the left margin in pixels"),
415                                                      0,
416                                                      G_MAXINT,
417                                                      0,
418                                                      GTK_PARAM_READWRITE));
419
420   g_object_class_install_property (object_class,
421                                    PROP_RIGHT_MARGIN,
422                                    g_param_spec_int ("right-margin",
423                                                      P_("Right margin"),
424                                                      P_("Width of the right margin in pixels"),
425                                                      0,
426                                                      G_MAXINT,
427                                                      0,
428                                                      GTK_PARAM_READWRITE));
429
430   
431   g_object_class_install_property (object_class,
432                                    PROP_INDENT,
433                                    g_param_spec_int ("indent",
434                                                      P_("Indent"),
435                                                      P_("Amount to indent the paragraph, in pixels"),
436                                                      G_MININT,
437                                                      G_MAXINT,
438                                                      0,
439                                                      GTK_PARAM_READWRITE));
440
441   
442   g_object_class_install_property (object_class,
443                                    PROP_RISE,
444                                    g_param_spec_int ("rise",
445                                                      P_("Rise"),
446                                                      P_("Offset of text above the baseline (below the baseline if rise is negative) in Pango units"),
447                                                      G_MININT,
448                                                      G_MAXINT,
449                                                      0,
450                                                      GTK_PARAM_READWRITE));
451
452   g_object_class_install_property (object_class,
453                                    PROP_PIXELS_ABOVE_LINES,
454                                    g_param_spec_int ("pixels-above-lines",
455                                                      P_("Pixels above lines"),
456                                                      P_("Pixels of blank space above paragraphs"),
457                                                      0,
458                                                      G_MAXINT,
459                                                      0,
460                                                      GTK_PARAM_READWRITE));
461   
462   g_object_class_install_property (object_class,
463                                    PROP_PIXELS_BELOW_LINES,
464                                    g_param_spec_int ("pixels-below-lines",
465                                                      P_("Pixels below lines"),
466                                                      P_("Pixels of blank space below paragraphs"),
467                                                      0,
468                                                      G_MAXINT,
469                                                      0,
470                                                      GTK_PARAM_READWRITE));
471
472   g_object_class_install_property (object_class,
473                                    PROP_PIXELS_INSIDE_WRAP,
474                                    g_param_spec_int ("pixels-inside-wrap",
475                                                      P_("Pixels inside wrap"),
476                                                      P_("Pixels of blank space between wrapped lines in a paragraph"),
477                                                      0,
478                                                      G_MAXINT,
479                                                      0,
480                                                      GTK_PARAM_READWRITE));
481
482   g_object_class_install_property (object_class,
483                                    PROP_STRIKETHROUGH,
484                                    g_param_spec_boolean ("strikethrough",
485                                                          P_("Strikethrough"),
486                                                          P_("Whether to strike through the text"),
487                                                          FALSE,
488                                                          GTK_PARAM_READWRITE));
489   
490   g_object_class_install_property (object_class,
491                                    PROP_UNDERLINE,
492                                    g_param_spec_enum ("underline",
493                                                       P_("Underline"),
494                                                       P_("Style of underline for this text"),
495                                                       PANGO_TYPE_UNDERLINE,
496                                                       PANGO_UNDERLINE_NONE,
497                                                       GTK_PARAM_READWRITE));
498   
499   g_object_class_install_property (object_class,
500                                    PROP_WRAP_MODE,
501                                    g_param_spec_enum ("wrap-mode",
502                                                      P_("Wrap mode"),
503                                                      P_("Whether to wrap lines never, at word boundaries, or at character boundaries"),
504                                                       GTK_TYPE_WRAP_MODE,
505                                                       GTK_WRAP_NONE,
506                                                       GTK_PARAM_READWRITE));
507   
508
509   g_object_class_install_property (object_class,
510                                    PROP_TABS,
511                                    g_param_spec_boxed ("tabs",
512                                                        P_("Tabs"),
513                                                        P_("Custom tabs for this text"),
514                                                        PANGO_TYPE_TAB_ARRAY,
515                                                        GTK_PARAM_READWRITE));
516   
517   /**
518    * GtkTextTag:invisible:
519    *
520    * Whether this text is hidden.
521    *
522    * Note that there may still be problems with the support for invisible 
523    * text, in particular when navigating programmatically inside a buffer
524    * containing invisible segments. 
525    *
526    * Since: 2.8
527    */
528   g_object_class_install_property (object_class,
529                                    PROP_INVISIBLE,
530                                    g_param_spec_boolean ("invisible",
531                                                          P_("Invisible"),
532                                                          P_("Whether this text is hidden."),
533                                                          FALSE,
534                                                          GTK_PARAM_READWRITE));
535
536   /**
537    * GtkTextTag:paragraph-background:
538    *
539    * The paragraph background color as a string.
540    *
541    * Since: 2.8
542    */
543   g_object_class_install_property (object_class,
544                                    PROP_PARAGRAPH_BACKGROUND,
545                                    g_param_spec_string ("paragraph-background",
546                                                         P_("Paragraph background color name"),
547                                                         P_("Paragraph background color as a string"),
548                                                         NULL,
549                                                         GTK_PARAM_WRITABLE));
550
551   /**
552    * GtkTextTag:paragraph-background-gdk:
553    *
554    * The paragraph background color as a as a #GdkColor.
555    *
556    * Since: 2.8
557    */
558   g_object_class_install_property (object_class,
559                                    PROP_PARAGRAPH_BACKGROUND_GDK,
560                                    g_param_spec_boxed ("paragraph-background-gdk",
561                                                        P_("Paragraph background color"),
562                                                        P_("Paragraph background color as a GdkColor"),
563                                                        GDK_TYPE_COLOR,
564                                                        GTK_PARAM_READWRITE));
565
566   /**
567    * GtkTextTag:paragraph-background-rgba:
568    *
569    * The paragraph background color as a as a #GdkRGBA.
570    *
571    * Since: 3.2
572    */
573   g_object_class_install_property (object_class,
574                                    PROP_PARAGRAPH_BACKGROUND_RGBA,
575                                    g_param_spec_boxed ("paragraph-background-rgba",
576                                                        P_("Paragraph background RGBA"),
577                                                        P_("Paragraph background RGBA as a GdkRGBA"),
578                                                        GDK_TYPE_RGBA,
579                                                        GTK_PARAM_READWRITE));
580
581   /**
582    * GtkTextTag:accumulative-margin:
583    *
584    * Whether the margins accumulate or override each other.
585    *
586    * When set to %TRUE the margins of this tag are added to the margins 
587    * of any other non-accumulative margins present. When set to %FALSE 
588    * the margins override one another (the default).
589    *
590    * Since: 2.12
591    */
592   g_object_class_install_property (object_class,
593                                    PROP_ACCUMULATIVE_MARGIN,
594                                    g_param_spec_boolean ("accumulative-margin",
595                                                          P_("Margin Accumulates"),
596                                                          P_("Whether left and right margins accumulate."),
597                                                          FALSE,
598                                                          GTK_PARAM_READWRITE));
599
600   /* Style props are set or not */
601
602 #define ADD_SET_PROP(propname, propval, nick, blurb) g_object_class_install_property (object_class, propval, g_param_spec_boolean (propname, nick, blurb, FALSE, GTK_PARAM_READWRITE))
603
604   ADD_SET_PROP ("background-set", PROP_BACKGROUND_SET,
605                 P_("Background set"),
606                 P_("Whether this tag affects the background color"));
607   
608   ADD_SET_PROP ("background-full-height-set", PROP_BACKGROUND_FULL_HEIGHT_SET,
609                 P_("Background full height set"),
610                 P_("Whether this tag affects background height"));
611
612   ADD_SET_PROP ("foreground-set", PROP_FOREGROUND_SET,
613                 P_("Foreground set"),
614                 P_("Whether this tag affects the foreground color"));
615
616   ADD_SET_PROP ("editable-set", PROP_EDITABLE_SET,
617                 P_("Editability set"),
618                 P_("Whether this tag affects text editability"));
619
620   ADD_SET_PROP ("family-set", PROP_FAMILY_SET,
621                 P_("Font family set"),
622                 P_("Whether this tag affects the font family"));  
623
624   ADD_SET_PROP ("style-set", PROP_STYLE_SET,
625                 P_("Font style set"),
626                 P_("Whether this tag affects the font style"));
627
628   ADD_SET_PROP ("variant-set", PROP_VARIANT_SET,
629                 P_("Font variant set"),
630                 P_("Whether this tag affects the font variant"));
631
632   ADD_SET_PROP ("weight-set", PROP_WEIGHT_SET,
633                 P_("Font weight set"),
634                 P_("Whether this tag affects the font weight"));
635
636   ADD_SET_PROP ("stretch-set", PROP_STRETCH_SET,
637                 P_("Font stretch set"),
638                 P_("Whether this tag affects the font stretch"));
639
640   ADD_SET_PROP ("size-set", PROP_SIZE_SET,
641                 P_("Font size set"),
642                 P_("Whether this tag affects the font size"));
643
644   ADD_SET_PROP ("scale-set", PROP_SCALE_SET,
645                 P_("Font scale set"),
646                 P_("Whether this tag scales the font size by a factor"));
647   
648   ADD_SET_PROP ("justification-set", PROP_JUSTIFICATION_SET,
649                 P_("Justification set"),
650                 P_("Whether this tag affects paragraph justification"));
651   
652   ADD_SET_PROP ("language-set", PROP_LANGUAGE_SET,
653                 P_("Language set"),
654                 P_("Whether this tag affects the language the text is rendered as"));
655
656   ADD_SET_PROP ("left-margin-set", PROP_LEFT_MARGIN_SET,
657                 P_("Left margin set"),
658                 P_("Whether this tag affects the left margin"));
659
660   ADD_SET_PROP ("indent-set", PROP_INDENT_SET,
661                 P_("Indent set"),
662                 P_("Whether this tag affects indentation"));
663
664   ADD_SET_PROP ("rise-set", PROP_RISE_SET,
665                 P_("Rise set"),
666                 P_("Whether this tag affects the rise"));
667
668   ADD_SET_PROP ("pixels-above-lines-set", PROP_PIXELS_ABOVE_LINES_SET,
669                 P_("Pixels above lines set"),
670                 P_("Whether this tag affects the number of pixels above lines"));
671
672   ADD_SET_PROP ("pixels-below-lines-set", PROP_PIXELS_BELOW_LINES_SET,
673                 P_("Pixels below lines set"),
674                 P_("Whether this tag affects the number of pixels above lines"));
675
676   ADD_SET_PROP ("pixels-inside-wrap-set", PROP_PIXELS_INSIDE_WRAP_SET,
677                 P_("Pixels inside wrap set"),
678                 P_("Whether this tag affects the number of pixels between wrapped lines"));
679
680   ADD_SET_PROP ("strikethrough-set", PROP_STRIKETHROUGH_SET,
681                 P_("Strikethrough set"),
682                 P_("Whether this tag affects strikethrough"));
683   
684   ADD_SET_PROP ("right-margin-set", PROP_RIGHT_MARGIN_SET,
685                 P_("Right margin set"),
686                 P_("Whether this tag affects the right margin"));
687
688   ADD_SET_PROP ("underline-set", PROP_UNDERLINE_SET,
689                 P_("Underline set"),
690                 P_("Whether this tag affects underlining"));
691
692   ADD_SET_PROP ("wrap-mode-set", PROP_WRAP_MODE_SET,
693                 P_("Wrap mode set"),
694                 P_("Whether this tag affects line wrap mode"));
695
696   ADD_SET_PROP ("tabs-set", PROP_TABS_SET,
697                 P_("Tabs set"),
698                 P_("Whether this tag affects tabs"));
699
700   ADD_SET_PROP ("invisible-set", PROP_INVISIBLE_SET,
701                 P_("Invisible set"),
702                 P_("Whether this tag affects text visibility"));
703
704   ADD_SET_PROP ("paragraph-background-set", PROP_PARAGRAPH_BACKGROUND_SET,
705                 P_("Paragraph background set"),
706                 P_("Whether this tag affects the paragraph background color"));
707
708   /**
709    * GtkTextTag::event:
710    * @tag: the #GtkTextTag on which the signal is emitted
711    * @object: the object the event was fired from (typically a #GtkTextView)
712    * @event: the event which triggered the signal
713    * @iter: a #GtkTextIter pointing at the location the event occured
714    *
715    * The ::event signal is emitted when an event occurs on a region of the
716    * buffer marked with this tag.
717    *
718    * Returns: %TRUE to stop other handlers from being invoked for the
719    * event. %FALSE to propagate the event further.
720    */
721   signals[EVENT] =
722     g_signal_new (I_("event"),
723                   G_OBJECT_CLASS_TYPE (object_class),
724                   G_SIGNAL_RUN_LAST,
725                   G_STRUCT_OFFSET (GtkTextTagClass, event),
726                   _gtk_boolean_handled_accumulator, NULL,
727                   _gtk_marshal_BOOLEAN__OBJECT_BOXED_BOXED,
728                   G_TYPE_BOOLEAN,
729                   3,
730                   G_TYPE_OBJECT,
731                   GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE,
732                   GTK_TYPE_TEXT_ITER);
733
734   g_type_class_add_private (klass, sizeof (GtkTextTagPrivate));
735 }
736
737 static void
738 gtk_text_tag_init (GtkTextTag *text_tag)
739 {
740   GtkTextTagPrivate *priv;
741
742   text_tag->priv = G_TYPE_INSTANCE_GET_PRIVATE (text_tag,
743                                                 GTK_TYPE_TEXT_TAG,
744                                                 GtkTextTagPrivate);
745   priv = text_tag->priv;
746
747   priv->values = gtk_text_attributes_new ();
748 }
749
750 /**
751  * gtk_text_tag_new:
752  * @name: (allow-none): tag name, or %NULL
753  * 
754  * Creates a #GtkTextTag. Configure the tag using object arguments,
755  * i.e. using g_object_set().
756  * 
757  * Return value: a new #GtkTextTag
758  **/
759 GtkTextTag*
760 gtk_text_tag_new (const gchar *name)
761 {
762   GtkTextTag *tag;
763
764   tag = g_object_new (GTK_TYPE_TEXT_TAG, "name", name, NULL);
765
766   return tag;
767 }
768
769 static void
770 gtk_text_tag_finalize (GObject *object)
771 {
772   GtkTextTag *text_tag = GTK_TEXT_TAG (object);
773   GtkTextTagPrivate *priv = text_tag->priv;
774
775   if (priv->table)
776     gtk_text_tag_table_remove (priv->table, text_tag);
777
778   g_assert (priv->table == NULL);
779
780   gtk_text_attributes_unref (priv->values);
781   priv->values = NULL;
782
783   g_free (priv->name);
784   priv->name = NULL;
785
786   G_OBJECT_CLASS (gtk_text_tag_parent_class)->finalize (object);
787 }
788
789 static void
790 copy_rgba_to_gdk_color (GdkRGBA  *src,
791                         GdkColor *dest)
792 {
793   dest->red   = CLAMP (src->red,   0.0, 1.0) * 65535.0;
794   dest->green = CLAMP (src->green, 0.0, 1.0) * 65535.0;
795   dest->blue  = CLAMP (src->blue,  0.0, 1.0) * 65535.0;
796 }
797
798 static void
799 copy_gdk_color_to_rgba (GdkColor *src,
800                         GdkRGBA  *dest)
801 {
802   dest->red   = src->red / 65535.;
803   dest->green = src->green / 65535.;
804   dest->blue  = src->blue / 65535.;
805   dest->alpha = 1;
806 }
807
808 static void
809 set_bg_rgba (GtkTextTag *tag, GdkRGBA *rgba)
810 {
811   GtkTextTagPrivate *priv = tag->priv;
812
813   if (priv->values->appearance.rgba[0])
814     gdk_rgba_free (priv->values->appearance.rgba[0]);
815
816   priv->values->appearance.rgba[0] = NULL;
817
818   if (rgba)
819     {
820       if (!priv->bg_color_set)
821         {
822           priv->bg_color_set = TRUE;
823           g_object_notify (G_OBJECT (tag), "background-set");
824         }
825
826       priv->values->appearance.rgba[0] = gdk_rgba_copy (rgba);
827
828       copy_rgba_to_gdk_color (rgba, &priv->values->appearance.bg_color);
829     }
830   else
831     {
832       if (priv->bg_color_set)
833         {
834           priv->bg_color_set = FALSE;
835           g_object_notify (G_OBJECT (tag), "background-set");
836         }
837     }
838 }
839
840 static void
841 set_fg_rgba (GtkTextTag *tag, GdkRGBA *rgba)
842 {
843   GtkTextTagPrivate *priv = tag->priv;
844
845   if (priv->values->appearance.rgba[1])
846     gdk_rgba_free (priv->values->appearance.rgba[1]);
847
848   priv->values->appearance.rgba[1] = NULL;
849
850   if (rgba)
851     {
852       if (!priv->fg_color_set)
853         {
854           priv->fg_color_set = TRUE;
855           g_object_notify (G_OBJECT (tag), "foreground-set");
856         }
857
858       priv->values->appearance.rgba[1] = gdk_rgba_copy (rgba);
859
860       copy_rgba_to_gdk_color (rgba, &priv->values->appearance.fg_color);
861     }
862   else
863     {
864       if (priv->fg_color_set)
865         {
866           priv->fg_color_set = FALSE;
867           g_object_notify (G_OBJECT (tag), "foreground-set");
868         }
869     }
870 }
871
872 static void
873 set_pg_bg_rgba (GtkTextTag *tag, GdkRGBA *rgba)
874 {
875   GtkTextTagPrivate *priv = tag->priv;
876
877   if (priv->values->pg_bg_rgba)
878     gdk_rgba_free (priv->values->pg_bg_rgba);
879
880   if (priv->values->pg_bg_color)
881     gdk_color_free (priv->values->pg_bg_color);
882
883   priv->values->pg_bg_rgba = NULL;
884   priv->values->pg_bg_color = NULL;
885
886   if (rgba)
887     {
888       GdkColor color = { 0, };
889
890       if (!priv->pg_bg_color_set)
891         {
892           priv->pg_bg_color_set = TRUE;
893           g_object_notify (G_OBJECT (tag), "paragraph-background-set");
894         }
895
896       priv->values->pg_bg_rgba = gdk_rgba_copy (rgba);
897
898       copy_rgba_to_gdk_color (rgba, &color);
899       priv->values->pg_bg_color = gdk_color_copy (&color);
900     }
901   else
902     {
903       if (priv->pg_bg_color_set)
904         {
905           priv->pg_bg_color_set = FALSE;
906           g_object_notify (G_OBJECT (tag), "paragraph-background-set");
907         }
908     }
909 }
910
911
912 static void
913 set_bg_color (GtkTextTag *tag, GdkColor *color)
914 {
915   if (color)
916     {
917       GdkRGBA rgba;
918
919       copy_gdk_color_to_rgba (color, &rgba);
920       set_bg_rgba (tag, &rgba);
921     }
922   else
923     set_bg_rgba (tag, NULL);
924 }
925
926 static void
927 set_fg_color (GtkTextTag *tag, GdkColor *color)
928 {
929   if (color)
930     {
931       GdkRGBA rgba;
932
933       copy_gdk_color_to_rgba (color, &rgba);
934       set_fg_rgba (tag, &rgba);
935     }
936   else
937     set_fg_rgba (tag, NULL);
938 }
939
940 static void
941 set_pg_bg_color (GtkTextTag *tag, GdkColor *color)
942 {
943   if (color)
944     {
945       GdkRGBA rgba;
946
947       copy_gdk_color_to_rgba (color, &rgba);
948       set_pg_bg_rgba (tag, &rgba);
949     }
950   else
951     set_pg_bg_rgba (tag, NULL);
952 }
953
954 static PangoFontMask
955 get_property_font_set_mask (guint prop_id)
956 {
957   switch (prop_id)
958     {
959     case PROP_FAMILY_SET:
960       return PANGO_FONT_MASK_FAMILY;
961     case PROP_STYLE_SET:
962       return PANGO_FONT_MASK_STYLE;
963     case PROP_VARIANT_SET:
964       return PANGO_FONT_MASK_VARIANT;
965     case PROP_WEIGHT_SET:
966       return PANGO_FONT_MASK_WEIGHT;
967     case PROP_STRETCH_SET:
968       return PANGO_FONT_MASK_STRETCH;
969     case PROP_SIZE_SET:
970       return PANGO_FONT_MASK_SIZE;
971     }
972
973   return 0;
974 }
975
976 static PangoFontMask
977 set_font_desc_fields (PangoFontDescription *desc,
978                       PangoFontMask         to_set)
979 {
980   PangoFontMask changed_mask = 0;
981   
982   if (to_set & PANGO_FONT_MASK_FAMILY)
983     {
984       const char *family = pango_font_description_get_family (desc);
985       if (!family)
986         {
987           family = "sans";
988           changed_mask |= PANGO_FONT_MASK_FAMILY;
989         }
990
991       pango_font_description_set_family (desc, family);
992     }
993   if (to_set & PANGO_FONT_MASK_STYLE)
994     pango_font_description_set_style (desc, pango_font_description_get_style (desc));
995   if (to_set & PANGO_FONT_MASK_VARIANT)
996     pango_font_description_set_variant (desc, pango_font_description_get_variant (desc));
997   if (to_set & PANGO_FONT_MASK_WEIGHT)
998     pango_font_description_set_weight (desc, pango_font_description_get_weight (desc));
999   if (to_set & PANGO_FONT_MASK_STRETCH)
1000     pango_font_description_set_stretch (desc, pango_font_description_get_stretch (desc));
1001   if (to_set & PANGO_FONT_MASK_SIZE)
1002     {
1003       gint size = pango_font_description_get_size (desc);
1004       if (size <= 0)
1005         {
1006           size = 10 * PANGO_SCALE;
1007           changed_mask |= PANGO_FONT_MASK_SIZE;
1008         }
1009       
1010       pango_font_description_set_size (desc, size);
1011     }
1012
1013   return changed_mask;
1014 }
1015
1016 static void
1017 notify_set_changed (GObject       *object,
1018                     PangoFontMask  changed_mask)
1019 {
1020   if (changed_mask & PANGO_FONT_MASK_FAMILY)
1021     g_object_notify (object, "family-set");
1022   if (changed_mask & PANGO_FONT_MASK_STYLE)
1023     g_object_notify (object, "style-set");
1024   if (changed_mask & PANGO_FONT_MASK_VARIANT)
1025     g_object_notify (object, "variant-set");
1026   if (changed_mask & PANGO_FONT_MASK_WEIGHT)
1027     g_object_notify (object, "weight-set");
1028   if (changed_mask & PANGO_FONT_MASK_STRETCH)
1029     g_object_notify (object, "stretch-set");
1030   if (changed_mask & PANGO_FONT_MASK_SIZE)
1031     g_object_notify (object, "size-set");
1032 }
1033
1034 static void
1035 notify_fields_changed (GObject       *object,
1036                        PangoFontMask  changed_mask)
1037 {
1038   if (changed_mask & PANGO_FONT_MASK_FAMILY)
1039     g_object_notify (object, "family");
1040   if (changed_mask & PANGO_FONT_MASK_STYLE)
1041     g_object_notify (object, "style");
1042   if (changed_mask & PANGO_FONT_MASK_VARIANT)
1043     g_object_notify (object, "variant");
1044   if (changed_mask & PANGO_FONT_MASK_WEIGHT)
1045     g_object_notify (object, "weight");
1046   if (changed_mask & PANGO_FONT_MASK_STRETCH)
1047     g_object_notify (object, "stretch");
1048   if (changed_mask & PANGO_FONT_MASK_SIZE)
1049     g_object_notify (object, "size");
1050 }
1051
1052 static void
1053 set_font_description (GtkTextTag           *text_tag,
1054                       PangoFontDescription *font_desc)
1055 {
1056   GtkTextTagPrivate *priv = text_tag->priv;
1057   GObject *object = G_OBJECT (text_tag);
1058   PangoFontDescription *new_font_desc;
1059   PangoFontMask old_mask, new_mask, changed_mask, set_changed_mask;
1060   
1061   if (font_desc)
1062     new_font_desc = pango_font_description_copy (font_desc);
1063   else
1064     new_font_desc = pango_font_description_new ();
1065
1066   if (priv->values->font)
1067     old_mask = pango_font_description_get_set_fields (priv->values->font);
1068   else
1069     old_mask = 0;
1070   
1071   new_mask = pango_font_description_get_set_fields (new_font_desc);
1072
1073   changed_mask = old_mask | new_mask;
1074   set_changed_mask = old_mask ^ new_mask;
1075
1076   if (priv->values->font)
1077     pango_font_description_free (priv->values->font);
1078   priv->values->font = new_font_desc;
1079
1080   g_object_freeze_notify (object);
1081
1082   g_object_notify (object, "font-desc");
1083   g_object_notify (object, "font");
1084   
1085   if (changed_mask & PANGO_FONT_MASK_FAMILY)
1086     g_object_notify (object, "family");
1087   if (changed_mask & PANGO_FONT_MASK_STYLE)
1088     g_object_notify (object, "style");
1089   if (changed_mask & PANGO_FONT_MASK_VARIANT)
1090     g_object_notify (object, "variant");
1091   if (changed_mask & PANGO_FONT_MASK_WEIGHT)
1092     g_object_notify (object, "weight");
1093   if (changed_mask & PANGO_FONT_MASK_STRETCH)
1094     g_object_notify (object, "stretch");
1095   if (changed_mask & PANGO_FONT_MASK_SIZE)
1096     {
1097       g_object_notify (object, "size");
1098       g_object_notify (object, "size-points");
1099     }
1100
1101   notify_set_changed (object, set_changed_mask);
1102   
1103   g_object_thaw_notify (object);
1104 }
1105
1106 static void
1107 gtk_text_tag_ensure_font (GtkTextTag *text_tag)
1108 {
1109   GtkTextTagPrivate *priv = text_tag->priv;
1110
1111   if (!priv->values->font)
1112     priv->values->font = pango_font_description_new ();
1113 }
1114
1115 static void
1116 gtk_text_tag_set_property (GObject      *object,
1117                            guint         prop_id,
1118                            const GValue *value,
1119                            GParamSpec   *pspec)
1120 {
1121   GtkTextTag *text_tag = GTK_TEXT_TAG (object);
1122   GtkTextTagPrivate *priv = text_tag->priv;
1123   gboolean size_changed = FALSE;
1124
1125   switch (prop_id)
1126     {
1127     case PROP_NAME:
1128       g_return_if_fail (priv->name == NULL);
1129       priv->name = g_value_dup_string (value);
1130       break;
1131
1132     case PROP_BACKGROUND:
1133       {
1134         GdkRGBA rgba;
1135
1136         if (!g_value_get_string (value))
1137           set_bg_rgba (text_tag, NULL);       /* reset background_set to FALSE */
1138         else if (gdk_rgba_parse (&rgba, g_value_get_string (value)))
1139           set_bg_rgba (text_tag, &rgba);
1140         else
1141           g_warning ("Don't know color `%s'", g_value_get_string (value));
1142
1143         g_object_notify (object, "background-gdk");
1144       }
1145       break;
1146
1147     case PROP_FOREGROUND:
1148       {
1149         GdkRGBA rgba;
1150
1151         if (!g_value_get_string (value))
1152           set_fg_rgba (text_tag, NULL);       /* reset to foreground_set to FALSE */
1153         else if (gdk_rgba_parse (&rgba, g_value_get_string (value)))
1154           set_fg_rgba (text_tag, &rgba);
1155         else
1156           g_warning ("Don't know color `%s'", g_value_get_string (value));
1157
1158         g_object_notify (object, "foreground-gdk");
1159       }
1160       break;
1161
1162     case PROP_BACKGROUND_GDK:
1163       {
1164         GdkColor *color = g_value_get_boxed (value);
1165
1166         set_bg_color (text_tag, color);
1167       }
1168       break;
1169
1170     case PROP_FOREGROUND_GDK:
1171       {
1172         GdkColor *color = g_value_get_boxed (value);
1173
1174         set_fg_color (text_tag, color);
1175       }
1176       break;
1177
1178     case PROP_BACKGROUND_RGBA:
1179       {
1180         GdkRGBA *color = g_value_get_boxed (value);
1181
1182         set_bg_rgba (text_tag, color);
1183       }
1184       break;
1185
1186     case PROP_FOREGROUND_RGBA:
1187       {
1188         GdkRGBA *color = g_value_get_boxed (value);
1189
1190         set_fg_rgba (text_tag, color);
1191       }
1192       break;
1193
1194     case PROP_FONT:
1195       {
1196         PangoFontDescription *font_desc = NULL;
1197         const gchar *name;
1198
1199         name = g_value_get_string (value);
1200
1201         if (name)
1202           font_desc = pango_font_description_from_string (name);
1203
1204         set_font_description (text_tag, font_desc);
1205         if (font_desc)
1206           pango_font_description_free (font_desc);
1207         
1208         size_changed = TRUE;
1209       }
1210       break;
1211
1212     case PROP_FONT_DESC:
1213       {
1214         PangoFontDescription *font_desc;
1215
1216         font_desc = g_value_get_boxed (value);
1217
1218         set_font_description (text_tag, font_desc);
1219
1220         size_changed = TRUE;
1221       }
1222       break;
1223
1224     case PROP_FAMILY:
1225     case PROP_STYLE:
1226     case PROP_VARIANT:
1227     case PROP_WEIGHT:
1228     case PROP_STRETCH:
1229     case PROP_SIZE:
1230     case PROP_SIZE_POINTS:
1231       {
1232         PangoFontMask old_set_mask;
1233
1234         gtk_text_tag_ensure_font (text_tag);
1235         old_set_mask = pango_font_description_get_set_fields (priv->values->font);
1236  
1237         switch (prop_id)
1238           {
1239           case PROP_FAMILY:
1240             pango_font_description_set_family (priv->values->font,
1241                                                g_value_get_string (value));
1242             break;
1243           case PROP_STYLE:
1244             pango_font_description_set_style (priv->values->font,
1245                                               g_value_get_enum (value));
1246             break;
1247           case PROP_VARIANT:
1248             pango_font_description_set_variant (priv->values->font,
1249                                                 g_value_get_enum (value));
1250             break;
1251           case PROP_WEIGHT:
1252             pango_font_description_set_weight (priv->values->font,
1253                                                g_value_get_int (value));
1254             break;
1255           case PROP_STRETCH:
1256             pango_font_description_set_stretch (priv->values->font,
1257                                                 g_value_get_enum (value));
1258             break;
1259           case PROP_SIZE:
1260             pango_font_description_set_size (priv->values->font,
1261                                              g_value_get_int (value));
1262             g_object_notify (object, "size-points");
1263             break;
1264           case PROP_SIZE_POINTS:
1265             pango_font_description_set_size (priv->values->font,
1266                                              g_value_get_double (value) * PANGO_SCALE);
1267             g_object_notify (object, "size");
1268             break;
1269           }
1270
1271         size_changed = TRUE;
1272         notify_set_changed (object, old_set_mask & pango_font_description_get_set_fields (priv->values->font));
1273         g_object_notify (object, "font-desc");
1274         g_object_notify (object, "font");
1275
1276         break;
1277       }
1278       
1279     case PROP_SCALE:
1280       priv->values->font_scale = g_value_get_double (value);
1281       priv->scale_set = TRUE;
1282       g_object_notify (object, "scale-set");
1283       size_changed = TRUE;
1284       break;
1285       
1286     case PROP_PIXELS_ABOVE_LINES:
1287       priv->pixels_above_lines_set = TRUE;
1288       priv->values->pixels_above_lines = g_value_get_int (value);
1289       g_object_notify (object, "pixels-above-lines-set");
1290       size_changed = TRUE;
1291       break;
1292
1293     case PROP_PIXELS_BELOW_LINES:
1294       priv->pixels_below_lines_set = TRUE;
1295       priv->values->pixels_below_lines = g_value_get_int (value);
1296       g_object_notify (object, "pixels-below-lines-set");
1297       size_changed = TRUE;
1298       break;
1299
1300     case PROP_PIXELS_INSIDE_WRAP:
1301       priv->pixels_inside_wrap_set = TRUE;
1302       priv->values->pixels_inside_wrap = g_value_get_int (value);
1303       g_object_notify (object, "pixels-inside-wrap-set");
1304       size_changed = TRUE;
1305       break;
1306
1307     case PROP_EDITABLE:
1308       priv->editable_set = TRUE;
1309       priv->values->editable = g_value_get_boolean (value);
1310       g_object_notify (object, "editable-set");
1311       break;
1312
1313     case PROP_WRAP_MODE:
1314       priv->wrap_mode_set = TRUE;
1315       priv->values->wrap_mode = g_value_get_enum (value);
1316       g_object_notify (object, "wrap-mode-set");
1317       size_changed = TRUE;
1318       break;
1319
1320     case PROP_JUSTIFICATION:
1321       priv->justification_set = TRUE;
1322       priv->values->justification = g_value_get_enum (value);
1323       g_object_notify (object, "justification-set");
1324       size_changed = TRUE;
1325       break;
1326
1327     case PROP_DIRECTION:
1328       priv->values->direction = g_value_get_enum (value);
1329       break;
1330
1331     case PROP_LEFT_MARGIN:
1332       priv->left_margin_set = TRUE;
1333       priv->values->left_margin = g_value_get_int (value);
1334       g_object_notify (object, "left-margin-set");
1335       size_changed = TRUE;
1336       break;
1337
1338     case PROP_INDENT:
1339       priv->indent_set = TRUE;
1340       priv->values->indent = g_value_get_int (value);
1341       g_object_notify (object, "indent-set");
1342       size_changed = TRUE;
1343       break;
1344
1345     case PROP_STRIKETHROUGH:
1346       priv->strikethrough_set = TRUE;
1347       priv->values->appearance.strikethrough = g_value_get_boolean (value);
1348       g_object_notify (object, "strikethrough-set");
1349       break;
1350
1351     case PROP_RIGHT_MARGIN:
1352       priv->right_margin_set = TRUE;
1353       priv->values->right_margin = g_value_get_int (value);
1354       g_object_notify (object, "right-margin-set");
1355       size_changed = TRUE;
1356       break;
1357
1358     case PROP_UNDERLINE:
1359       priv->underline_set = TRUE;
1360       priv->values->appearance.underline = g_value_get_enum (value);
1361       g_object_notify (object, "underline-set");
1362       break;
1363
1364     case PROP_RISE:
1365       priv->rise_set = TRUE;
1366       priv->values->appearance.rise = g_value_get_int (value);
1367       g_object_notify (object, "rise-set");
1368       size_changed = TRUE;      
1369       break;
1370
1371     case PROP_BACKGROUND_FULL_HEIGHT:
1372       priv->bg_full_height_set = TRUE;
1373       priv->values->bg_full_height = g_value_get_boolean (value);
1374       g_object_notify (object, "background-full-height-set");
1375       break;
1376
1377     case PROP_LANGUAGE:
1378       priv->language_set = TRUE;
1379       priv->values->language = pango_language_from_string (g_value_get_string (value));
1380       g_object_notify (object, "language-set");
1381       break;
1382
1383     case PROP_TABS:
1384       priv->tabs_set = TRUE;
1385
1386       if (priv->values->tabs)
1387         pango_tab_array_free (priv->values->tabs);
1388
1389       /* FIXME I'm not sure if this is a memleak or not */
1390       priv->values->tabs =
1391         pango_tab_array_copy (g_value_get_boxed (value));
1392
1393       g_object_notify (object, "tabs-set");
1394       
1395       size_changed = TRUE;
1396       break;
1397
1398     case PROP_INVISIBLE:
1399       priv->invisible_set = TRUE;
1400       priv->values->invisible = g_value_get_boolean (value);
1401       g_object_notify (object, "invisible-set");
1402       size_changed = TRUE;
1403       break;
1404       
1405     case PROP_PARAGRAPH_BACKGROUND:
1406       {
1407         GdkRGBA rgba;
1408
1409         if (!g_value_get_string (value))
1410           set_pg_bg_rgba (text_tag, NULL);       /* reset paragraph_background_set to FALSE */
1411         else if (gdk_rgba_parse (&rgba, g_value_get_string (value)))
1412           set_pg_bg_rgba (text_tag, &rgba);
1413         else
1414           g_warning ("Don't know color `%s'", g_value_get_string (value));
1415
1416         g_object_notify (object, "paragraph-background-gdk");
1417       }
1418       break;
1419
1420     case PROP_PARAGRAPH_BACKGROUND_GDK:
1421       {
1422         GdkColor *color = g_value_get_boxed (value);
1423
1424         set_pg_bg_color (text_tag, color);
1425       }
1426       break;
1427
1428     case PROP_PARAGRAPH_BACKGROUND_RGBA:
1429       {
1430         GdkRGBA *color = g_value_get_boxed (value);
1431
1432         set_pg_bg_rgba (text_tag, color);
1433       }
1434       break;
1435
1436     case PROP_ACCUMULATIVE_MARGIN:
1437       priv->accumulative_margin = g_value_get_boolean (value);
1438       g_object_notify (object, "accumulative-margin");
1439       size_changed = TRUE;
1440       break;
1441
1442       /* Whether the value should be used... */
1443
1444     case PROP_BACKGROUND_SET:
1445       priv->bg_color_set = g_value_get_boolean (value);
1446       break;
1447
1448     case PROP_FOREGROUND_SET:
1449       priv->fg_color_set = g_value_get_boolean (value);
1450       break;
1451
1452     case PROP_FAMILY_SET:
1453     case PROP_STYLE_SET:
1454     case PROP_VARIANT_SET:
1455     case PROP_WEIGHT_SET:
1456     case PROP_STRETCH_SET:
1457     case PROP_SIZE_SET:
1458       if (!g_value_get_boolean (value))
1459         {
1460           if (priv->values->font)
1461             pango_font_description_unset_fields (priv->values->font,
1462                                                  get_property_font_set_mask (prop_id));
1463         }
1464       else
1465         {
1466           PangoFontMask changed_mask;
1467           
1468           gtk_text_tag_ensure_font (text_tag);
1469           changed_mask = set_font_desc_fields (priv->values->font,
1470                                                get_property_font_set_mask (prop_id));
1471           notify_fields_changed (G_OBJECT (text_tag), changed_mask);
1472         }
1473       break;
1474
1475     case PROP_SCALE_SET:
1476       priv->scale_set = g_value_get_boolean (value);
1477       size_changed = TRUE;
1478       break;
1479       
1480     case PROP_PIXELS_ABOVE_LINES_SET:
1481       priv->pixels_above_lines_set = g_value_get_boolean (value);
1482       size_changed = TRUE;
1483       break;
1484
1485     case PROP_PIXELS_BELOW_LINES_SET:
1486       priv->pixels_below_lines_set = g_value_get_boolean (value);
1487       size_changed = TRUE;
1488       break;
1489
1490     case PROP_PIXELS_INSIDE_WRAP_SET:
1491       priv->pixels_inside_wrap_set = g_value_get_boolean (value);
1492       size_changed = TRUE;
1493       break;
1494
1495     case PROP_EDITABLE_SET:
1496       priv->editable_set = g_value_get_boolean (value);
1497       break;
1498
1499     case PROP_WRAP_MODE_SET:
1500       priv->wrap_mode_set = g_value_get_boolean (value);
1501       size_changed = TRUE;
1502       break;
1503
1504     case PROP_JUSTIFICATION_SET:
1505       priv->justification_set = g_value_get_boolean (value);
1506       size_changed = TRUE;
1507       break;
1508       
1509     case PROP_LEFT_MARGIN_SET:
1510       priv->left_margin_set = g_value_get_boolean (value);
1511       size_changed = TRUE;
1512       break;
1513
1514     case PROP_INDENT_SET:
1515       priv->indent_set = g_value_get_boolean (value);
1516       size_changed = TRUE;
1517       break;
1518
1519     case PROP_STRIKETHROUGH_SET:
1520       priv->strikethrough_set = g_value_get_boolean (value);
1521       break;
1522
1523     case PROP_RIGHT_MARGIN_SET:
1524       priv->right_margin_set = g_value_get_boolean (value);
1525       size_changed = TRUE;
1526       break;
1527
1528     case PROP_UNDERLINE_SET:
1529       priv->underline_set = g_value_get_boolean (value);
1530       break;
1531
1532     case PROP_RISE_SET:
1533       priv->rise_set = g_value_get_boolean (value);
1534       size_changed = TRUE;
1535       break;
1536
1537     case PROP_BACKGROUND_FULL_HEIGHT_SET:
1538       priv->bg_full_height_set = g_value_get_boolean (value);
1539       break;
1540
1541     case PROP_LANGUAGE_SET:
1542       priv->language_set = g_value_get_boolean (value);
1543       size_changed = TRUE;
1544       break;
1545
1546     case PROP_TABS_SET:
1547       priv->tabs_set = g_value_get_boolean (value);
1548       size_changed = TRUE;
1549       break;
1550
1551     case PROP_INVISIBLE_SET:
1552       priv->invisible_set = g_value_get_boolean (value);
1553       size_changed = TRUE;
1554       break;
1555       
1556     case PROP_PARAGRAPH_BACKGROUND_SET:
1557       priv->pg_bg_color_set = g_value_get_boolean (value);
1558       break;
1559
1560     default:
1561       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1562       break;
1563     }
1564
1565   /* FIXME I would like to do this after all set_property in a single
1566    * g_object_set () have been called. But an idle function won't
1567    * work; we need to emit when the tag is changed, not when we get
1568    * around to the event loop. So blah, we eat some inefficiency.
1569    */
1570
1571   /* This is also somewhat weird since we emit another object's
1572    * signal here, but the two objects are already tightly bound.
1573    */
1574
1575   if (priv->table)
1576     g_signal_emit_by_name (priv->table,
1577                            "tag_changed",
1578                            text_tag, size_changed);
1579 }
1580
1581 static void
1582 gtk_text_tag_get_property (GObject      *object,
1583                            guint         prop_id,
1584                            GValue       *value,
1585                            GParamSpec   *pspec)
1586 {
1587   GtkTextTag *tag = GTK_TEXT_TAG (object);
1588   GtkTextTagPrivate *priv = tag->priv;
1589
1590   switch (prop_id)
1591     {
1592     case PROP_NAME:
1593       g_value_set_string (value, priv->name);
1594       break;
1595
1596     case PROP_BACKGROUND_GDK:
1597       g_value_set_boxed (value, &priv->values->appearance.bg_color);
1598       break;
1599
1600     case PROP_BACKGROUND_RGBA:
1601       g_value_set_boxed (value, priv->values->appearance.rgba[0]);
1602       break;
1603
1604     case PROP_FOREGROUND_GDK:
1605       g_value_set_boxed (value, &priv->values->appearance.fg_color);
1606       break;
1607
1608     case PROP_FOREGROUND_RGBA:
1609       g_value_set_boxed (value, priv->values->appearance.rgba[1]);
1610       break;
1611
1612     case PROP_FONT:
1613         {
1614           gchar *str;
1615
1616           gtk_text_tag_ensure_font (tag);
1617
1618           str = pango_font_description_to_string (priv->values->font);
1619           g_value_take_string (value, str);
1620         }
1621       break;
1622
1623     case PROP_FONT_DESC:
1624       gtk_text_tag_ensure_font (tag);
1625       g_value_set_boxed (value, priv->values->font);
1626       break;
1627
1628     case PROP_FAMILY:
1629     case PROP_STYLE:
1630     case PROP_VARIANT:
1631     case PROP_WEIGHT:
1632     case PROP_STRETCH:
1633     case PROP_SIZE:
1634     case PROP_SIZE_POINTS:
1635       gtk_text_tag_ensure_font (tag);
1636       switch (prop_id)
1637         {
1638         case PROP_FAMILY:
1639           g_value_set_string (value, pango_font_description_get_family (priv->values->font));
1640           break;
1641           
1642         case PROP_STYLE:
1643           g_value_set_enum (value, pango_font_description_get_style (priv->values->font));
1644           break;
1645           
1646         case PROP_VARIANT:
1647           g_value_set_enum (value, pango_font_description_get_variant (priv->values->font));
1648           break;
1649           
1650         case PROP_WEIGHT:
1651           g_value_set_int (value, pango_font_description_get_weight (priv->values->font));
1652           break;
1653           
1654         case PROP_STRETCH:
1655           g_value_set_enum (value, pango_font_description_get_stretch (priv->values->font));
1656           break;
1657           
1658         case PROP_SIZE:
1659           g_value_set_int (value, pango_font_description_get_size (priv->values->font));
1660           break;
1661           
1662         case PROP_SIZE_POINTS:
1663           g_value_set_double (value, ((double)pango_font_description_get_size (priv->values->font)) / (double)PANGO_SCALE);
1664           break;
1665         }
1666       break;
1667       
1668     case PROP_SCALE:
1669       g_value_set_double (value, priv->values->font_scale);
1670       break;
1671       
1672     case PROP_PIXELS_ABOVE_LINES:
1673       g_value_set_int (value,  priv->values->pixels_above_lines);
1674       break;
1675
1676     case PROP_PIXELS_BELOW_LINES:
1677       g_value_set_int (value,  priv->values->pixels_below_lines);
1678       break;
1679
1680     case PROP_PIXELS_INSIDE_WRAP:
1681       g_value_set_int (value,  priv->values->pixels_inside_wrap);
1682       break;
1683
1684     case PROP_EDITABLE:
1685       g_value_set_boolean (value, priv->values->editable);
1686       break;
1687
1688     case PROP_WRAP_MODE:
1689       g_value_set_enum (value, priv->values->wrap_mode);
1690       break;
1691
1692     case PROP_JUSTIFICATION:
1693       g_value_set_enum (value, priv->values->justification);
1694       break;
1695
1696     case PROP_DIRECTION:
1697       g_value_set_enum (value, priv->values->direction);
1698       break;
1699       
1700     case PROP_LEFT_MARGIN:
1701       g_value_set_int (value,  priv->values->left_margin);
1702       break;
1703
1704     case PROP_INDENT:
1705       g_value_set_int (value,  priv->values->indent);
1706       break;
1707
1708     case PROP_STRIKETHROUGH:
1709       g_value_set_boolean (value, priv->values->appearance.strikethrough);
1710       break;
1711
1712     case PROP_RIGHT_MARGIN:
1713       g_value_set_int (value, priv->values->right_margin);
1714       break;
1715
1716     case PROP_UNDERLINE:
1717       g_value_set_enum (value, priv->values->appearance.underline);
1718       break;
1719
1720     case PROP_RISE:
1721       g_value_set_int (value, priv->values->appearance.rise);
1722       break;
1723
1724     case PROP_BACKGROUND_FULL_HEIGHT:
1725       g_value_set_boolean (value, priv->values->bg_full_height);
1726       break;
1727
1728     case PROP_LANGUAGE:
1729       g_value_set_string (value, pango_language_to_string (priv->values->language));
1730       break;
1731
1732     case PROP_TABS:
1733       if (priv->values->tabs)
1734         g_value_set_boxed (value, priv->values->tabs);
1735       break;
1736
1737     case PROP_INVISIBLE:
1738       g_value_set_boolean (value, priv->values->invisible);
1739       break;
1740       
1741     case PROP_PARAGRAPH_BACKGROUND_GDK:
1742       g_value_set_boxed (value, priv->values->pg_bg_color);
1743       break;
1744
1745     case PROP_PARAGRAPH_BACKGROUND_RGBA:
1746       g_value_set_boxed (value, priv->values->pg_bg_rgba);
1747       break;
1748
1749     case PROP_ACCUMULATIVE_MARGIN:
1750       g_value_set_boolean (value, priv->accumulative_margin);
1751       break;
1752
1753     case PROP_BACKGROUND_SET:
1754       g_value_set_boolean (value, priv->bg_color_set);
1755       break;
1756
1757     case PROP_FOREGROUND_SET:
1758       g_value_set_boolean (value, priv->fg_color_set);
1759       break;
1760
1761     case PROP_FAMILY_SET:
1762     case PROP_STYLE_SET:
1763     case PROP_VARIANT_SET:
1764     case PROP_WEIGHT_SET:
1765     case PROP_STRETCH_SET:
1766     case PROP_SIZE_SET:
1767       {
1768         PangoFontMask set_mask = priv->values->font ? pango_font_description_get_set_fields (priv->values->font) : 0;
1769         PangoFontMask test_mask = get_property_font_set_mask (prop_id);
1770         g_value_set_boolean (value, (set_mask & test_mask) != 0);
1771
1772         break;
1773       }
1774
1775     case PROP_SCALE_SET:
1776       g_value_set_boolean (value, priv->scale_set);
1777       break;
1778       
1779     case PROP_PIXELS_ABOVE_LINES_SET:
1780       g_value_set_boolean (value, priv->pixels_above_lines_set);
1781       break;
1782
1783     case PROP_PIXELS_BELOW_LINES_SET:
1784       g_value_set_boolean (value, priv->pixels_below_lines_set);
1785       break;
1786
1787     case PROP_PIXELS_INSIDE_WRAP_SET:
1788       g_value_set_boolean (value, priv->pixels_inside_wrap_set);
1789       break;
1790
1791     case PROP_EDITABLE_SET:
1792       g_value_set_boolean (value, priv->editable_set);
1793       break;
1794
1795     case PROP_WRAP_MODE_SET:
1796       g_value_set_boolean (value, priv->wrap_mode_set);
1797       break;
1798
1799     case PROP_JUSTIFICATION_SET:
1800       g_value_set_boolean (value, priv->justification_set);
1801       break;
1802       
1803     case PROP_LEFT_MARGIN_SET:
1804       g_value_set_boolean (value, priv->left_margin_set);
1805       break;
1806
1807     case PROP_INDENT_SET:
1808       g_value_set_boolean (value, priv->indent_set);
1809       break;
1810
1811     case PROP_STRIKETHROUGH_SET:
1812       g_value_set_boolean (value, priv->strikethrough_set);
1813       break;
1814
1815     case PROP_RIGHT_MARGIN_SET:
1816       g_value_set_boolean (value, priv->right_margin_set);
1817       break;
1818
1819     case PROP_UNDERLINE_SET:
1820       g_value_set_boolean (value, priv->underline_set);
1821       break;
1822
1823     case PROP_RISE_SET:
1824       g_value_set_boolean (value, priv->rise_set);
1825       break;
1826
1827     case PROP_BACKGROUND_FULL_HEIGHT_SET:
1828       g_value_set_boolean (value, priv->bg_full_height_set);
1829       break;
1830
1831     case PROP_LANGUAGE_SET:
1832       g_value_set_boolean (value, priv->language_set);
1833       break;
1834
1835     case PROP_TABS_SET:
1836       g_value_set_boolean (value, priv->tabs_set);
1837       break;
1838
1839     case PROP_INVISIBLE_SET:
1840       g_value_set_boolean (value, priv->invisible_set);
1841       break;
1842       
1843     case PROP_PARAGRAPH_BACKGROUND_SET:
1844       g_value_set_boolean (value, priv->pg_bg_color_set);
1845       break;
1846
1847     case PROP_BACKGROUND:
1848     case PROP_FOREGROUND:
1849     case PROP_PARAGRAPH_BACKGROUND:
1850       g_warning ("'foreground', 'background' and 'paragraph_background' properties are not readable, use 'foreground_gdk', 'background_gdk' and 'paragraph_background_gdk'");
1851       break;
1852     default:
1853       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1854       break;
1855     }
1856 }
1857
1858 /*
1859  * Tag operations
1860  */
1861
1862 typedef struct {
1863   gint high;
1864   gint low;
1865   gint delta;
1866 } DeltaData;
1867
1868 static void
1869 delta_priority_foreach (GtkTextTag *tag, gpointer user_data)
1870 {
1871   GtkTextTagPrivate *priv = tag->priv;
1872   DeltaData *dd = user_data;
1873
1874   if (priv->priority >= dd->low && priv->priority <= dd->high)
1875     priv->priority += dd->delta;
1876 }
1877
1878 /**
1879  * gtk_text_tag_get_priority:
1880  * @tag: a #GtkTextTag
1881  * 
1882  * Get the tag priority.
1883  * 
1884  * Return value: The tag's priority.
1885  **/
1886 gint
1887 gtk_text_tag_get_priority (GtkTextTag *tag)
1888 {
1889   g_return_val_if_fail (GTK_IS_TEXT_TAG (tag), 0);
1890
1891   return tag->priv->priority;
1892 }
1893
1894 /**
1895  * gtk_text_tag_set_priority:
1896  * @tag: a #GtkTextTag
1897  * @priority: the new priority
1898  * 
1899  * Sets the priority of a #GtkTextTag. Valid priorities are
1900  * start at 0 and go to one less than gtk_text_tag_table_get_size().
1901  * Each tag in a table has a unique priority; setting the priority
1902  * of one tag shifts the priorities of all the other tags in the
1903  * table to maintain a unique priority for each tag. Higher priority
1904  * tags "win" if two tags both set the same text attribute. When adding
1905  * a tag to a tag table, it will be assigned the highest priority in
1906  * the table by default; so normally the precedence of a set of tags
1907  * is the order in which they were added to the table, or created with
1908  * gtk_text_buffer_create_tag(), which adds the tag to the buffer's table
1909  * automatically.
1910  **/
1911 void
1912 gtk_text_tag_set_priority (GtkTextTag *tag,
1913                            gint        priority)
1914 {
1915   GtkTextTagPrivate *priv;
1916   DeltaData dd;
1917
1918   g_return_if_fail (GTK_IS_TEXT_TAG (tag));
1919
1920   priv = tag->priv;
1921
1922   g_return_if_fail (priv->table != NULL);
1923   g_return_if_fail (priority >= 0);
1924   g_return_if_fail (priority < gtk_text_tag_table_get_size (priv->table));
1925
1926   if (priority == priv->priority)
1927     return;
1928
1929   if (priority < priv->priority)
1930     {
1931       dd.low = priority;
1932       dd.high = priv->priority - 1;
1933       dd.delta = 1;
1934     }
1935   else
1936     {
1937       dd.low = priv->priority + 1;
1938       dd.high = priority;
1939       dd.delta = -1;
1940     }
1941
1942   gtk_text_tag_table_foreach (priv->table,
1943                               delta_priority_foreach,
1944                               &dd);
1945
1946   priv->priority = priority;
1947 }
1948
1949 /**
1950  * gtk_text_tag_event:
1951  * @tag: a #GtkTextTag
1952  * @event_object: object that received the event, such as a widget
1953  * @event: the event
1954  * @iter: location where the event was received
1955  * 
1956  * Emits the "event" signal on the #GtkTextTag.
1957  * 
1958  * Return value: result of signal emission (whether the event was handled)
1959  **/
1960 gboolean
1961 gtk_text_tag_event (GtkTextTag        *tag,
1962                     GObject           *event_object,
1963                     GdkEvent          *event,
1964                     const GtkTextIter *iter)
1965 {
1966   gboolean retval = FALSE;
1967
1968   g_return_val_if_fail (GTK_IS_TEXT_TAG (tag), FALSE);
1969   g_return_val_if_fail (G_IS_OBJECT (event_object), FALSE);
1970   g_return_val_if_fail (event != NULL, FALSE);
1971
1972   g_signal_emit (tag,
1973                  signals[EVENT],
1974                  0,
1975                  event_object,
1976                  event,
1977                  iter,
1978                  &retval);
1979
1980   return retval;
1981 }
1982
1983 static int
1984 tag_sort_func (gconstpointer first, gconstpointer second)
1985 {
1986   GtkTextTag *tag1, *tag2;
1987
1988   tag1 = * (GtkTextTag **) first;
1989   tag2 = * (GtkTextTag **) second;
1990   return tag1->priv->priority - tag2->priv->priority;
1991 }
1992
1993 void
1994 _gtk_text_tag_array_sort (GtkTextTag** tag_array_p,
1995                           guint len)
1996 {
1997   int i, j, prio;
1998   GtkTextTag **tag;
1999   GtkTextTag **maxPtrPtr, *tmp;
2000
2001   g_return_if_fail (tag_array_p != NULL);
2002   g_return_if_fail (len > 0);
2003
2004   if (len < 2) {
2005     return;
2006   }
2007   if (len < 20) {
2008     GtkTextTag **iter = tag_array_p;
2009
2010     for (i = len-1; i > 0; i--, iter++) {
2011       maxPtrPtr = tag = iter;
2012       prio = tag[0]->priv->priority;
2013       for (j = i, tag++; j > 0; j--, tag++) {
2014         if (tag[0]->priv->priority < prio) {
2015           prio = tag[0]->priv->priority;
2016           maxPtrPtr = tag;
2017         }
2018       }
2019       tmp = *maxPtrPtr;
2020       *maxPtrPtr = *iter;
2021       *iter = tmp;
2022     }
2023   } else {
2024     qsort ((void *) tag_array_p, (unsigned) len, sizeof (GtkTextTag *),
2025            tag_sort_func);
2026   }
2027
2028 #if 0
2029   {
2030     printf ("Sorted tag array: \n");
2031     i = 0;
2032     while (i < len)
2033       {
2034         GtkTextTag *t = tag_array_p[i];
2035         printf ("  %s priority %d\n", t->name, t->priority);
2036
2037         ++i;
2038       }
2039   }
2040 #endif
2041 }
2042