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