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