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