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