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