]> Pileus Git - ~andy/gtk/blob - gtk/gtktexttag.c
Fix type names for GtkIconSet, GtkIconSource, GtkSelectionData, GtkBorder,
[~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 "gtkmarshalers.h"
58 #include "gtktypebuiltins.h"
59
60 #include <stdlib.h>
61 #include <string.h>
62
63 enum {
64   EVENT,
65   LAST_SIGNAL
66 };
67
68 enum {
69   PROP_0,
70   /* Construct args */
71   PROP_NAME,
72
73   /* Style args */
74   PROP_BACKGROUND,
75   PROP_FOREGROUND,
76   PROP_BACKGROUND_GDK,
77   PROP_FOREGROUND_GDK,
78   PROP_BACKGROUND_STIPPLE,
79   PROP_FOREGROUND_STIPPLE,
80   PROP_FONT,
81   PROP_FONT_DESC,
82   PROP_FAMILY,
83   PROP_STYLE,
84   PROP_VARIANT,
85   PROP_WEIGHT,
86   PROP_STRETCH,
87   PROP_SIZE,
88   PROP_SIZE_POINTS,
89   PROP_SCALE,
90   PROP_PIXELS_ABOVE_LINES,
91   PROP_PIXELS_BELOW_LINES,
92   PROP_PIXELS_INSIDE_WRAP,
93   PROP_EDITABLE,
94   PROP_WRAP_MODE,
95   PROP_JUSTIFICATION,
96   PROP_DIRECTION,
97   PROP_LEFT_MARGIN,
98   PROP_INDENT,
99   PROP_STRIKETHROUGH,
100   PROP_RIGHT_MARGIN,
101   PROP_UNDERLINE,
102   PROP_RISE,
103   PROP_BG_FULL_HEIGHT,
104   PROP_LANGUAGE,
105   PROP_TABS,
106   PROP_INVISIBLE,
107   
108   /* Whether-a-style-arg-is-set args */
109   PROP_BACKGROUND_SET,
110   PROP_FOREGROUND_SET,
111   PROP_BACKGROUND_STIPPLE_SET,
112   PROP_FOREGROUND_STIPPLE_SET,
113   PROP_FAMILY_SET,
114   PROP_STYLE_SET,
115   PROP_VARIANT_SET,
116   PROP_WEIGHT_SET,
117   PROP_STRETCH_SET,
118   PROP_SIZE_SET,
119   PROP_SCALE_SET,
120   PROP_PIXELS_ABOVE_LINES_SET,
121   PROP_PIXELS_BELOW_LINES_SET,
122   PROP_PIXELS_INSIDE_WRAP_SET,
123   PROP_EDITABLE_SET,
124   PROP_WRAP_MODE_SET,
125   PROP_JUSTIFICATION_SET,
126   PROP_LEFT_MARGIN_SET,
127   PROP_INDENT_SET,
128   PROP_STRIKETHROUGH_SET,
129   PROP_RIGHT_MARGIN_SET,
130   PROP_UNDERLINE_SET,
131   PROP_RISE_SET,
132   PROP_BG_FULL_HEIGHT_SET,
133   PROP_LANGUAGE_SET,
134   PROP_TABS_SET,
135   PROP_INVISIBLE_SET,
136
137   LAST_ARG
138 };
139 static void gtk_text_tag_init         (GtkTextTag      *text_tag);
140 static void gtk_text_tag_class_init   (GtkTextTagClass *klass);
141 static void gtk_text_tag_finalize     (GObject         *object);
142 static void gtk_text_tag_set_property (GObject         *object,
143                                        guint            prop_id,
144                                        const GValue    *value,
145                                        GParamSpec      *pspec);
146 static void gtk_text_tag_get_property (GObject         *object,
147                                        guint            prop_id,
148                                        GValue          *value,
149                                        GParamSpec      *pspec);
150
151 static GObjectClass *parent_class = NULL;
152 static guint signals[LAST_SIGNAL] = { 0 };
153
154 GType
155 gtk_text_tag_get_type (void)
156 {
157   static GType our_type = 0;
158
159   if (our_type == 0)
160     {
161       static const GTypeInfo our_info =
162       {
163         sizeof (GtkTextTagClass),
164         (GBaseInitFunc) NULL,
165         (GBaseFinalizeFunc) NULL,
166         (GClassInitFunc) gtk_text_tag_class_init,
167         NULL,           /* class_finalize */
168         NULL,           /* class_data */
169         sizeof (GtkTextTag),
170         0,              /* n_preallocs */
171         (GInstanceInitFunc) gtk_text_tag_init
172       };
173
174       our_type = g_type_register_static (G_TYPE_OBJECT,
175                                          "GtkTextTag",
176                                          &our_info,
177                                          0);
178     }
179
180   return our_type;
181 }
182
183 static void
184 gtk_text_tag_class_init (GtkTextTagClass *klass)
185 {
186   GObjectClass *object_class = G_OBJECT_CLASS (klass);
187
188   parent_class = g_type_class_peek_parent (klass);
189
190   object_class->set_property = gtk_text_tag_set_property;
191   object_class->get_property = gtk_text_tag_get_property;
192   
193   object_class->finalize = gtk_text_tag_finalize;
194
195   /* Construct */
196   g_object_class_install_property (object_class,
197                                    PROP_NAME,
198                                    g_param_spec_string ("name",
199                                                         _("Tag name"),
200                                                         _("Name used to refer to the text tag. NULL for anonymous tags."),
201                                                         NULL,
202                                                         G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
203
204   /* Style args */
205
206   g_object_class_install_property (object_class,
207                                    PROP_BACKGROUND,
208                                    g_param_spec_string ("background",
209                                                         _("Background color name"),
210                                                         _("Background color as a string"),
211                                                         NULL,
212                                                         G_PARAM_WRITABLE));
213
214   g_object_class_install_property (object_class,
215                                    PROP_BACKGROUND_GDK,
216                                    g_param_spec_boxed ("background_gdk",
217                                                        _("Background color"),
218                                                        _("Background color as a (possibly unallocated) GdkColor"),
219                                                        GDK_TYPE_COLOR,
220                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));
221
222   g_object_class_install_property (object_class,
223                                    PROP_BG_FULL_HEIGHT,
224                                    g_param_spec_boolean ("background_full_height",
225                                                          _("Background full height"),
226                                                          _("Whether the background color fills the entire line height or only the height of the tagged characters"),
227                                                          FALSE,
228                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
229
230   
231   g_object_class_install_property (object_class,
232                                    PROP_BACKGROUND_STIPPLE,
233                                    g_param_spec_object ("background_stipple",
234                                                         _("Background stipple mask"),
235                                                         _("Bitmap to use as a mask when drawing the text background"),
236                                                         GDK_TYPE_PIXMAP,
237                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));  
238
239
240   g_object_class_install_property (object_class,
241                                    PROP_FOREGROUND,
242                                    g_param_spec_string ("foreground",
243                                                         _("Foreground color name"),
244                                                         _("Foreground color as a string"),
245                                                         NULL,
246                                                         G_PARAM_WRITABLE));
247
248   g_object_class_install_property (object_class,
249                                    PROP_FOREGROUND_GDK,
250                                    g_param_spec_boxed ("foreground_gdk",
251                                                        _("Foreground color"),
252                                                        _("Foreground color as a (possibly unallocated) GdkColor"),
253                                                        GDK_TYPE_COLOR,
254                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));
255
256   
257   g_object_class_install_property (object_class,
258                                    PROP_FOREGROUND_STIPPLE,
259                                    g_param_spec_object ("foreground_stipple",
260                                                         _("Foreground stipple mask"),
261                                                         _("Bitmap to use as a mask when drawing the text foreground"),
262                                                         GDK_TYPE_PIXMAP,
263                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));  
264   
265   g_object_class_install_property (object_class,
266                                    PROP_DIRECTION,
267                                    g_param_spec_enum ("direction",
268                                                       _("Text direction"),
269                                                       _("Text direction, e.g. right-to-left or left-to-right"),
270                                                       GTK_TYPE_TEXT_DIRECTION,
271                                                       GTK_TEXT_DIR_LTR,
272                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
273
274   g_object_class_install_property (object_class,
275                                    PROP_EDITABLE,
276                                    g_param_spec_boolean ("editable",
277                                                          _("Editable"),
278                                                          _("Whether the text can be modified by the user"),
279                                                          TRUE,
280                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
281
282   g_object_class_install_property (object_class,
283                                    PROP_FONT,
284                                    g_param_spec_string ("font",
285                                                         _("Font"),
286                                                         _("Font description as a string, e.g. \"Sans Italic 12\""),
287                                                         NULL,
288                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));
289
290   g_object_class_install_property (object_class,
291                                    PROP_FONT_DESC,
292                                    g_param_spec_boxed ("font_desc",
293                                                        _("Font"),
294                                                        _("Font description as a PangoFontDescription struct"),
295                                                        PANGO_TYPE_FONT_DESCRIPTION,
296                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));
297
298   
299   g_object_class_install_property (object_class,
300                                    PROP_FAMILY,
301                                    g_param_spec_string ("family",
302                                                         _("Font family"),
303                                                         _("Name of the font family, e.g. Sans, Helvetica, Times, Monospace"),
304                                                         NULL,
305                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));
306
307   g_object_class_install_property (object_class,
308                                    PROP_STYLE,
309                                    g_param_spec_enum ("style",
310                                                       _("Font style"),
311                                                       _("Font style as a PangoStyle, e.g. PANGO_STYLE_ITALIC."),
312                                                       PANGO_TYPE_STYLE,
313                                                       PANGO_STYLE_NORMAL,
314                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
315
316   g_object_class_install_property (object_class,
317                                    PROP_VARIANT,
318                                    g_param_spec_enum ("variant",
319                                                      _("Font variant"),
320                                                      _("Font variant as a PangoVariant, e.g. PANGO_VARIANT_SMALL_CAPS."),
321                                                       PANGO_TYPE_VARIANT,
322                                                       PANGO_VARIANT_NORMAL,
323                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
324   
325   g_object_class_install_property (object_class,
326                                    PROP_WEIGHT,
327                                    g_param_spec_int ("weight",
328                                                      _("Font weight"),
329                                                      _("Font weight as an integer, see predefined values in PangoWeight; for example, PANGO_WEIGHT_BOLD."),
330                                                      0,
331                                                      G_MAXINT,
332                                                      PANGO_WEIGHT_NORMAL,
333                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
334   
335
336   g_object_class_install_property (object_class,
337                                    PROP_STRETCH,
338                                    g_param_spec_enum ("stretch",
339                                                       _("Font stretch"),
340                                                       _("Font stretch as a PangoStretch, e.g. PANGO_STRETCH_CONDENSED."),
341                                                       PANGO_TYPE_STRETCH,
342                                                       PANGO_STRETCH_NORMAL,
343                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
344   
345   g_object_class_install_property (object_class,
346                                    PROP_SIZE,
347                                    g_param_spec_int ("size",
348                                                      _("Font size"),
349                                                      _("Font size in Pango units."),
350                                                      0,
351                                                      G_MAXINT,
352                                                      0,
353                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
354
355   g_object_class_install_property (object_class,
356                                    PROP_SCALE,
357                                    g_param_spec_double ("scale",
358                                                         _("Font scale"),
359                                                         _("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."),
360                                                         0.0,
361                                                         G_MAXDOUBLE,
362                                                         1.0,
363                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));
364   
365   g_object_class_install_property (object_class,
366                                    PROP_SIZE_POINTS,
367                                    g_param_spec_double ("size_points",
368                                                         _("Font points"),
369                                                         _("Font size in points"),
370                                                         0.0,
371                                                         G_MAXDOUBLE,
372                                                         0.0,
373                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));  
374
375   g_object_class_install_property (object_class,
376                                    PROP_JUSTIFICATION,
377                                    g_param_spec_enum ("justification",
378                                                       _("Justification"),
379                                                       _("Left, right, or center justification"),
380                                                       GTK_TYPE_JUSTIFICATION,
381                                                       GTK_JUSTIFY_LEFT,
382                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
383   
384   g_object_class_install_property (object_class,
385                                    PROP_LANGUAGE,
386                                    g_param_spec_string ("language",
387                                                         _("Language"),
388                                                         _("The language this text is in, as an ISO code. Pango can use this as a hint when rendering the text. If you don't understand this parameter, you probably don't need it."),
389                                                         NULL,
390                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));  
391
392   g_object_class_install_property (object_class,
393                                    PROP_LEFT_MARGIN,
394                                    g_param_spec_int ("left_margin",
395                                                      _("Left margin"),
396                                                      _("Width of the left margin in pixels"),
397                                                      0,
398                                                      G_MAXINT,
399                                                      0,
400                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
401
402   g_object_class_install_property (object_class,
403                                    PROP_RIGHT_MARGIN,
404                                    g_param_spec_int ("right_margin",
405                                                      _("Right margin"),
406                                                      _("Width of the right margin in pixels"),
407                                                      0,
408                                                      G_MAXINT,
409                                                      0,
410                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
411
412   
413   g_object_class_install_property (object_class,
414                                    PROP_INDENT,
415                                    g_param_spec_int ("indent",
416                                                      _("Indent"),
417                                                      _("Amount to indent the paragraph, in pixels"),
418                                                      G_MININT,
419                                                      G_MAXINT,
420                                                      0,
421                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
422
423   
424   g_object_class_install_property (object_class,
425                                    PROP_RISE,
426                                    g_param_spec_int ("rise",
427                                                      _("Rise"),
428                                                      _("Offset of text above the baseline (below the baseline if rise is negative) in pixels"),
429                                                      G_MININT,
430                                                      G_MAXINT,
431                                                      0,
432                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
433
434   g_object_class_install_property (object_class,
435                                    PROP_PIXELS_ABOVE_LINES,
436                                    g_param_spec_int ("pixels_above_lines",
437                                                      _("Pixels above lines"),
438                                                      _("Pixels of blank space above paragraphs"),
439                                                      0,
440                                                      G_MAXINT,
441                                                      0,
442                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
443   
444   g_object_class_install_property (object_class,
445                                    PROP_PIXELS_BELOW_LINES,
446                                    g_param_spec_int ("pixels_below_lines",
447                                                      _("Pixels below lines"),
448                                                      _("Pixels of blank space below paragraphs"),
449                                                      0,
450                                                      G_MAXINT,
451                                                      0,
452                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
453
454   g_object_class_install_property (object_class,
455                                    PROP_PIXELS_INSIDE_WRAP,
456                                    g_param_spec_int ("pixels_inside_wrap",
457                                                      _("Pixels inside wrap"),
458                                                      _("Pixels of blank space between wrapped lines in a paragraph"),
459                                                      0,
460                                                      G_MAXINT,
461                                                      0,
462                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
463
464   g_object_class_install_property (object_class,
465                                    PROP_STRIKETHROUGH,
466                                    g_param_spec_boolean ("strikethrough",
467                                                          _("Strikethrough"),
468                                                          _("Whether to strike through the text"),
469                                                          FALSE,
470                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
471   
472   g_object_class_install_property (object_class,
473                                    PROP_UNDERLINE,
474                                    g_param_spec_enum ("underline",
475                                                       _("Underline"),
476                                                       _("Style of underline for this text"),
477                                                       PANGO_TYPE_UNDERLINE,
478                                                       PANGO_UNDERLINE_NONE,
479                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
480   
481   g_object_class_install_property (object_class,
482                                    PROP_WRAP_MODE,
483                                    g_param_spec_enum ("wrap_mode",
484                                                      _("Wrap mode"),
485                                                      _("Whether to wrap lines never, at word boundaries, or at character boundaries"),
486                                                       GTK_TYPE_WRAP_MODE,
487                                                       GTK_WRAP_NONE,
488                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
489   
490
491   g_object_class_install_property (object_class,
492                                    PROP_TABS,
493                                    g_param_spec_boxed ("tabs",
494                                                        _("Tabs"),
495                                                        _("Custom tabs for this text"),
496                                                        PANGO_TYPE_TAB_ARRAY,
497                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));
498   
499   g_object_class_install_property (object_class,
500                                    PROP_INVISIBLE,
501                                    g_param_spec_boolean ("invisible",
502                                                          _("Invisible"),
503                                                          _("Whether this text is hidden. Not implemented in GTK 2.0"),
504                                                          FALSE,
505                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
506
507   /* Style props are set or not */
508
509 #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))
510
511   ADD_SET_PROP ("background_set", PROP_BACKGROUND_SET,
512                 _("Background set"),
513                 _("Whether this tag affects the background color"));
514   
515   ADD_SET_PROP ("background_full_height_set", PROP_BG_FULL_HEIGHT_SET,
516                 _("Background full height set"),
517                 _("Whether this tag affects background height"));
518
519   ADD_SET_PROP ("background_stipple_set", PROP_BACKGROUND_STIPPLE_SET,
520                 _("Background stipple set"),
521                 _("Whether this tag affects the background stipple"));  
522
523   ADD_SET_PROP ("foreground_set", PROP_FOREGROUND_SET,
524                 _("Foreground set"),
525                 _("Whether this tag affects the foreground color"));
526
527   ADD_SET_PROP ("foreground_stipple_set", PROP_FOREGROUND_STIPPLE_SET,
528                 _("Foreground stipple set"),
529                 _("Whether this tag affects the foreground stipple"));
530   
531   ADD_SET_PROP ("editable_set", PROP_EDITABLE_SET,
532                 _("Editability set"),
533                 _("Whether this tag affects text editability"));
534
535   ADD_SET_PROP ("family_set", PROP_FAMILY_SET,
536                 _("Font family set"),
537                 _("Whether this tag affects the font family"));  
538
539   ADD_SET_PROP ("style_set", PROP_STYLE_SET,
540                 _("Font style set"),
541                 _("Whether this tag affects the font style"));
542
543   ADD_SET_PROP ("variant_set", PROP_VARIANT_SET,
544                 _("Font variant set"),
545                 _("Whether this tag affects the font variant"));
546
547   ADD_SET_PROP ("weight_set", PROP_WEIGHT_SET,
548                 _("Font weight set"),
549                 _("Whether this tag affects the font weight"));
550
551   ADD_SET_PROP ("stretch_set", PROP_STRETCH_SET,
552                 _("Font stretch set"),
553                 _("Whether this tag affects the font stretch"));
554
555   ADD_SET_PROP ("size_set", PROP_SIZE_SET,
556                 _("Font size set"),
557                 _("Whether this tag affects the font size"));
558
559   ADD_SET_PROP ("scale_set", PROP_SCALE_SET,
560                 _("Font scale set"),
561                 _("Whether this tag scales the font size by a factor"));
562   
563   ADD_SET_PROP ("justification_set", PROP_JUSTIFICATION_SET,
564                 _("Justification set"),
565                 _("Whether this tag affects paragraph justification"));
566   
567   ADD_SET_PROP ("language_set", PROP_LANGUAGE_SET,
568                 _("Language set"),
569                 _("Whether this tag affects the language the text is rendered as"));
570
571   ADD_SET_PROP ("left_margin_set", PROP_LEFT_MARGIN_SET,
572                 _("Left margin set"),
573                 _("Whether this tag affects the left margin"));
574
575   ADD_SET_PROP ("indent_set", PROP_INDENT_SET,
576                 _("Indent set"),
577                 _("Whether this tag affects indentation"));
578
579   ADD_SET_PROP ("rise_set", PROP_RISE_SET,
580                 _("Rise set"),
581                 _("Whether this tag affects the rise"));
582
583   ADD_SET_PROP ("pixels_above_lines_set", PROP_PIXELS_ABOVE_LINES_SET,
584                 _("Pixels above lines set"),
585                 _("Whether this tag affects the number of pixels above lines"));
586
587   ADD_SET_PROP ("pixels_below_lines_set", PROP_PIXELS_BELOW_LINES_SET,
588                 _("Pixels below lines set"),
589                 _("Whether this tag affects the number of pixels above lines"));
590
591   ADD_SET_PROP ("pixels_inside_wrap_set", PROP_PIXELS_INSIDE_WRAP_SET,
592                 _("Pixels inside wrap set"),
593                 _("Whether this tag affects the number of pixels between wrapped lines"));
594
595   ADD_SET_PROP ("strikethrough_set", PROP_STRIKETHROUGH_SET,
596                 _("Strikethrough set"),
597                 _("Whether this tag affects strikethrough"));
598   
599   ADD_SET_PROP ("right_margin_set", PROP_RIGHT_MARGIN_SET,
600                 _("Right margin set"),
601                 _("Whether this tag affects the right margin"));
602
603   ADD_SET_PROP ("underline_set", PROP_UNDERLINE_SET,
604                 _("Underline set"),
605                 _("Whether this tag affects underlining"));
606
607   ADD_SET_PROP ("wrap_mode_set", PROP_WRAP_MODE_SET,
608                 _("Wrap mode set"),
609                 _("Whether this tag affects line wrap mode"));
610
611   ADD_SET_PROP ("tabs_set", PROP_TABS_SET,
612                 _("Tabs set"),
613                 _("Whether this tag affects tabs"));
614
615   ADD_SET_PROP ("invisible_set", PROP_INVISIBLE_SET,
616                 _("Invisible set"),
617                 _("Whether this tag affects text visibility"));
618
619   signals[EVENT] =
620     g_signal_new ("event",
621                   G_OBJECT_CLASS_TYPE (object_class),
622                   G_SIGNAL_RUN_LAST,
623                   GTK_SIGNAL_OFFSET (GtkTextTagClass, event),
624                   _gtk_boolean_handled_accumulator, NULL,
625                   _gtk_marshal_BOOLEAN__OBJECT_BOXED_BOXED,
626                   G_TYPE_BOOLEAN,
627                   3,
628                   G_TYPE_OBJECT,
629                   GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE,
630                   GTK_TYPE_TEXT_ITER);
631 }
632
633 static void
634 gtk_text_tag_init (GtkTextTag *text_tag)
635 {
636   /* 0 is basically a fine way to initialize everything in the
637      entire struct */
638   
639   text_tag->values = gtk_text_attributes_new ();
640 }
641
642 /**
643  * gtk_text_tag_new:
644  * @name: tag name, or %NULL
645  * 
646  * Creates a #GtkTextTag. Configure the tag using object arguments,
647  * i.e. using g_object_set().
648  * 
649  * Return value: a new #GtkTextTag
650  **/
651 GtkTextTag*
652 gtk_text_tag_new (const gchar *name)
653 {
654   GtkTextTag *tag;
655
656   tag = GTK_TEXT_TAG (g_object_new (gtk_text_tag_get_type (),
657                                     "name", name,
658                                     NULL));
659
660   return tag;
661 }
662
663 static void
664 gtk_text_tag_finalize (GObject *object)
665 {
666   GtkTextTag *text_tag;
667
668   text_tag = GTK_TEXT_TAG (object);
669
670   g_assert (!text_tag->values->realized);
671
672   if (text_tag->table)
673     gtk_text_tag_table_remove (text_tag->table, text_tag);
674
675   g_assert (text_tag->table == NULL);
676
677   gtk_text_attributes_unref (text_tag->values);
678   text_tag->values = NULL;
679   
680   g_free (text_tag->name);
681   text_tag->name = NULL;
682
683   (* G_OBJECT_CLASS (parent_class)->finalize) (object);
684 }
685
686 static void
687 set_bg_color (GtkTextTag *tag, GdkColor *color)
688 {
689   if (color)
690     {
691       if (!tag->bg_color_set)
692         {
693           tag->bg_color_set = TRUE;
694           g_object_notify (G_OBJECT (tag), "background_set");
695         }
696       
697       tag->values->appearance.bg_color = *color;
698     }
699   else
700     {
701       if (tag->bg_color_set)
702         {
703           tag->bg_color_set = FALSE;
704           g_object_notify (G_OBJECT (tag), "background_set");
705         }
706     }
707 }
708
709 static void
710 set_fg_color (GtkTextTag *tag, GdkColor *color)
711 {
712   if (color)
713     {
714       if (!tag->fg_color_set)
715         {
716           tag->fg_color_set = TRUE;
717           g_object_notify (G_OBJECT (tag), "foreground_set");
718         }
719       tag->values->appearance.fg_color = *color;
720     }
721   else
722     {
723       if (tag->fg_color_set)
724         {
725           tag->fg_color_set = FALSE;
726           g_object_notify (G_OBJECT (tag), "foreground_set");
727         }
728     }
729 }
730
731 static PangoFontMask
732 get_property_font_set_mask (guint prop_id)
733 {
734   switch (prop_id)
735     {
736     case PROP_FAMILY_SET:
737       return PANGO_FONT_MASK_FAMILY;
738     case PROP_STYLE_SET:
739       return PANGO_FONT_MASK_STYLE;
740     case PROP_VARIANT_SET:
741       return PANGO_FONT_MASK_VARIANT;
742     case PROP_WEIGHT_SET:
743       return PANGO_FONT_MASK_WEIGHT;
744     case PROP_STRETCH_SET:
745       return PANGO_FONT_MASK_STRETCH;
746     case PROP_SIZE_SET:
747       return PANGO_FONT_MASK_SIZE;
748     }
749
750   return 0;
751 }
752
753 static PangoFontMask
754 set_font_desc_fields (PangoFontDescription *desc,
755                       PangoFontMask         to_set)
756 {
757   PangoFontMask changed_mask = 0;
758   
759   if (to_set & PANGO_FONT_MASK_FAMILY)
760     {
761       const char *family = pango_font_description_get_family (desc);
762       if (!family)
763         {
764           family = "sans";
765           changed_mask |= PANGO_FONT_MASK_FAMILY;
766         }
767
768       pango_font_description_set_family (desc, family);
769     }
770   if (to_set & PANGO_FONT_MASK_STYLE)
771     pango_font_description_set_style (desc, pango_font_description_get_style (desc));
772   if (to_set & PANGO_FONT_MASK_VARIANT)
773     pango_font_description_set_variant (desc, pango_font_description_get_variant (desc));
774   if (to_set & PANGO_FONT_MASK_WEIGHT)
775     pango_font_description_set_weight (desc, pango_font_description_get_weight (desc));
776   if (to_set & PANGO_FONT_MASK_STRETCH)
777     pango_font_description_set_stretch (desc, pango_font_description_get_stretch (desc));
778   if (to_set & PANGO_FONT_MASK_SIZE)
779     {
780       gint size = pango_font_description_get_size (desc);
781       if (size <= 0)
782         {
783           size = 10 * PANGO_SCALE;
784           changed_mask |= PANGO_FONT_MASK_SIZE;
785         }
786       
787       pango_font_description_set_size (desc, size);
788     }
789
790   return changed_mask;
791 }
792
793 static void
794 notify_set_changed (GObject       *object,
795                     PangoFontMask  changed_mask)
796 {
797   if (changed_mask & PANGO_FONT_MASK_FAMILY)
798     g_object_notify (object, "family_set");
799   if (changed_mask & PANGO_FONT_MASK_STYLE)
800     g_object_notify (object, "style_set");
801   if (changed_mask & PANGO_FONT_MASK_VARIANT)
802     g_object_notify (object, "variant_set");
803   if (changed_mask & PANGO_FONT_MASK_WEIGHT)
804     g_object_notify (object, "weight_set");
805   if (changed_mask & PANGO_FONT_MASK_STRETCH)
806     g_object_notify (object, "stretch_set");
807   if (changed_mask & PANGO_FONT_MASK_SIZE)
808     g_object_notify (object, "size_set");
809 }
810
811 static void
812 notify_fields_changed (GObject       *object,
813                        PangoFontMask  changed_mask)
814 {
815   if (changed_mask & PANGO_FONT_MASK_FAMILY)
816     g_object_notify (object, "family");
817   if (changed_mask & PANGO_FONT_MASK_STYLE)
818     g_object_notify (object, "style");
819   if (changed_mask & PANGO_FONT_MASK_VARIANT)
820     g_object_notify (object, "variant");
821   if (changed_mask & PANGO_FONT_MASK_WEIGHT)
822     g_object_notify (object, "weight");
823   if (changed_mask & PANGO_FONT_MASK_STRETCH)
824     g_object_notify (object, "stretch");
825   if (changed_mask & PANGO_FONT_MASK_SIZE)
826     g_object_notify (object, "size");
827 }
828
829 static void
830 set_font_description (GtkTextTag           *text_tag,
831                       PangoFontDescription *font_desc)
832 {
833   GObject *object = G_OBJECT (text_tag);
834   PangoFontDescription *new_font_desc;
835   PangoFontMask old_mask, new_mask, changed_mask, set_changed_mask;
836   
837   if (font_desc)
838     new_font_desc = pango_font_description_copy (font_desc);
839   else
840     new_font_desc = pango_font_description_new ();
841
842   if (text_tag->values->font)
843     old_mask = pango_font_description_get_set_fields (text_tag->values->font);
844   else
845     old_mask = 0;
846   
847   new_mask = pango_font_description_get_set_fields (new_font_desc);
848
849   changed_mask = old_mask | new_mask;
850   set_changed_mask = old_mask ^ new_mask;
851
852   if (text_tag->values->font)
853     pango_font_description_free (text_tag->values->font);
854   text_tag->values->font = new_font_desc;
855   
856   g_object_freeze_notify (object);
857
858   g_object_notify (object, "font_desc");
859   g_object_notify (object, "font");
860   
861   if (changed_mask & PANGO_FONT_MASK_FAMILY)
862     g_object_notify (object, "family");
863   if (changed_mask & PANGO_FONT_MASK_STYLE)
864     g_object_notify (object, "style");
865   if (changed_mask & PANGO_FONT_MASK_VARIANT)
866     g_object_notify (object, "variant");
867   if (changed_mask & PANGO_FONT_MASK_WEIGHT)
868     g_object_notify (object, "weight");
869   if (changed_mask & PANGO_FONT_MASK_STRETCH)
870     g_object_notify (object, "stretch");
871   if (changed_mask & PANGO_FONT_MASK_SIZE)
872     {
873       g_object_notify (object, "size");
874       g_object_notify (object, "size_points");
875     }
876
877   notify_set_changed (object, set_changed_mask);
878   
879   g_object_thaw_notify (object);
880 }
881
882 static void
883 gtk_text_tag_ensure_font (GtkTextTag *text_tag)
884 {
885   if (!text_tag->values->font)
886     text_tag->values->font = pango_font_description_new ();
887 }
888
889 static void
890 gtk_text_tag_set_property (GObject      *object,
891                            guint         prop_id,
892                            const GValue *value,
893                            GParamSpec   *pspec)
894 {
895   GtkTextTag *text_tag;
896   gboolean size_changed = FALSE;
897
898   text_tag = GTK_TEXT_TAG (object);
899
900   g_return_if_fail (!text_tag->values->realized);
901
902   switch (prop_id)
903     {
904     case PROP_NAME:
905       g_return_if_fail (text_tag->name == NULL);
906       text_tag->name = g_strdup (g_value_get_string (value));
907       break;
908
909     case PROP_BACKGROUND:
910       {
911         GdkColor color;
912
913         if (gdk_color_parse (g_value_get_string (value), &color))
914           set_bg_color (text_tag, &color);
915         else
916           g_warning ("Don't know color `%s'", g_value_get_string (value));
917
918         g_object_notify (object, "background_gdk");
919       }
920       break;
921
922     case PROP_FOREGROUND:
923       {
924         GdkColor color;
925
926         if (gdk_color_parse (g_value_get_string (value), &color))
927           set_fg_color (text_tag, &color);
928         else
929           g_warning ("Don't know color `%s'", g_value_get_string (value));
930
931         g_object_notify (object, "foreground_gdk");
932       }
933       break;
934
935     case PROP_BACKGROUND_GDK:
936       {
937         GdkColor *color = g_value_get_boxed (value);
938
939         set_bg_color (text_tag, color);
940       }
941       break;
942
943     case PROP_FOREGROUND_GDK:
944       {
945         GdkColor *color = g_value_get_boxed (value);
946
947         set_fg_color (text_tag, color);
948       }
949       break;
950
951     case PROP_BACKGROUND_STIPPLE:
952       {
953         GdkBitmap *bitmap = g_value_get_object (value);
954
955         text_tag->bg_stipple_set = TRUE;
956         g_object_notify (object, "background_stipple_set");
957         
958         if (text_tag->values->appearance.bg_stipple != bitmap)
959           {
960             if (bitmap != NULL)
961               gdk_bitmap_ref (bitmap);
962
963             if (text_tag->values->appearance.bg_stipple)
964               gdk_bitmap_unref (text_tag->values->appearance.bg_stipple);
965
966             text_tag->values->appearance.bg_stipple = bitmap;
967           }
968       }
969       break;
970
971     case PROP_FOREGROUND_STIPPLE:
972       {
973         GdkBitmap *bitmap = g_value_get_object (value);
974
975         text_tag->fg_stipple_set = TRUE;
976         g_object_notify (object, "foreground_stipple_set");
977
978         if (text_tag->values->appearance.fg_stipple != bitmap)
979           {
980             if (bitmap != NULL)
981               gdk_bitmap_ref (bitmap);
982
983             if (text_tag->values->appearance.fg_stipple)
984               gdk_bitmap_unref (text_tag->values->appearance.fg_stipple);
985
986             text_tag->values->appearance.fg_stipple = bitmap;
987           }
988       }
989       break;
990
991     case PROP_FONT:
992       {
993         PangoFontDescription *font_desc = NULL;
994         const gchar *name;
995
996         name = g_value_get_string (value);
997
998         if (name)
999           font_desc = pango_font_description_from_string (name);
1000
1001         set_font_description (text_tag, font_desc);
1002         if (font_desc)
1003           pango_font_description_free (font_desc);
1004         
1005         size_changed = TRUE;
1006       }
1007       break;
1008
1009     case PROP_FONT_DESC:
1010       {
1011         PangoFontDescription *font_desc;
1012
1013         font_desc = g_value_get_boxed (value);
1014
1015         set_font_description (text_tag, font_desc);
1016
1017         size_changed = TRUE;
1018       }
1019       break;
1020
1021     case PROP_FAMILY:
1022     case PROP_STYLE:
1023     case PROP_VARIANT:
1024     case PROP_WEIGHT:
1025     case PROP_STRETCH:
1026     case PROP_SIZE:
1027     case PROP_SIZE_POINTS:
1028       {
1029         PangoFontMask old_set_mask;
1030
1031         gtk_text_tag_ensure_font (text_tag);
1032         old_set_mask = pango_font_description_get_set_fields (text_tag->values->font);
1033  
1034         switch (prop_id)
1035           {
1036           case PROP_FAMILY:
1037             pango_font_description_set_family (text_tag->values->font,
1038                                                g_value_get_string (value));
1039             break;
1040           case PROP_STYLE:
1041             pango_font_description_set_style (text_tag->values->font,
1042                                               g_value_get_enum (value));
1043             break;
1044           case PROP_VARIANT:
1045             pango_font_description_set_variant (text_tag->values->font,
1046                                                 g_value_get_enum (value));
1047             break;
1048           case PROP_WEIGHT:
1049             pango_font_description_set_weight (text_tag->values->font,
1050                                                g_value_get_int (value));
1051             break;
1052           case PROP_STRETCH:
1053             pango_font_description_set_stretch (text_tag->values->font,
1054                                                 g_value_get_enum (value));
1055             break;
1056           case PROP_SIZE:
1057             pango_font_description_set_size (text_tag->values->font,
1058                                              g_value_get_int (value));
1059             g_object_notify (object, "size_points");
1060             break;
1061           case PROP_SIZE_POINTS:
1062             pango_font_description_set_size (text_tag->values->font,
1063                                              g_value_get_double (value) * PANGO_SCALE);
1064             g_object_notify (object, "size");
1065             break;
1066           }
1067
1068         size_changed = TRUE;
1069         notify_set_changed (object, old_set_mask & pango_font_description_get_set_fields (text_tag->values->font));
1070         g_object_notify (object, "font_desc");
1071         g_object_notify (object, "font");
1072
1073         break;
1074       }
1075       
1076     case PROP_SCALE:
1077       text_tag->values->font_scale = g_value_get_double (value);
1078       text_tag->scale_set = TRUE;
1079       g_object_notify (object, "scale_set");
1080       size_changed = TRUE;
1081       break;
1082       
1083     case PROP_PIXELS_ABOVE_LINES:
1084       text_tag->pixels_above_lines_set = TRUE;
1085       text_tag->values->pixels_above_lines = g_value_get_int (value);
1086       g_object_notify (object, "pixels_above_lines_set");
1087       size_changed = TRUE;
1088       break;
1089
1090     case PROP_PIXELS_BELOW_LINES:
1091       text_tag->pixels_below_lines_set = TRUE;
1092       text_tag->values->pixels_below_lines = g_value_get_int (value);
1093       g_object_notify (object, "pixels_below_lines_set");
1094       size_changed = TRUE;
1095       break;
1096
1097     case PROP_PIXELS_INSIDE_WRAP:
1098       text_tag->pixels_inside_wrap_set = TRUE;
1099       text_tag->values->pixels_inside_wrap = g_value_get_int (value);
1100       g_object_notify (object, "pixels_inside_wrap_set");
1101       size_changed = TRUE;
1102       break;
1103
1104     case PROP_EDITABLE:
1105       text_tag->editable_set = TRUE;
1106       text_tag->values->editable = g_value_get_boolean (value);
1107       g_object_notify (object, "editable_set");
1108       break;
1109
1110     case PROP_WRAP_MODE:
1111       text_tag->wrap_mode_set = TRUE;
1112       text_tag->values->wrap_mode = g_value_get_enum (value);
1113       g_object_notify (object, "wrap_mode_set");
1114       size_changed = TRUE;
1115       break;
1116
1117     case PROP_JUSTIFICATION:
1118       text_tag->justification_set = TRUE;
1119       text_tag->values->justification = g_value_get_enum (value);
1120       g_object_notify (object, "justification_set");
1121       size_changed = TRUE;
1122       break;
1123
1124     case PROP_DIRECTION:
1125       text_tag->values->direction = g_value_get_enum (value);
1126       break;
1127
1128     case PROP_LEFT_MARGIN:
1129       text_tag->left_margin_set = TRUE;
1130       text_tag->values->left_margin = g_value_get_int (value);
1131       g_object_notify (object, "left_margin_set");
1132       size_changed = TRUE;
1133       break;
1134
1135     case PROP_INDENT:
1136       text_tag->indent_set = TRUE;
1137       text_tag->values->indent = g_value_get_int (value);
1138       g_object_notify (object, "indent_set");
1139       size_changed = TRUE;
1140       break;
1141
1142     case PROP_STRIKETHROUGH:
1143       text_tag->strikethrough_set = TRUE;
1144       text_tag->values->appearance.strikethrough = g_value_get_boolean (value);
1145       g_object_notify (object, "strikethrough_set");
1146       break;
1147
1148     case PROP_RIGHT_MARGIN:
1149       text_tag->right_margin_set = TRUE;
1150       text_tag->values->right_margin = g_value_get_int (value);
1151       g_object_notify (object, "right_margin_set");
1152       size_changed = TRUE;
1153       break;
1154
1155     case PROP_UNDERLINE:
1156       text_tag->underline_set = TRUE;
1157       text_tag->values->appearance.underline = g_value_get_enum (value);
1158       g_object_notify (object, "underline_set");
1159       break;
1160
1161     case PROP_RISE:
1162       text_tag->rise_set = TRUE;
1163       text_tag->values->appearance.rise = g_value_get_int (value);
1164       g_object_notify (object, "rise_set");
1165       size_changed = TRUE;      
1166       break;
1167
1168     case PROP_BG_FULL_HEIGHT:
1169       text_tag->bg_full_height_set = TRUE;
1170       text_tag->values->bg_full_height = g_value_get_boolean (value);
1171       g_object_notify (object, "bg_full_height_set");
1172       break;
1173
1174     case PROP_LANGUAGE:
1175       text_tag->language_set = TRUE;
1176       text_tag->values->language = pango_language_from_string (g_value_get_string (value));
1177       g_object_notify (object, "language_set");
1178       break;
1179
1180     case PROP_TABS:
1181       text_tag->tabs_set = TRUE;
1182
1183       if (text_tag->values->tabs)
1184         pango_tab_array_free (text_tag->values->tabs);
1185
1186       /* FIXME I'm not sure if this is a memleak or not */
1187       text_tag->values->tabs =
1188         pango_tab_array_copy (g_value_get_boxed (value));
1189
1190       g_object_notify (object, "tabs_set");
1191       
1192       size_changed = TRUE;
1193       break;
1194
1195     case PROP_INVISIBLE:
1196       g_warning ("The \"invisible\" property on GtkTextTag is not supported for GTK 2.0, it will be added in a future release. see http://bugzilla.gnome.org bug #66194 for status.");
1197       text_tag->invisible_set = TRUE;
1198       text_tag->values->invisible = g_value_get_boolean (value);
1199       g_object_notify (object, "invisible_set");
1200       size_changed = TRUE;
1201       break;
1202       
1203       /* Whether the value should be used... */
1204
1205     case PROP_BACKGROUND_SET:
1206       text_tag->bg_color_set = g_value_get_boolean (value);
1207       break;
1208
1209     case PROP_FOREGROUND_SET:
1210       text_tag->fg_color_set = g_value_get_boolean (value);
1211       break;
1212
1213     case PROP_BACKGROUND_STIPPLE_SET:
1214       text_tag->bg_stipple_set = g_value_get_boolean (value);
1215       if (!text_tag->bg_stipple_set &&
1216           text_tag->values->appearance.bg_stipple)
1217         {
1218           g_object_unref (G_OBJECT (text_tag->values->appearance.bg_stipple));
1219           text_tag->values->appearance.bg_stipple = NULL;
1220         }
1221       break;
1222
1223     case PROP_FOREGROUND_STIPPLE_SET:
1224       text_tag->fg_stipple_set = g_value_get_boolean (value);
1225       if (!text_tag->fg_stipple_set &&
1226           text_tag->values->appearance.fg_stipple)
1227         {
1228           g_object_unref (G_OBJECT (text_tag->values->appearance.fg_stipple));
1229           text_tag->values->appearance.fg_stipple = NULL;
1230         }
1231       break;
1232
1233     case PROP_FAMILY_SET:
1234     case PROP_STYLE_SET:
1235     case PROP_VARIANT_SET:
1236     case PROP_WEIGHT_SET:
1237     case PROP_STRETCH_SET:
1238     case PROP_SIZE_SET:
1239       if (!g_value_get_boolean (value))
1240         {
1241           if (text_tag->values->font)
1242             pango_font_description_unset_fields (text_tag->values->font,
1243                                                  get_property_font_set_mask (prop_id));
1244         }
1245       else
1246         {
1247           PangoFontMask changed_mask;
1248           
1249           gtk_text_tag_ensure_font (text_tag);
1250           changed_mask = set_font_desc_fields (text_tag->values->font,
1251                                                get_property_font_set_mask (prop_id));
1252           notify_fields_changed (G_OBJECT (text_tag), changed_mask);
1253         }
1254       break;
1255
1256     case PROP_SCALE_SET:
1257       text_tag->scale_set = g_value_get_boolean (value);
1258       size_changed = TRUE;
1259       break;
1260       
1261     case PROP_PIXELS_ABOVE_LINES_SET:
1262       text_tag->pixels_above_lines_set = g_value_get_boolean (value);
1263       size_changed = TRUE;
1264       break;
1265
1266     case PROP_PIXELS_BELOW_LINES_SET:
1267       text_tag->pixels_below_lines_set = g_value_get_boolean (value);
1268       size_changed = TRUE;
1269       break;
1270
1271     case PROP_PIXELS_INSIDE_WRAP_SET:
1272       text_tag->pixels_inside_wrap_set = g_value_get_boolean (value);
1273       size_changed = TRUE;
1274       break;
1275
1276     case PROP_EDITABLE_SET:
1277       text_tag->editable_set = g_value_get_boolean (value);
1278       break;
1279
1280     case PROP_WRAP_MODE_SET:
1281       text_tag->wrap_mode_set = g_value_get_boolean (value);
1282       size_changed = TRUE;
1283       break;
1284
1285     case PROP_JUSTIFICATION_SET:
1286       text_tag->justification_set = g_value_get_boolean (value);
1287       size_changed = TRUE;
1288       break;
1289       
1290     case PROP_LEFT_MARGIN_SET:
1291       text_tag->left_margin_set = g_value_get_boolean (value);
1292       size_changed = TRUE;
1293       break;
1294
1295     case PROP_INDENT_SET:
1296       text_tag->indent_set = g_value_get_boolean (value);
1297       size_changed = TRUE;
1298       break;
1299
1300     case PROP_STRIKETHROUGH_SET:
1301       text_tag->strikethrough_set = g_value_get_boolean (value);
1302       break;
1303
1304     case PROP_RIGHT_MARGIN_SET:
1305       text_tag->right_margin_set = g_value_get_boolean (value);
1306       size_changed = TRUE;
1307       break;
1308
1309     case PROP_UNDERLINE_SET:
1310       text_tag->underline_set = g_value_get_boolean (value);
1311       break;
1312
1313     case PROP_RISE_SET:
1314       text_tag->rise_set = g_value_get_boolean (value);
1315       size_changed = TRUE;
1316       break;
1317
1318     case PROP_BG_FULL_HEIGHT_SET:
1319       text_tag->bg_full_height_set = g_value_get_boolean (value);
1320       break;
1321
1322     case PROP_LANGUAGE_SET:
1323       text_tag->language_set = g_value_get_boolean (value);
1324       size_changed = TRUE;
1325       break;
1326
1327     case PROP_TABS_SET:
1328       text_tag->tabs_set = g_value_get_boolean (value);
1329       size_changed = TRUE;
1330       break;
1331
1332     case PROP_INVISIBLE_SET:
1333       text_tag->invisible_set = g_value_get_boolean (value);
1334       size_changed = TRUE;
1335       break;
1336       
1337     default:
1338       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1339       break;
1340     }
1341
1342   /* FIXME I would like to do this after all set_property in a single
1343    * g_object_set () have been called. But an idle function won't
1344    * work; we need to emit when the tag is changed, not when we get
1345    * around to the event loop. So blah, we eat some inefficiency.
1346    */
1347
1348   /* This is also somewhat weird since we emit another object's
1349    * signal here, but the two objects are already tightly bound.
1350    */
1351
1352   if (text_tag->table)
1353     g_signal_emit_by_name (G_OBJECT (text_tag->table),
1354                            "tag_changed",
1355                            text_tag, size_changed);
1356 }
1357
1358 static void
1359 get_color_arg (GValue *value, GdkColor *orig)
1360 {
1361   g_value_init (value, GDK_TYPE_COLOR);
1362   g_value_set_boxed (value, orig);
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 GType
1869 gtk_text_attributes_get_type (void)
1870 {
1871   static GType our_type = 0;
1872   
1873   if (our_type == 0)
1874     our_type = g_boxed_type_register_static ("GtkTextAttributes",
1875                                              (GBoxedCopyFunc) gtk_text_attributes_ref,
1876                                              (GBoxedFreeFunc) gtk_text_attributes_unref);
1877
1878   return our_type;
1879 }
1880
1881 /**
1882  * gtk_text_attributes_copy_values:
1883  * @src: a #GtkTextAttributes
1884  * @dest: another #GtkTextAttributes
1885  * 
1886  * Copies the values from @src to @dest so that @dest has the same values
1887  * as @src. Frees existing values in @dest.
1888  **/
1889 void
1890 gtk_text_attributes_copy_values (GtkTextAttributes *src,
1891                                  GtkTextAttributes *dest)
1892 {
1893   guint orig_refcount;
1894
1895   g_return_if_fail (!dest->realized);
1896
1897   if (src == dest)
1898     return;
1899
1900   /* Add refs */
1901
1902   if (src->appearance.bg_stipple)
1903     gdk_bitmap_ref (src->appearance.bg_stipple);
1904
1905   if (src->appearance.fg_stipple)
1906     gdk_bitmap_ref (src->appearance.fg_stipple);
1907
1908   /* Remove refs */
1909
1910   if (dest->appearance.bg_stipple)
1911     gdk_bitmap_unref (dest->appearance.bg_stipple);
1912
1913   if (dest->appearance.fg_stipple)
1914     gdk_bitmap_unref (dest->appearance.fg_stipple);
1915
1916   if (dest->font)
1917     pango_font_description_free (dest->font);
1918   
1919   /* Copy */
1920   orig_refcount = dest->refcount;
1921
1922   *dest = *src;
1923
1924   if (src->tabs)
1925     dest->tabs = pango_tab_array_copy (src->tabs);
1926
1927   dest->language = src->language;
1928
1929   if (dest->font)
1930     dest->font = pango_font_description_copy (src->font);
1931   
1932   dest->refcount = orig_refcount;
1933   dest->realized = FALSE;
1934 }
1935
1936 /**
1937  * gtk_text_attributes_ref:
1938  * @values: a #GtkTextAttributes
1939  * 
1940  * Increments the reference count on @values.
1941  **/
1942 void
1943 gtk_text_attributes_ref (GtkTextAttributes *values)
1944 {
1945   g_return_if_fail (values != NULL);
1946
1947   values->refcount += 1;
1948 }
1949
1950 /**
1951  * gtk_text_attributes_unref:
1952  * @values: a #GtkTextAttributes
1953  * 
1954  * Decrements the reference count on @values, freeing the structure
1955  * if the reference count reaches 0.
1956  **/
1957 void
1958 gtk_text_attributes_unref (GtkTextAttributes *values)
1959 {
1960   g_return_if_fail (values != NULL);
1961   g_return_if_fail (values->refcount > 0);
1962
1963   values->refcount -= 1;
1964
1965   if (values->refcount == 0)
1966     {
1967       g_assert (!values->realized);
1968
1969       if (values->appearance.bg_stipple)
1970         gdk_bitmap_unref (values->appearance.bg_stipple);
1971
1972       if (values->appearance.fg_stipple)
1973         gdk_bitmap_unref (values->appearance.fg_stipple);
1974
1975       if (values->tabs)
1976         pango_tab_array_free (values->tabs);
1977
1978       if (values->font)
1979         pango_font_description_free (values->font);
1980       
1981       g_free (values);
1982     }
1983 }
1984
1985 void
1986 _gtk_text_attributes_realize (GtkTextAttributes *values,
1987                               GdkColormap *cmap,
1988                               GdkVisual *visual)
1989 {
1990   g_return_if_fail (values != NULL);
1991   g_return_if_fail (values->refcount > 0);
1992   g_return_if_fail (!values->realized);
1993
1994   /* It is wrong to use this colormap, FIXME */
1995   gdk_colormap_alloc_color (cmap,
1996                             &values->appearance.fg_color,
1997                             FALSE, TRUE);
1998
1999   gdk_colormap_alloc_color (cmap,
2000                             &values->appearance.bg_color,
2001                             FALSE, TRUE);
2002
2003   values->realized = TRUE;
2004 }
2005
2006 void
2007 _gtk_text_attributes_unrealize (GtkTextAttributes *values,
2008                                 GdkColormap *cmap,
2009                                 GdkVisual *visual)
2010 {
2011   g_return_if_fail (values != NULL);
2012   g_return_if_fail (values->refcount > 0);
2013   g_return_if_fail (values->realized);
2014
2015   gdk_colormap_free_colors (cmap,
2016                             &values->appearance.fg_color, 1);
2017
2018
2019   gdk_colormap_free_colors (cmap,
2020                             &values->appearance.bg_color, 1);
2021
2022   values->appearance.fg_color.pixel = 0;
2023   values->appearance.bg_color.pixel = 0;
2024
2025   values->realized = FALSE;
2026 }
2027
2028 void
2029 _gtk_text_attributes_fill_from_tags (GtkTextAttributes *dest,
2030                                      GtkTextTag**       tags,
2031                                      guint              n_tags)
2032 {
2033   guint n = 0;
2034
2035   g_return_if_fail (!dest->realized);
2036
2037   while (n < n_tags)
2038     {
2039       GtkTextTag *tag = tags[n];
2040       GtkTextAttributes *vals = tag->values;
2041
2042       g_assert (tag->table != NULL);
2043       if (n > 0)
2044         g_assert (tags[n]->priority > tags[n-1]->priority);
2045
2046       if (tag->bg_color_set)
2047         {
2048           dest->appearance.bg_color = vals->appearance.bg_color;
2049
2050           dest->appearance.draw_bg = TRUE;
2051         }
2052       if (tag->fg_color_set)
2053         dest->appearance.fg_color = vals->appearance.fg_color;
2054       
2055       if (tag->bg_stipple_set)
2056         {
2057           gdk_bitmap_ref (vals->appearance.bg_stipple);
2058           if (dest->appearance.bg_stipple)
2059             gdk_bitmap_unref (dest->appearance.bg_stipple);
2060           dest->appearance.bg_stipple = vals->appearance.bg_stipple;
2061
2062           dest->appearance.draw_bg = TRUE;
2063         }
2064
2065       if (tag->fg_stipple_set)
2066         {
2067           gdk_bitmap_ref (vals->appearance.fg_stipple);
2068           if (dest->appearance.fg_stipple)
2069             gdk_bitmap_unref (dest->appearance.fg_stipple);
2070           dest->appearance.fg_stipple = vals->appearance.fg_stipple;
2071         }
2072
2073       if (vals->font)
2074         {
2075           if (dest->font)
2076             pango_font_description_merge (dest->font, vals->font, TRUE);
2077           else
2078             dest->font = pango_font_description_copy (vals->font);
2079         }
2080
2081       /* multiply all the scales together to get a composite */
2082       if (tag->scale_set)
2083         dest->font_scale *= vals->font_scale;
2084       
2085       if (tag->justification_set)
2086         dest->justification = vals->justification;
2087
2088       if (vals->direction != GTK_TEXT_DIR_NONE)
2089         dest->direction = vals->direction;
2090
2091       if (tag->left_margin_set)
2092         dest->left_margin = vals->left_margin;
2093
2094       if (tag->indent_set)
2095         dest->indent = vals->indent;
2096
2097       if (tag->rise_set)
2098         dest->appearance.rise = vals->appearance.rise;
2099
2100       if (tag->right_margin_set)
2101         dest->right_margin = vals->right_margin;
2102
2103       if (tag->pixels_above_lines_set)
2104         dest->pixels_above_lines = vals->pixels_above_lines;
2105
2106       if (tag->pixels_below_lines_set)
2107         dest->pixels_below_lines = vals->pixels_below_lines;
2108
2109       if (tag->pixels_inside_wrap_set)
2110         dest->pixels_inside_wrap = vals->pixels_inside_wrap;
2111
2112       if (tag->tabs_set)
2113         {
2114           if (dest->tabs)
2115             pango_tab_array_free (dest->tabs);
2116           dest->tabs = pango_tab_array_copy (vals->tabs);
2117         }
2118
2119       if (tag->wrap_mode_set)
2120         dest->wrap_mode = vals->wrap_mode;
2121
2122       if (tag->underline_set)
2123         dest->appearance.underline = vals->appearance.underline;
2124
2125       if (tag->strikethrough_set)
2126         dest->appearance.strikethrough = vals->appearance.strikethrough;
2127
2128       if (tag->invisible_set)
2129         dest->invisible = vals->invisible;
2130
2131       if (tag->editable_set)
2132         dest->editable = vals->editable;
2133
2134       if (tag->bg_full_height_set)
2135         dest->bg_full_height = vals->bg_full_height;
2136
2137       if (tag->language_set)
2138         dest->language = vals->language;
2139
2140       ++n;
2141     }
2142 }
2143
2144 gboolean
2145 _gtk_text_tag_affects_size (GtkTextTag *tag)
2146 {
2147   g_return_val_if_fail (GTK_IS_TEXT_TAG (tag), FALSE);
2148
2149   return
2150     (tag->values->font && pango_font_description_get_set_fields (tag->values->font) != 0) ||
2151     tag->scale_set ||
2152     tag->justification_set ||
2153     tag->left_margin_set ||
2154     tag->indent_set ||
2155     tag->rise_set ||
2156     tag->right_margin_set ||
2157     tag->pixels_above_lines_set ||
2158     tag->pixels_below_lines_set ||
2159     tag->pixels_inside_wrap_set ||
2160     tag->tabs_set ||
2161     tag->underline_set ||
2162     tag->wrap_mode_set ||
2163     tag->invisible_set;
2164 }
2165
2166 gboolean
2167 _gtk_text_tag_affects_nonsize_appearance (GtkTextTag *tag)
2168 {
2169   g_return_val_if_fail (GTK_IS_TEXT_TAG (tag), FALSE);
2170
2171   return
2172     tag->bg_color_set ||
2173     tag->bg_stipple_set ||
2174     tag->fg_color_set ||
2175     tag->fg_stipple_set ||
2176     tag->strikethrough_set ||
2177     tag->bg_full_height_set;
2178 }