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