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