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