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