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