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