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