]> Pileus Git - ~andy/gtk/blob - gtk/gtktexttag.c
Deprecation cleanup
[~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 get_color_arg (GValue *value, GdkColor *orig)
1354 {
1355   g_value_init (value, GDK_TYPE_COLOR);
1356   g_value_set_boxed (value, orig);
1357 }
1358
1359 static void
1360 gtk_text_tag_get_property (GObject      *object,
1361                            guint         prop_id,
1362                            GValue       *value,
1363                            GParamSpec   *pspec)
1364 {
1365   GtkTextTag *tag;
1366
1367   tag = GTK_TEXT_TAG (object);
1368
1369   switch (prop_id)
1370     {
1371     case PROP_NAME:
1372       g_value_set_string (value, tag->name);
1373       break;
1374
1375     case PROP_BACKGROUND_GDK:
1376       get_color_arg (value, &tag->values->appearance.bg_color);
1377       break;
1378
1379     case PROP_FOREGROUND_GDK:
1380       get_color_arg (value, &tag->values->appearance.fg_color);
1381       break;
1382
1383     case PROP_BACKGROUND_STIPPLE:
1384       if (tag->bg_stipple_set)
1385         g_value_set_boxed (value, tag->values->appearance.bg_stipple);
1386       break;
1387
1388     case PROP_FOREGROUND_STIPPLE:
1389       if (tag->fg_stipple_set)
1390         g_value_set_boxed (value, tag->values->appearance.fg_stipple);
1391       break;
1392
1393     case PROP_FONT:
1394         {
1395           /* FIXME GValue imposes a totally gratuitous string copy
1396            * here, we could just hand off string ownership
1397            */
1398           gchar *str;
1399
1400           gtk_text_tag_ensure_font (tag);
1401           
1402           str = pango_font_description_to_string (tag->values->font);
1403           g_value_set_string (value, str);
1404           g_free (str);
1405         }
1406       break;
1407
1408     case PROP_FONT_DESC:
1409       gtk_text_tag_ensure_font (tag);
1410       g_value_set_boxed (value, tag->values->font);
1411       break;
1412
1413     case PROP_FAMILY:
1414     case PROP_STYLE:
1415     case PROP_VARIANT:
1416     case PROP_WEIGHT:
1417     case PROP_STRETCH:
1418     case PROP_SIZE:
1419     case PROP_SIZE_POINTS:
1420       gtk_text_tag_ensure_font (tag);
1421       switch (prop_id)
1422         {
1423         case PROP_FAMILY:
1424           g_value_set_string (value, pango_font_description_get_family (tag->values->font));
1425           break;
1426           
1427         case PROP_STYLE:
1428           g_value_set_enum (value, pango_font_description_get_style (tag->values->font));
1429           break;
1430           
1431         case PROP_VARIANT:
1432           g_value_set_enum (value, pango_font_description_get_variant (tag->values->font));
1433           break;
1434           
1435         case PROP_WEIGHT:
1436           g_value_set_int (value, pango_font_description_get_weight (tag->values->font));
1437           break;
1438           
1439         case PROP_STRETCH:
1440           g_value_set_enum (value, pango_font_description_get_stretch (tag->values->font));
1441           break;
1442           
1443         case PROP_SIZE:
1444           g_value_set_int (value, pango_font_description_get_size (tag->values->font));
1445           break;
1446           
1447         case PROP_SIZE_POINTS:
1448           g_value_set_double (value, ((double)pango_font_description_get_size (tag->values->font)) / (double)PANGO_SCALE);
1449           break;
1450         }
1451       break;
1452       
1453     case PROP_SCALE:
1454       g_value_set_double (value, tag->values->font_scale);
1455       break;
1456       
1457     case PROP_PIXELS_ABOVE_LINES:
1458       g_value_set_int (value,  tag->values->pixels_above_lines);
1459       break;
1460
1461     case PROP_PIXELS_BELOW_LINES:
1462       g_value_set_int (value,  tag->values->pixels_below_lines);
1463       break;
1464
1465     case PROP_PIXELS_INSIDE_WRAP:
1466       g_value_set_int (value,  tag->values->pixels_inside_wrap);
1467       break;
1468
1469     case PROP_EDITABLE:
1470       g_value_set_boolean (value, tag->values->editable);
1471       break;
1472
1473     case PROP_WRAP_MODE:
1474       g_value_set_enum (value, tag->values->wrap_mode);
1475       break;
1476
1477     case PROP_JUSTIFICATION:
1478       g_value_set_enum (value, tag->values->justification);
1479       break;
1480
1481     case PROP_DIRECTION:
1482       g_value_set_enum (value, tag->values->direction);
1483       break;
1484       
1485     case PROP_LEFT_MARGIN:
1486       g_value_set_int (value,  tag->values->left_margin);
1487       break;
1488
1489     case PROP_INDENT:
1490       g_value_set_int (value,  tag->values->indent);
1491       break;
1492
1493     case PROP_STRIKETHROUGH:
1494       g_value_set_boolean (value, tag->values->appearance.strikethrough);
1495       break;
1496
1497     case PROP_RIGHT_MARGIN:
1498       g_value_set_int (value, tag->values->right_margin);
1499       break;
1500
1501     case PROP_UNDERLINE:
1502       g_value_set_enum (value, tag->values->appearance.underline);
1503       break;
1504
1505     case PROP_RISE:
1506       g_value_set_int (value, tag->values->appearance.rise);
1507       break;
1508
1509     case PROP_BG_FULL_HEIGHT:
1510       g_value_set_boolean (value, tag->values->bg_full_height);
1511       break;
1512
1513     case PROP_LANGUAGE:
1514       g_value_set_string (value, pango_language_to_string (tag->values->language));
1515       break;
1516
1517     case PROP_TABS:
1518       if (tag->values->tabs)
1519         g_value_set_boxed (value, tag->values->tabs);
1520       break;
1521
1522     case PROP_INVISIBLE:
1523       g_value_set_boolean (value, tag->values->invisible);
1524       break;
1525       
1526     case PROP_BACKGROUND_SET:
1527       g_value_set_boolean (value, tag->bg_color_set);
1528       break;
1529
1530     case PROP_FOREGROUND_SET:
1531       g_value_set_boolean (value, tag->fg_color_set);
1532       break;
1533
1534     case PROP_BACKGROUND_STIPPLE_SET:
1535       g_value_set_boolean (value, tag->bg_stipple_set);
1536       break;
1537
1538     case PROP_FOREGROUND_STIPPLE_SET:
1539       g_value_set_boolean (value, tag->fg_stipple_set);
1540       break;
1541
1542     case PROP_FAMILY_SET:
1543     case PROP_STYLE_SET:
1544     case PROP_VARIANT_SET:
1545     case PROP_WEIGHT_SET:
1546     case PROP_STRETCH_SET:
1547     case PROP_SIZE_SET:
1548       {
1549         PangoFontMask set_mask = tag->values->font ? pango_font_description_get_set_fields (tag->values->font) : 0;
1550         PangoFontMask test_mask = get_property_font_set_mask (prop_id);
1551         g_value_set_boolean (value, (set_mask & test_mask) != 0);
1552
1553         break;
1554       }
1555
1556     case PROP_SCALE_SET:
1557       g_value_set_boolean (value, tag->scale_set);
1558       break;
1559       
1560     case PROP_PIXELS_ABOVE_LINES_SET:
1561       g_value_set_boolean (value, tag->pixels_above_lines_set);
1562       break;
1563
1564     case PROP_PIXELS_BELOW_LINES_SET:
1565       g_value_set_boolean (value, tag->pixels_below_lines_set);
1566       break;
1567
1568     case PROP_PIXELS_INSIDE_WRAP_SET:
1569       g_value_set_boolean (value, tag->pixels_inside_wrap_set);
1570       break;
1571
1572     case PROP_EDITABLE_SET:
1573       g_value_set_boolean (value, tag->editable_set);
1574       break;
1575
1576     case PROP_WRAP_MODE_SET:
1577       g_value_set_boolean (value, tag->wrap_mode_set);
1578       break;
1579
1580     case PROP_JUSTIFICATION_SET:
1581       g_value_set_boolean (value, tag->justification_set);
1582       break;
1583       
1584     case PROP_LEFT_MARGIN_SET:
1585       g_value_set_boolean (value, tag->left_margin_set);
1586       break;
1587
1588     case PROP_INDENT_SET:
1589       g_value_set_boolean (value, tag->indent_set);
1590       break;
1591
1592     case PROP_STRIKETHROUGH_SET:
1593       g_value_set_boolean (value, tag->strikethrough_set);
1594       break;
1595
1596     case PROP_RIGHT_MARGIN_SET:
1597       g_value_set_boolean (value, tag->right_margin_set);
1598       break;
1599
1600     case PROP_UNDERLINE_SET:
1601       g_value_set_boolean (value, tag->underline_set);
1602       break;
1603
1604     case PROP_RISE_SET:
1605       g_value_set_boolean (value, tag->rise_set);
1606       break;
1607
1608     case PROP_BG_FULL_HEIGHT_SET:
1609       g_value_set_boolean (value, tag->bg_full_height_set);
1610       break;
1611
1612     case PROP_LANGUAGE_SET:
1613       g_value_set_boolean (value, tag->language_set);
1614       break;
1615
1616     case PROP_TABS_SET:
1617       g_value_set_boolean (value, tag->tabs_set);
1618       break;
1619
1620     case PROP_INVISIBLE_SET:
1621       g_value_set_boolean (value, tag->invisible_set);
1622       break;
1623       
1624     case PROP_BACKGROUND:
1625     case PROP_FOREGROUND:
1626       g_warning ("'foreground' and 'background' properties are not readable, use 'foreground_gdk' and 'background_gdk'");
1627     default:
1628       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1629       break;
1630     }
1631 }
1632
1633 /*
1634  * Tag operations
1635  */
1636
1637 typedef struct {
1638   gint high;
1639   gint low;
1640   gint delta;
1641 } DeltaData;
1642
1643 static void
1644 delta_priority_foreach (GtkTextTag *tag, gpointer user_data)
1645 {
1646   DeltaData *dd = user_data;
1647
1648   if (tag->priority >= dd->low && tag->priority <= dd->high)
1649     tag->priority += dd->delta;
1650 }
1651
1652 /**
1653  * gtk_text_tag_get_priority:
1654  * @tag: a #GtkTextTag
1655  * 
1656  * Get the tag priority.
1657  * 
1658  * Return value: The tag's priority.
1659  **/
1660 gint
1661 gtk_text_tag_get_priority (GtkTextTag *tag)
1662 {
1663   g_return_val_if_fail (GTK_IS_TEXT_TAG (tag), 0);
1664
1665   return tag->priority;
1666 }
1667
1668 /**
1669  * gtk_text_tag_set_priority:
1670  * @tag: a #GtkTextTag
1671  * @priority: the new priority
1672  * 
1673  * Sets the priority of a #GtkTextTag. Valid priorities are
1674  * start at 0 and go to one less than gtk_text_tag_table_get_size().
1675  * Each tag in a table has a unique priority; setting the priority
1676  * of one tag shifts the priorities of all the other tags in the
1677  * table to maintain a unique priority for each tag. Higher priority
1678  * tags "win" if two tags both set the same text attribute. When adding
1679  * a tag to a tag table, it will be assigned the highest priority in
1680  * the table by default; so normally the precedence of a set of tags
1681  * is the order in which they were added to the table, or created with
1682  * gtk_text_buffer_create_tag(), which adds the tag to the buffer's table
1683  * automatically.
1684  **/
1685 void
1686 gtk_text_tag_set_priority (GtkTextTag *tag,
1687                            gint        priority)
1688 {
1689   DeltaData dd;
1690
1691   g_return_if_fail (GTK_IS_TEXT_TAG (tag));
1692   g_return_if_fail (tag->table != NULL);
1693   g_return_if_fail (priority >= 0);
1694   g_return_if_fail (priority < gtk_text_tag_table_get_size (tag->table));
1695
1696   if (priority == tag->priority)
1697     return;
1698
1699   if (priority < tag->priority)
1700     {
1701       dd.low = priority;
1702       dd.high = tag->priority - 1;
1703       dd.delta = 1;
1704     }
1705   else
1706     {
1707       dd.low = tag->priority + 1;
1708       dd.high = priority;
1709       dd.delta = -1;
1710     }
1711
1712   gtk_text_tag_table_foreach (tag->table,
1713                               delta_priority_foreach,
1714                               &dd);
1715
1716   tag->priority = priority;
1717 }
1718
1719 /**
1720  * gtk_text_tag_event:
1721  * @tag: a #GtkTextTag
1722  * @event_object: object that received the event, such as a widget
1723  * @event: the event
1724  * @iter: location where the event was received
1725  * 
1726  * Emits the "event" signal on the #GtkTextTag.
1727  * 
1728  * Return value: result of signal emission (whether the event was handled)
1729  **/
1730 gboolean
1731 gtk_text_tag_event (GtkTextTag        *tag,
1732                     GObject           *event_object,
1733                     GdkEvent          *event,
1734                     const GtkTextIter *iter)
1735 {
1736   gboolean retval = FALSE;
1737
1738   g_return_val_if_fail (GTK_IS_TEXT_TAG (tag), FALSE);
1739   g_return_val_if_fail (G_IS_OBJECT (event_object), FALSE);
1740   g_return_val_if_fail (event != NULL, FALSE);
1741
1742   g_signal_emit (tag,
1743                  signals[EVENT],
1744                  0,
1745                  event_object,
1746                  event,
1747                  iter,
1748                  &retval);
1749
1750   return retval;
1751 }
1752
1753 static int
1754 tag_sort_func (gconstpointer first, gconstpointer second)
1755 {
1756   GtkTextTag *tag1, *tag2;
1757
1758   tag1 = * (GtkTextTag **) first;
1759   tag2 = * (GtkTextTag **) second;
1760   return tag1->priority - tag2->priority;
1761 }
1762
1763 void
1764 _gtk_text_tag_array_sort (GtkTextTag** tag_array_p,
1765                           guint len)
1766 {
1767   int i, j, prio;
1768   GtkTextTag **tag;
1769   GtkTextTag **maxPtrPtr, *tmp;
1770
1771   g_return_if_fail (tag_array_p != NULL);
1772   g_return_if_fail (len > 0);
1773
1774   if (len < 2) {
1775     return;
1776   }
1777   if (len < 20) {
1778     GtkTextTag **iter = tag_array_p;
1779
1780     for (i = len-1; i > 0; i--, iter++) {
1781       maxPtrPtr = tag = iter;
1782       prio = tag[0]->priority;
1783       for (j = i, tag++; j > 0; j--, tag++) {
1784         if (tag[0]->priority < prio) {
1785           prio = tag[0]->priority;
1786           maxPtrPtr = tag;
1787         }
1788       }
1789       tmp = *maxPtrPtr;
1790       *maxPtrPtr = *iter;
1791       *iter = tmp;
1792     }
1793   } else {
1794     qsort ((void *) tag_array_p, (unsigned) len, sizeof (GtkTextTag *),
1795            tag_sort_func);
1796   }
1797
1798 #if 0
1799   {
1800     printf ("Sorted tag array: \n");
1801     i = 0;
1802     while (i < len)
1803       {
1804         GtkTextTag *t = tag_array_p[i];
1805         printf ("  %s priority %d\n", t->name, t->priority);
1806
1807         ++i;
1808       }
1809   }
1810 #endif
1811 }
1812
1813 /*
1814  * Attributes
1815  */
1816
1817 /**
1818  * gtk_text_attributes_new:
1819  * 
1820  * Creates a #GtkTextAttributes, which describes
1821  * a set of properties on some text.
1822  * 
1823  * Return value: a new #GtkTextAttributes
1824  **/
1825 GtkTextAttributes*
1826 gtk_text_attributes_new (void)
1827 {
1828   GtkTextAttributes *values;
1829
1830   values = g_new0 (GtkTextAttributes, 1);
1831
1832   /* 0 is a valid value for most of the struct */
1833
1834   values->refcount = 1;
1835
1836   values->language = gtk_get_default_language ();
1837
1838   values->font_scale = 1.0;
1839   
1840   return values;
1841 }
1842
1843 /**
1844  * gtk_text_attributes_copy:
1845  * @src: a #GtkTextAttributes to be copied
1846  * 
1847  * Copies @src and returns a new #GtkTextAttributes.
1848  * 
1849  * Return value: a copy of @src
1850  **/
1851 GtkTextAttributes*
1852 gtk_text_attributes_copy (GtkTextAttributes *src)
1853 {
1854   GtkTextAttributes *dest;
1855
1856   dest = gtk_text_attributes_new ();
1857   gtk_text_attributes_copy_values (src, dest);
1858
1859   return dest;
1860 }
1861
1862 GType
1863 gtk_text_attributes_get_type (void)
1864 {
1865   static GType our_type = 0;
1866   
1867   if (our_type == 0)
1868     our_type = g_boxed_type_register_static ("GtkTextAttributes",
1869                                              (GBoxedCopyFunc) gtk_text_attributes_ref,
1870                                              (GBoxedFreeFunc) gtk_text_attributes_unref);
1871
1872   return our_type;
1873 }
1874
1875 /**
1876  * gtk_text_attributes_copy_values:
1877  * @src: a #GtkTextAttributes
1878  * @dest: another #GtkTextAttributes
1879  * 
1880  * Copies the values from @src to @dest so that @dest has the same values
1881  * as @src. Frees existing values in @dest.
1882  **/
1883 void
1884 gtk_text_attributes_copy_values (GtkTextAttributes *src,
1885                                  GtkTextAttributes *dest)
1886 {
1887   guint orig_refcount;
1888
1889   g_return_if_fail (!dest->realized);
1890
1891   if (src == dest)
1892     return;
1893
1894   /* Add refs */
1895
1896   if (src->appearance.bg_stipple)
1897     g_object_ref (src->appearance.bg_stipple);
1898
1899   if (src->appearance.fg_stipple)
1900     g_object_ref (src->appearance.fg_stipple);
1901
1902   /* Remove refs */
1903
1904   if (dest->appearance.bg_stipple)
1905     g_object_unref (dest->appearance.bg_stipple);
1906
1907   if (dest->appearance.fg_stipple)
1908     g_object_unref (dest->appearance.fg_stipple);
1909
1910   if (dest->font)
1911     pango_font_description_free (dest->font);
1912   
1913   /* Copy */
1914   orig_refcount = dest->refcount;
1915
1916   *dest = *src;
1917
1918   if (src->tabs)
1919     dest->tabs = pango_tab_array_copy (src->tabs);
1920
1921   dest->language = src->language;
1922
1923   if (dest->font)
1924     dest->font = pango_font_description_copy (src->font);
1925   
1926   dest->refcount = orig_refcount;
1927   dest->realized = FALSE;
1928 }
1929
1930 /**
1931  * gtk_text_attributes_ref:
1932  * @values: a #GtkTextAttributes
1933  * 
1934  * Increments the reference count on @values.
1935  **/
1936 void
1937 gtk_text_attributes_ref (GtkTextAttributes *values)
1938 {
1939   g_return_if_fail (values != NULL);
1940
1941   values->refcount += 1;
1942 }
1943
1944 /**
1945  * gtk_text_attributes_unref:
1946  * @values: a #GtkTextAttributes
1947  * 
1948  * Decrements the reference count on @values, freeing the structure
1949  * if the reference count reaches 0.
1950  **/
1951 void
1952 gtk_text_attributes_unref (GtkTextAttributes *values)
1953 {
1954   g_return_if_fail (values != NULL);
1955   g_return_if_fail (values->refcount > 0);
1956
1957   values->refcount -= 1;
1958
1959   if (values->refcount == 0)
1960     {
1961       g_assert (!values->realized);
1962
1963       if (values->appearance.bg_stipple)
1964         g_object_unref (values->appearance.bg_stipple);
1965
1966       if (values->appearance.fg_stipple)
1967         g_object_unref (values->appearance.fg_stipple);
1968
1969       if (values->tabs)
1970         pango_tab_array_free (values->tabs);
1971
1972       if (values->font)
1973         pango_font_description_free (values->font);
1974       
1975       g_free (values);
1976     }
1977 }
1978
1979 void
1980 _gtk_text_attributes_realize (GtkTextAttributes *values,
1981                               GdkColormap *cmap,
1982                               GdkVisual *visual)
1983 {
1984   g_return_if_fail (values != NULL);
1985   g_return_if_fail (values->refcount > 0);
1986   g_return_if_fail (!values->realized);
1987
1988   /* It is wrong to use this colormap, FIXME */
1989   gdk_colormap_alloc_color (cmap,
1990                             &values->appearance.fg_color,
1991                             FALSE, TRUE);
1992
1993   gdk_colormap_alloc_color (cmap,
1994                             &values->appearance.bg_color,
1995                             FALSE, TRUE);
1996
1997   values->realized = TRUE;
1998 }
1999
2000 void
2001 _gtk_text_attributes_unrealize (GtkTextAttributes *values,
2002                                 GdkColormap *cmap,
2003                                 GdkVisual *visual)
2004 {
2005   g_return_if_fail (values != NULL);
2006   g_return_if_fail (values->refcount > 0);
2007   g_return_if_fail (values->realized);
2008
2009   gdk_colormap_free_colors (cmap,
2010                             &values->appearance.fg_color, 1);
2011
2012
2013   gdk_colormap_free_colors (cmap,
2014                             &values->appearance.bg_color, 1);
2015
2016   values->appearance.fg_color.pixel = 0;
2017   values->appearance.bg_color.pixel = 0;
2018
2019   values->realized = FALSE;
2020 }
2021
2022 void
2023 _gtk_text_attributes_fill_from_tags (GtkTextAttributes *dest,
2024                                      GtkTextTag**       tags,
2025                                      guint              n_tags)
2026 {
2027   guint n = 0;
2028
2029   g_return_if_fail (!dest->realized);
2030
2031   while (n < n_tags)
2032     {
2033       GtkTextTag *tag = tags[n];
2034       GtkTextAttributes *vals = tag->values;
2035
2036       g_assert (tag->table != NULL);
2037       if (n > 0)
2038         g_assert (tags[n]->priority > tags[n-1]->priority);
2039
2040       if (tag->bg_color_set)
2041         {
2042           dest->appearance.bg_color = vals->appearance.bg_color;
2043
2044           dest->appearance.draw_bg = TRUE;
2045         }
2046       if (tag->fg_color_set)
2047         dest->appearance.fg_color = vals->appearance.fg_color;
2048       
2049       if (tag->bg_stipple_set)
2050         {
2051           g_object_ref (vals->appearance.bg_stipple);
2052           if (dest->appearance.bg_stipple)
2053             g_object_unref (dest->appearance.bg_stipple);
2054           dest->appearance.bg_stipple = vals->appearance.bg_stipple;
2055
2056           dest->appearance.draw_bg = TRUE;
2057         }
2058
2059       if (tag->fg_stipple_set)
2060         {
2061           g_object_ref (vals->appearance.fg_stipple);
2062           if (dest->appearance.fg_stipple)
2063             g_object_unref (dest->appearance.fg_stipple);
2064           dest->appearance.fg_stipple = vals->appearance.fg_stipple;
2065         }
2066
2067       if (vals->font)
2068         {
2069           if (dest->font)
2070             pango_font_description_merge (dest->font, vals->font, TRUE);
2071           else
2072             dest->font = pango_font_description_copy (vals->font);
2073         }
2074
2075       /* multiply all the scales together to get a composite */
2076       if (tag->scale_set)
2077         dest->font_scale *= vals->font_scale;
2078       
2079       if (tag->justification_set)
2080         dest->justification = vals->justification;
2081
2082       if (vals->direction != GTK_TEXT_DIR_NONE)
2083         dest->direction = vals->direction;
2084
2085       if (tag->left_margin_set)
2086         dest->left_margin = vals->left_margin;
2087
2088       if (tag->indent_set)
2089         dest->indent = vals->indent;
2090
2091       if (tag->rise_set)
2092         dest->appearance.rise = vals->appearance.rise;
2093
2094       if (tag->right_margin_set)
2095         dest->right_margin = vals->right_margin;
2096
2097       if (tag->pixels_above_lines_set)
2098         dest->pixels_above_lines = vals->pixels_above_lines;
2099
2100       if (tag->pixels_below_lines_set)
2101         dest->pixels_below_lines = vals->pixels_below_lines;
2102
2103       if (tag->pixels_inside_wrap_set)
2104         dest->pixels_inside_wrap = vals->pixels_inside_wrap;
2105
2106       if (tag->tabs_set)
2107         {
2108           if (dest->tabs)
2109             pango_tab_array_free (dest->tabs);
2110           dest->tabs = pango_tab_array_copy (vals->tabs);
2111         }
2112
2113       if (tag->wrap_mode_set)
2114         dest->wrap_mode = vals->wrap_mode;
2115
2116       if (tag->underline_set)
2117         dest->appearance.underline = vals->appearance.underline;
2118
2119       if (tag->strikethrough_set)
2120         dest->appearance.strikethrough = vals->appearance.strikethrough;
2121
2122       if (tag->invisible_set)
2123         dest->invisible = vals->invisible;
2124
2125       if (tag->editable_set)
2126         dest->editable = vals->editable;
2127
2128       if (tag->bg_full_height_set)
2129         dest->bg_full_height = vals->bg_full_height;
2130
2131       if (tag->language_set)
2132         dest->language = vals->language;
2133
2134       ++n;
2135     }
2136 }
2137
2138 gboolean
2139 _gtk_text_tag_affects_size (GtkTextTag *tag)
2140 {
2141   g_return_val_if_fail (GTK_IS_TEXT_TAG (tag), FALSE);
2142
2143   return
2144     (tag->values->font && pango_font_description_get_set_fields (tag->values->font) != 0) ||
2145     tag->scale_set ||
2146     tag->justification_set ||
2147     tag->left_margin_set ||
2148     tag->indent_set ||
2149     tag->rise_set ||
2150     tag->right_margin_set ||
2151     tag->pixels_above_lines_set ||
2152     tag->pixels_below_lines_set ||
2153     tag->pixels_inside_wrap_set ||
2154     tag->tabs_set ||
2155     tag->underline_set ||
2156     tag->wrap_mode_set ||
2157     tag->invisible_set;
2158 }
2159
2160 gboolean
2161 _gtk_text_tag_affects_nonsize_appearance (GtkTextTag *tag)
2162 {
2163   g_return_val_if_fail (GTK_IS_TEXT_TAG (tag), FALSE);
2164
2165   return
2166     tag->bg_color_set ||
2167     tag->bg_stipple_set ||
2168     tag->fg_color_set ||
2169     tag->fg_stipple_set ||
2170     tag->strikethrough_set ||
2171     tag->bg_full_height_set;
2172 }