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