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