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