]> Pileus Git - ~andy/gtk/blob - gtk/gtktexttag.c
Rename GtkTextStyleValues to GtkTextAttributes
[~andy/gtk] / gtk / gtktexttag.c
1 /* gtktexttag.c - text tag object
2  * 
3  * Copyright (c) 1992-1994 The Regents of the University of California.
4  * Copyright (c) 1994-1997 Sun Microsystems, Inc.
5  * Copyright (c) 2000      Red Hat, Inc.
6  * Tk -> Gtk port by Havoc Pennington <hp@redhat.com>
7  *
8  * This software is copyrighted by the Regents of the University of
9  * California, Sun Microsystems, Inc., and other parties.  The
10  * following terms apply to all files associated with the software
11  * unless explicitly disclaimed in individual files.
12  * 
13  * The authors hereby grant permission to use, copy, modify,
14  * distribute, and license this software and its documentation for any
15  * purpose, provided that existing copyright notices are retained in
16  * all copies and that this notice is included verbatim in any
17  * distributions. No written agreement, license, or royalty fee is
18  * required for any of the authorized uses.  Modifications to this
19  * software may be copyrighted by their authors and need not follow
20  * the licensing terms described here, provided that the new terms are
21  * clearly indicated on the first page of each file where they apply.
22  * 
23  * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY
24  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
25  * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION,
26  * OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED
27  * OF THE POSSIBILITY OF SUCH DAMAGE.
28  * 
29  * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
30  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
31  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
32  * NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
33  * AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
34  * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
35  *
36  * GOVERNMENT USE: If you are acquiring this software on behalf of the
37  * U.S. government, the Government shall have only "Restricted Rights"
38  * in the software and related documentation as defined in the Federal
39  * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
40  * are acquiring the software on behalf of the Department of Defense,
41  * the software shall be classified as "Commercial Computer Software"
42  * and the Government shall have only "Restricted Rights" as defined
43  * in Clause 252.227-7013 (c) (1) of DFARs.  Notwithstanding the
44  * foregoing, the authors grant the U.S. Government and others acting
45  * in its behalf permission to use and distribute the software in
46  * accordance with the terms specified in this license.
47  * 
48  */
49
50 #include "gtkmain.h"
51 #include "gtktexttag.h"
52 #include "gtktexttypes.h"
53 #include "gtktexttagtable.h"
54 #include "gtksignal.h"
55 #include "gtkmain.h"
56
57 #include <stdlib.h>
58
59 enum {
60   EVENT,
61   LAST_SIGNAL
62 };
63
64 enum {
65   ARG_0,
66   /* Construct args */
67   ARG_NAME,
68
69   /* Style args */
70   ARG_BACKGROUND,
71   ARG_FOREGROUND,
72   ARG_BACKGROUND_GDK,
73   ARG_FOREGROUND_GDK,
74   ARG_BACKGROUND_STIPPLE,
75   ARG_FOREGROUND_STIPPLE,
76   ARG_FONT,
77   ARG_FONT_DESC,
78   ARG_PIXELS_ABOVE_LINES,
79   ARG_PIXELS_BELOW_LINES,
80   ARG_PIXELS_INSIDE_WRAP,
81   ARG_EDITABLE,
82   ARG_WRAP_MODE,
83   ARG_JUSTIFY,
84   ARG_DIRECTION,
85   ARG_LEFT_MARGIN,
86   ARG_LEFT_WRAPPED_LINE_MARGIN,
87   ARG_OVERSTRIKE,
88   ARG_RIGHT_MARGIN,
89   ARG_UNDERLINE,
90   ARG_OFFSET,
91   ARG_BG_FULL_HEIGHT,
92   ARG_LANGUAGE,
93   
94   /* Whether-a-style-arg-is-set args */
95   ARG_BACKGROUND_SET,
96   ARG_FOREGROUND_SET,
97   ARG_BACKGROUND_GDK_SET,
98   ARG_FOREGROUND_GDK_SET,
99   ARG_BACKGROUND_STIPPLE_SET,
100   ARG_FOREGROUND_STIPPLE_SET,
101   ARG_FONT_SET,
102   ARG_PIXELS_ABOVE_LINES_SET,
103   ARG_PIXELS_BELOW_LINES_SET,
104   ARG_PIXELS_INSIDE_WRAP_SET,
105   ARG_EDITABLE_SET,
106   ARG_WRAP_MODE_SET,
107   ARG_JUSTIFY_SET,
108   ARG_LEFT_MARGIN_SET,
109   ARG_LEFT_WRAPPED_LINE_MARGIN_SET,
110   ARG_OVERSTRIKE_SET,
111   ARG_RIGHT_MARGIN_SET,
112   ARG_UNDERLINE_SET,
113   ARG_OFFSET_SET,
114   ARG_BG_FULL_HEIGHT_SET,
115   ARG_LANGUAGE_SET,
116   
117   LAST_ARG
118 };
119
120 static void gtk_text_tag_init       (GtkTextTag      *tkxt_tag);
121 static void gtk_text_tag_class_init (GtkTextTagClass *klass);
122 static void gtk_text_tag_destroy    (GtkObject       *object);
123 static void gtk_text_tag_finalize   (GObject         *object);
124 static void gtk_text_tag_set_arg    (GtkObject       *object,
125                                      GtkArg          *arg,
126                                      guint            arg_id);
127 static void gtk_text_tag_get_arg    (GtkObject       *object,
128                                      GtkArg          *arg,
129                                      guint            arg_id);
130
131 static GtkObjectClass *parent_class = NULL;
132 static guint signals[LAST_SIGNAL] = { 0 };
133
134 GtkType
135 gtk_text_tag_get_type (void)
136 {
137   static GtkType our_type = 0;
138
139   if (our_type == 0)
140     {
141       static const GtkTypeInfo our_info =
142       {
143         "GtkTextTag",
144         sizeof (GtkTextTag),
145         sizeof (GtkTextTagClass),
146         (GtkClassInitFunc) gtk_text_tag_class_init,
147         (GtkObjectInitFunc) gtk_text_tag_init,
148         /* reserved_1 */ NULL,
149         /* reserved_2 */ NULL,
150         (GtkClassInitFunc) NULL
151       };
152
153     our_type = gtk_type_unique (GTK_TYPE_OBJECT, &our_info);
154   }
155
156   return our_type;
157 }
158
159 static void
160 gtk_text_tag_class_init (GtkTextTagClass *klass)
161 {
162   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
163   GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
164
165   parent_class = gtk_type_class (GTK_TYPE_OBJECT);
166
167   /* Construct */
168   gtk_object_add_arg_type ("GtkTextTag::name", GTK_TYPE_STRING,
169                            GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY,
170                            ARG_NAME);
171
172   /* Style args */
173   gtk_object_add_arg_type ("GtkTextTag::background", GTK_TYPE_STRING,
174                            GTK_ARG_WRITABLE, ARG_BACKGROUND);
175   gtk_object_add_arg_type ("GtkTextTag::foreground", GTK_TYPE_STRING,
176                            GTK_ARG_WRITABLE, ARG_FOREGROUND);
177   gtk_object_add_arg_type ("GtkTextTag::background_gdk", GTK_TYPE_GDK_COLOR,
178                            GTK_ARG_READWRITE, ARG_BACKGROUND_GDK);
179   gtk_object_add_arg_type ("GtkTextTag::foreground_gdk", GTK_TYPE_GDK_COLOR,
180                            GTK_ARG_READWRITE, ARG_FOREGROUND_GDK);
181   gtk_object_add_arg_type ("GtkTextTag::background_stipple",
182                            GDK_TYPE_PIXMAP,
183                            GTK_ARG_READWRITE, ARG_BACKGROUND_STIPPLE);
184   gtk_object_add_arg_type ("GtkTextTag::foreground_stipple",
185                            GDK_TYPE_PIXMAP,
186                            GTK_ARG_READWRITE, ARG_FOREGROUND_STIPPLE);
187   gtk_object_add_arg_type ("GtkTextTag::font", GTK_TYPE_STRING,
188                            GTK_ARG_READWRITE, ARG_FONT);
189   gtk_object_add_arg_type ("GtkTextTag::font_desc", GTK_TYPE_BOXED,
190                            GTK_ARG_READWRITE, ARG_FONT_DESC);
191   gtk_object_add_arg_type ("GtkTextTag::pixels_above_lines", GTK_TYPE_INT,
192                            GTK_ARG_READWRITE, ARG_PIXELS_ABOVE_LINES);
193   gtk_object_add_arg_type ("GtkTextTag::pixels_below_lines", GTK_TYPE_INT,
194                            GTK_ARG_READWRITE, ARG_PIXELS_BELOW_LINES);
195   gtk_object_add_arg_type ("GtkTextTag::pixels_inside_wrap", GTK_TYPE_INT,
196                            GTK_ARG_READWRITE, ARG_PIXELS_INSIDE_WRAP);
197   gtk_object_add_arg_type ("GtkTextTag::editable", GTK_TYPE_BOOL,
198                            GTK_ARG_READWRITE, ARG_EDITABLE);
199   gtk_object_add_arg_type ("GtkTextTag::wrap_mode", GTK_TYPE_ENUM,
200                            GTK_ARG_READWRITE, ARG_WRAP_MODE);
201   gtk_object_add_arg_type ("GtkTextTag::justify", GTK_TYPE_ENUM,
202                            GTK_ARG_READWRITE, ARG_JUSTIFY);
203   gtk_object_add_arg_type ("GtkTextTag::direction", GTK_TYPE_ENUM,
204                            GTK_ARG_READWRITE, ARG_DIRECTION);
205   gtk_object_add_arg_type ("GtkTextTag::left_margin", GTK_TYPE_INT,
206                            GTK_ARG_READWRITE, ARG_LEFT_MARGIN);
207   gtk_object_add_arg_type ("GtkTextTag::left_wrapped_line_margin", GTK_TYPE_INT,
208                            GTK_ARG_READWRITE, ARG_LEFT_WRAPPED_LINE_MARGIN);
209   gtk_object_add_arg_type ("GtkTextTag::overstrike", GTK_TYPE_BOOL,
210                            GTK_ARG_READWRITE, ARG_OVERSTRIKE);
211   gtk_object_add_arg_type ("GtkTextTag::right_margin", GTK_TYPE_INT,
212                            GTK_ARG_READWRITE, ARG_RIGHT_MARGIN);
213   gtk_object_add_arg_type ("GtkTextTag::pixels_above_lines", GTK_TYPE_INT,
214                            GTK_ARG_READWRITE, ARG_PIXELS_ABOVE_LINES);
215   gtk_object_add_arg_type ("GtkTextTag::pixels_below_lines", GTK_TYPE_INT,
216                            GTK_ARG_READWRITE, ARG_PIXELS_BELOW_LINES);
217   gtk_object_add_arg_type ("GtkTextTag::pixels_inside_wrap", GTK_TYPE_INT,
218                            GTK_ARG_READWRITE, ARG_PIXELS_INSIDE_WRAP);
219   gtk_object_add_arg_type ("GtkTextTag::underline", GTK_TYPE_ENUM,
220                            GTK_ARG_READWRITE, ARG_UNDERLINE);
221   gtk_object_add_arg_type ("GtkTextTag::wrap_mode", GTK_TYPE_ENUM,
222                            GTK_ARG_READWRITE, ARG_WRAP_MODE);
223   gtk_object_add_arg_type ("GtkTextTag::offset", GTK_TYPE_INT,
224                            GTK_ARG_READWRITE, ARG_OFFSET);
225   gtk_object_add_arg_type ("GtkTextTag::background_full_height", GTK_TYPE_BOOL,
226                            GTK_ARG_READWRITE, ARG_BG_FULL_HEIGHT);
227   gtk_object_add_arg_type ("GtkTextTag::language", GTK_TYPE_STRING,
228                            GTK_ARG_READWRITE, ARG_LANGUAGE);
229   
230   /* Style args are set or not */
231   gtk_object_add_arg_type ("GtkTextTag::background_set", GTK_TYPE_BOOL,
232                            GTK_ARG_READWRITE, ARG_BACKGROUND_SET);
233   gtk_object_add_arg_type ("GtkTextTag::foreground_set", GTK_TYPE_BOOL,
234                            GTK_ARG_READWRITE, ARG_FOREGROUND_SET);
235   gtk_object_add_arg_type ("GtkTextTag::background_gdk_set", GTK_TYPE_BOOL,
236                            GTK_ARG_READWRITE, ARG_BACKGROUND_GDK_SET);
237   gtk_object_add_arg_type ("GtkTextTag::foreground_gdk_set", GTK_TYPE_BOOL,
238                            GTK_ARG_READWRITE, ARG_FOREGROUND_GDK_SET);
239   gtk_object_add_arg_type ("GtkTextTag::background_stipple_set", GTK_TYPE_BOOL,
240                            GTK_ARG_READWRITE, ARG_BACKGROUND_STIPPLE_SET);
241   gtk_object_add_arg_type ("GtkTextTag::foreground_stipple_set", GTK_TYPE_BOOL,
242                            GTK_ARG_READWRITE, ARG_FOREGROUND_STIPPLE_SET);
243   gtk_object_add_arg_type ("GtkTextTag::font_set", GTK_TYPE_BOOL,
244                            GTK_ARG_READWRITE, ARG_FONT_SET);
245   gtk_object_add_arg_type ("GtkTextTag::pixels_above_lines_set", GTK_TYPE_BOOL,
246                            GTK_ARG_READWRITE, ARG_PIXELS_ABOVE_LINES_SET);
247   gtk_object_add_arg_type ("GtkTextTag::pixels_below_lines_set", GTK_TYPE_BOOL,
248                            GTK_ARG_READWRITE, ARG_PIXELS_BELOW_LINES_SET);
249   gtk_object_add_arg_type ("GtkTextTag::pixels_inside_wrap_set", GTK_TYPE_BOOL,
250                            GTK_ARG_READWRITE, ARG_PIXELS_INSIDE_WRAP_SET);
251   gtk_object_add_arg_type ("GtkTextTag::editable_set", GTK_TYPE_BOOL,
252                            GTK_ARG_READWRITE, ARG_EDITABLE_SET);
253   gtk_object_add_arg_type ("GtkTextTag::wrap_mode_set", GTK_TYPE_BOOL,
254                            GTK_ARG_READWRITE, ARG_WRAP_MODE_SET);
255   gtk_object_add_arg_type ("GtkTextTag::justify_set", GTK_TYPE_BOOL,
256                            GTK_ARG_READWRITE, ARG_JUSTIFY_SET);
257   gtk_object_add_arg_type ("GtkTextTag::left_margin_set", GTK_TYPE_BOOL,
258                            GTK_ARG_READWRITE, ARG_LEFT_MARGIN_SET);
259   gtk_object_add_arg_type ("GtkTextTag::left_wrapped_line_margin_set", GTK_TYPE_BOOL,
260                            GTK_ARG_READWRITE, ARG_LEFT_WRAPPED_LINE_MARGIN_SET);
261   gtk_object_add_arg_type ("GtkTextTag::overstrike_set", GTK_TYPE_BOOL,
262                            GTK_ARG_READWRITE, ARG_OVERSTRIKE_SET);
263   gtk_object_add_arg_type ("GtkTextTag::right_margin_set", GTK_TYPE_BOOL,
264                            GTK_ARG_READWRITE, ARG_RIGHT_MARGIN_SET);
265   gtk_object_add_arg_type ("GtkTextTag::pixels_above_lines_set", GTK_TYPE_BOOL,
266                            GTK_ARG_READWRITE, ARG_PIXELS_ABOVE_LINES_SET);
267   gtk_object_add_arg_type ("GtkTextTag::pixels_below_lines_set", GTK_TYPE_BOOL,
268                            GTK_ARG_READWRITE, ARG_PIXELS_BELOW_LINES_SET);
269   gtk_object_add_arg_type ("GtkTextTag::pixels_inside_wrap_set", GTK_TYPE_BOOL,
270                            GTK_ARG_READWRITE, ARG_PIXELS_INSIDE_WRAP_SET);
271   gtk_object_add_arg_type ("GtkTextTag::underline_set", GTK_TYPE_ENUM,
272                            GTK_ARG_READWRITE, ARG_UNDERLINE_SET);
273   gtk_object_add_arg_type ("GtkTextTag::wrap_mode_set", GTK_TYPE_BOOL,
274                            GTK_ARG_READWRITE, ARG_WRAP_MODE_SET);
275   gtk_object_add_arg_type ("GtkTextTag::offset_set", GTK_TYPE_BOOL,
276                            GTK_ARG_READWRITE, ARG_OFFSET_SET);  
277   gtk_object_add_arg_type ("GtkTextTag::background_full_height_set", GTK_TYPE_BOOL,
278                            GTK_ARG_READWRITE, ARG_BG_FULL_HEIGHT_SET);
279   gtk_object_add_arg_type ("GtkTextTag::language_set", GTK_TYPE_BOOL,
280                            GTK_ARG_READWRITE, ARG_LANGUAGE_SET);
281   
282   signals[EVENT] =
283     gtk_signal_new ("event",
284                     GTK_RUN_LAST,
285                     GTK_CLASS_TYPE (object_class),
286                     GTK_SIGNAL_OFFSET (GtkTextTagClass, event),
287                     gtk_marshal_INT__OBJECT_BOXED_POINTER,
288                     GTK_TYPE_INT,
289                     3,
290                     GTK_TYPE_OBJECT,
291                     GTK_TYPE_GDK_EVENT,
292                     GTK_TYPE_POINTER);
293
294   gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
295
296   object_class->set_arg = gtk_text_tag_set_arg;
297   object_class->get_arg = gtk_text_tag_get_arg;
298
299   object_class->destroy = gtk_text_tag_destroy;
300   gobject_class->finalize = gtk_text_tag_finalize;
301 }
302
303 void
304 gtk_text_tag_init (GtkTextTag *tkxt_tag)
305 {
306   /* 0 is basically a fine way to initialize everything in the
307      entire struct */
308   
309 }
310
311 GtkTextTag*
312 gtk_text_tag_new (const gchar *name)
313 {
314   GtkTextTag *tag;
315
316   tag = GTK_TEXT_TAG (gtk_type_new (gtk_text_tag_get_type ()));
317
318   tag->name = g_strdup(name);
319
320   tag->values = gtk_text_attributes_new();
321   
322   return tag;
323 }
324
325 static void
326 gtk_text_tag_destroy (GtkObject *object)
327 {
328   GtkTextTag *tkxt_tag;
329
330   tkxt_tag = GTK_TEXT_TAG (object);
331
332   g_assert(!tkxt_tag->values->realized);
333   
334   if (tkxt_tag->table)
335     gtk_text_tag_table_remove(tkxt_tag->table, tkxt_tag);
336
337   g_assert(tkxt_tag->table == NULL);
338   
339   gtk_text_attributes_unref(tkxt_tag->values);
340   tkxt_tag->values = NULL;
341   
342   (* GTK_OBJECT_CLASS(parent_class)->destroy) (object);
343 }
344
345 static void
346 gtk_text_tag_finalize (GObject *object)
347 {
348   GtkTextTag *tkxt_tag;
349
350   tkxt_tag = GTK_TEXT_TAG (object);
351
352   g_free(tkxt_tag->name);
353   tkxt_tag->name = NULL;
354
355   (* G_OBJECT_CLASS(parent_class)->finalize) (object);
356 }
357
358 static void
359 set_bg_color(GtkTextTag *tag, GdkColor *color)
360 {
361   if (color)
362     {
363       tag->bg_color_set = TRUE;
364       tag->values->appearance.bg_color = *color;
365     }
366   else
367     {
368       tag->bg_color_set = FALSE;
369     }
370 }
371
372 static void
373 set_fg_color(GtkTextTag *tag, GdkColor *color)
374 {
375   if (color)
376     {
377       tag->fg_color_set = TRUE;
378       tag->values->appearance.fg_color = *color;
379     }
380   else
381     {
382       tag->fg_color_set = FALSE;
383     }
384 }
385
386 static void
387 gtk_text_tag_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
388 {
389   GtkTextTag *tkxt_tag;
390   gboolean size_changed = FALSE;
391   
392   tkxt_tag = GTK_TEXT_TAG (object);
393
394   g_return_if_fail(!tkxt_tag->values->realized);
395   
396   switch (arg_id)
397     {
398     case ARG_NAME:
399       g_return_if_fail(tkxt_tag->name == NULL);
400       tkxt_tag->name = g_strdup(GTK_VALUE_STRING(*arg));
401       break;
402
403     case ARG_BACKGROUND:
404       {
405         GdkColor color;
406
407         if (gdk_color_parse(GTK_VALUE_STRING(*arg), &color))
408           set_bg_color(tkxt_tag, &color);
409         else
410           g_warning("Don't know color `%s'", GTK_VALUE_STRING(*arg));
411       }
412       break;
413
414     case ARG_FOREGROUND:
415       {
416         GdkColor color;
417
418         if (gdk_color_parse(GTK_VALUE_STRING(*arg), &color))
419           set_fg_color(tkxt_tag, &color);
420         else
421           g_warning("Don't know color `%s'", GTK_VALUE_STRING(*arg));
422       }
423       break;
424       
425     case ARG_BACKGROUND_GDK:
426       {
427         GdkColor *color = GTK_VALUE_POINTER(*arg);
428         set_bg_color(tkxt_tag, color);
429       }
430       break;
431
432     case ARG_FOREGROUND_GDK:
433       {
434         GdkColor *color = GTK_VALUE_POINTER(*arg);
435         set_fg_color(tkxt_tag, color);
436       }
437       break;
438
439     case ARG_BACKGROUND_STIPPLE:
440       {
441         GdkBitmap *bitmap = GTK_VALUE_POINTER(*arg);
442
443         tkxt_tag->bg_stipple_set = TRUE;
444         
445         if (tkxt_tag->values->appearance.bg_stipple != bitmap)
446           {
447             if (bitmap != NULL)
448               gdk_bitmap_ref(bitmap);
449             
450             if (tkxt_tag->values->appearance.bg_stipple)
451               gdk_bitmap_unref(tkxt_tag->values->appearance.bg_stipple);
452             
453             tkxt_tag->values->appearance.bg_stipple = bitmap;
454           }
455       }
456       break;
457
458     case ARG_FOREGROUND_STIPPLE:
459       {
460         GdkBitmap *bitmap = GTK_VALUE_POINTER(*arg);
461
462         tkxt_tag->fg_stipple_set = TRUE;
463         
464         if (tkxt_tag->values->appearance.fg_stipple != bitmap)
465           {
466             if (bitmap != NULL)
467               gdk_bitmap_ref(bitmap);
468             
469             if (tkxt_tag->values->appearance.fg_stipple)
470               gdk_bitmap_unref(tkxt_tag->values->appearance.fg_stipple);
471             
472             tkxt_tag->values->appearance.fg_stipple = bitmap;
473           }
474       }
475       break;
476
477     case ARG_FONT:
478       {
479         PangoFontDescription *font_desc = NULL;
480         const gchar *name;
481
482         name = GTK_VALUE_STRING(*arg);        
483
484         if (name)
485           font_desc = pango_font_description_from_string (name);
486
487         if (tkxt_tag->values->font_desc)
488           pango_font_description_free (tkxt_tag->values->font_desc);
489         
490         tkxt_tag->font_set = (font_desc != NULL);
491         tkxt_tag->values->font_desc = font_desc;
492
493         size_changed = TRUE;
494       }
495       break;
496
497     case ARG_FONT_DESC:
498       {
499         PangoFontDescription *font_desc;
500
501         font_desc = GTK_VALUE_BOXED(*arg);        
502
503         if (tkxt_tag->values->font_desc)
504           pango_font_description_free (tkxt_tag->values->font_desc);
505
506         if (font_desc)
507           tkxt_tag->values->font_desc = pango_font_description_copy (font_desc);
508         else
509           tkxt_tag->values->font_desc = NULL;
510         
511         tkxt_tag->font_set = (font_desc != NULL);
512
513         size_changed = TRUE;
514       }
515       break;
516
517     case ARG_PIXELS_ABOVE_LINES:
518       tkxt_tag->pixels_above_lines_set = TRUE;
519       tkxt_tag->values->pixels_above_lines = GTK_VALUE_INT(*arg);
520       size_changed = TRUE;
521       break;
522
523     case ARG_PIXELS_BELOW_LINES:
524       tkxt_tag->pixels_below_lines_set = TRUE;
525       tkxt_tag->values->pixels_below_lines = GTK_VALUE_INT(*arg);
526       size_changed = TRUE;
527       break;
528
529     case ARG_PIXELS_INSIDE_WRAP:
530       tkxt_tag->pixels_inside_wrap_set = TRUE;
531       tkxt_tag->values->pixels_inside_wrap = GTK_VALUE_INT(*arg);
532       size_changed = TRUE;
533       break;
534
535     case ARG_EDITABLE:
536       tkxt_tag->editable_set = TRUE;
537       tkxt_tag->values->editable = GTK_VALUE_BOOL(*arg);
538       break;
539
540     case ARG_WRAP_MODE:
541       tkxt_tag->wrap_mode_set = TRUE;
542       tkxt_tag->values->wrap_mode = GTK_VALUE_ENUM(*arg);
543       size_changed = TRUE;
544       break;
545
546     case ARG_JUSTIFY:
547       tkxt_tag->justify_set = TRUE;
548       tkxt_tag->values->justify = GTK_VALUE_ENUM(*arg);
549       size_changed = TRUE;
550       break;
551
552     case ARG_DIRECTION:
553       tkxt_tag->values->direction = GTK_VALUE_ENUM(*arg);
554       break;
555
556     case ARG_LEFT_MARGIN:
557       tkxt_tag->left_margin_set = TRUE;
558       tkxt_tag->values->left_margin = GTK_VALUE_INT(*arg);
559       size_changed = TRUE;
560       break;
561
562     case ARG_LEFT_WRAPPED_LINE_MARGIN:
563       tkxt_tag->left_wrapped_line_margin_set = TRUE;
564       tkxt_tag->values->left_wrapped_line_margin = GTK_VALUE_INT(*arg);
565       size_changed = TRUE;
566       break;
567
568     case ARG_OVERSTRIKE:
569       tkxt_tag->overstrike_set = TRUE;
570       tkxt_tag->values->appearance.overstrike = GTK_VALUE_BOOL(*arg);
571       break;
572       
573     case ARG_RIGHT_MARGIN:
574       tkxt_tag->right_margin_set = TRUE;
575       tkxt_tag->values->right_margin = GTK_VALUE_INT(*arg);
576       size_changed = TRUE;
577       break;
578       
579     case ARG_UNDERLINE:
580       tkxt_tag->underline_set = TRUE;
581       tkxt_tag->values->appearance.underline = GTK_VALUE_ENUM(*arg);
582       break;
583       
584     case ARG_OFFSET:
585       tkxt_tag->offset_set = TRUE;
586       tkxt_tag->values->offset = GTK_VALUE_INT(*arg);
587       size_changed = TRUE;
588       break;
589
590     case ARG_BG_FULL_HEIGHT:
591       tkxt_tag->bg_full_height_set = TRUE;
592       tkxt_tag->values->bg_full_height = GTK_VALUE_BOOL(*arg);
593       break;
594
595     case ARG_LANGUAGE:
596       tkxt_tag->language_set = TRUE;
597       tkxt_tag->values->language = g_strdup (GTK_VALUE_STRING(*arg));
598       break;
599       
600       /* Whether the value should be used... */
601       
602     case ARG_BACKGROUND_SET:
603     case ARG_BACKGROUND_GDK_SET:
604       tkxt_tag->bg_color_set = GTK_VALUE_BOOL(*arg);
605       break;
606
607     case ARG_FOREGROUND_SET:
608     case ARG_FOREGROUND_GDK_SET:
609       tkxt_tag->fg_color_set = GTK_VALUE_BOOL(*arg);
610       break;
611
612     case ARG_BACKGROUND_STIPPLE_SET:
613       tkxt_tag->bg_stipple_set = GTK_VALUE_BOOL(*arg);
614       break;
615
616     case ARG_FOREGROUND_STIPPLE_SET:
617       tkxt_tag->fg_stipple_set = GTK_VALUE_BOOL(*arg);
618       break;
619
620     case ARG_FONT_SET:
621       tkxt_tag->font_set = GTK_VALUE_BOOL(*arg);
622       size_changed = TRUE;
623       break;
624
625     case ARG_PIXELS_ABOVE_LINES_SET:
626       tkxt_tag->pixels_above_lines_set = GTK_VALUE_BOOL(*arg);
627       size_changed = TRUE;
628       break;
629
630     case ARG_PIXELS_BELOW_LINES_SET:
631       tkxt_tag->pixels_below_lines_set = GTK_VALUE_BOOL(*arg);
632       size_changed = TRUE;
633       break;
634
635     case ARG_PIXELS_INSIDE_WRAP_SET:
636       tkxt_tag->pixels_inside_wrap_set = GTK_VALUE_BOOL(*arg);
637       size_changed = TRUE;
638       break;
639
640     case ARG_EDITABLE_SET:
641       tkxt_tag->editable_set = GTK_VALUE_BOOL(*arg);
642       break;
643
644     case ARG_WRAP_MODE_SET:
645       tkxt_tag->wrap_mode_set = GTK_VALUE_BOOL(*arg);
646       size_changed = TRUE;
647       break;
648
649     case ARG_JUSTIFY_SET:
650       tkxt_tag->justify_set = GTK_VALUE_BOOL(*arg);
651       size_changed = TRUE;
652       break;
653
654     case ARG_LEFT_MARGIN_SET:
655       tkxt_tag->left_margin_set = GTK_VALUE_BOOL(*arg);
656       size_changed = TRUE;
657       break;
658
659     case ARG_LEFT_WRAPPED_LINE_MARGIN_SET:
660       tkxt_tag->left_wrapped_line_margin_set = GTK_VALUE_BOOL(*arg);
661       size_changed = TRUE;
662       break;
663
664     case ARG_OVERSTRIKE_SET:
665       tkxt_tag->overstrike_set = GTK_VALUE_BOOL(*arg);
666       break;
667
668     case ARG_RIGHT_MARGIN_SET:
669       tkxt_tag->right_margin_set = GTK_VALUE_BOOL(*arg);
670       size_changed = TRUE;
671       break;
672
673     case ARG_UNDERLINE_SET:
674       tkxt_tag->underline_set = GTK_VALUE_BOOL(*arg);
675       break;
676
677     case ARG_OFFSET_SET:
678       tkxt_tag->offset_set = GTK_VALUE_BOOL(*arg);
679       size_changed = TRUE;
680       break;
681
682     case ARG_BG_FULL_HEIGHT_SET:
683       tkxt_tag->bg_full_height_set = GTK_VALUE_BOOL(*arg);
684       break;
685
686     case ARG_LANGUAGE_SET:
687       tkxt_tag->language_set = GTK_VALUE_BOOL(*arg);
688       size_changed = TRUE;
689       break;
690       
691     default:
692       g_assert_not_reached();
693       break;
694     }
695   
696   /* FIXME I would like to do this after all set_arg in a single
697      gtk_object_set() have been called. But an idle function
698      won't work; we need to emit when the tag is changed, not
699      when we get around to the event loop. So blah, we eat some
700      inefficiency. */
701   
702   /* This is also somewhat weird since we emit another object's
703      signal here, but the two objects are already tightly bound. */
704   
705   if (tkxt_tag->table)
706     gtk_signal_emit_by_name(GTK_OBJECT(tkxt_tag->table),
707                             "tag_changed",
708                             tkxt_tag, size_changed);
709 }
710
711 static void
712 get_color_arg (GtkArg *arg, GdkColor *orig)
713 {
714   GdkColor *color;
715   
716   color = g_new (GdkColor, 1);
717   *color = *orig;
718   GTK_VALUE_BOXED (*arg) = color;
719 }
720
721 static void
722 gtk_text_tag_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
723 {
724   GtkTextTag *tag;
725
726   tag = GTK_TEXT_TAG (object);
727
728   switch (arg_id)
729     {
730     case ARG_NAME:
731       GTK_VALUE_STRING(*arg) = g_strdup(tag->name);
732       break;
733       
734     case ARG_BACKGROUND_GDK:
735       get_color_arg(arg, &tag->values->appearance.bg_color);
736       break;
737
738     case ARG_FOREGROUND_GDK:
739       get_color_arg(arg, &tag->values->appearance.fg_color);
740       break;
741
742     case ARG_BACKGROUND_STIPPLE:
743       GTK_VALUE_BOXED(*arg) = tag->values->appearance.bg_stipple;
744       break;
745
746     case ARG_FOREGROUND_STIPPLE:
747       GTK_VALUE_BOXED(*arg) = tag->values->appearance.fg_stipple;
748       break;
749
750     case ARG_FONT:
751       if (tag->values->font_desc)
752         GTK_VALUE_STRING(*arg) = pango_font_description_to_string (tag->values->font_desc);
753       else
754         GTK_VALUE_STRING(*arg) = NULL;
755       break;
756
757     case ARG_FONT_DESC:
758       if (tag->values->font_desc)
759         GTK_VALUE_BOXED(*arg) = pango_font_description_copy (tag->values->font_desc);
760       else
761         GTK_VALUE_BOXED(*arg) = NULL;
762       break;
763
764     case ARG_PIXELS_ABOVE_LINES:
765       GTK_VALUE_INT(*arg) = tag->values->pixels_above_lines;
766       break;
767
768     case ARG_PIXELS_BELOW_LINES:
769       GTK_VALUE_INT(*arg) = tag->values->pixels_below_lines;
770       break;
771
772     case ARG_PIXELS_INSIDE_WRAP:
773       GTK_VALUE_INT(*arg) = tag->values->pixels_inside_wrap;
774       break;
775
776     case ARG_EDITABLE:
777       GTK_VALUE_BOOL(*arg) = tag->values->editable;
778       break;      
779
780     case ARG_WRAP_MODE:
781       GTK_VALUE_ENUM(*arg) = tag->values->wrap_mode;
782       break;
783
784     case ARG_JUSTIFY:
785       GTK_VALUE_ENUM(*arg) = tag->values->justify;
786       break;
787
788     case ARG_LEFT_MARGIN:
789       GTK_VALUE_INT(*arg) = tag->values->left_margin;
790       break;
791
792     case ARG_LEFT_WRAPPED_LINE_MARGIN:
793       GTK_VALUE_INT(*arg) = tag->values->left_wrapped_line_margin;
794       break;
795
796     case ARG_OVERSTRIKE:
797       GTK_VALUE_BOOL(*arg) = tag->values->appearance.overstrike;
798       break;
799       
800     case ARG_RIGHT_MARGIN:
801       GTK_VALUE_INT(*arg) = tag->values->right_margin;
802       break;
803       
804     case ARG_UNDERLINE:
805       GTK_VALUE_ENUM(*arg) = tag->values->appearance.underline;
806       break;
807
808     case ARG_OFFSET:
809       GTK_VALUE_INT(*arg) = tag->values->offset;
810       break;
811
812     case ARG_BG_FULL_HEIGHT:
813       GTK_VALUE_BOOL(*arg) = tag->values->bg_full_height;
814       break;
815
816     case ARG_LANGUAGE:
817       GTK_VALUE_STRING(*arg) = g_strdup (tag->values->language);
818       break;
819       
820     case ARG_BACKGROUND_SET:
821     case ARG_BACKGROUND_GDK_SET:
822       GTK_VALUE_BOOL(*arg) = tag->bg_color_set;
823       break;
824
825     case ARG_FOREGROUND_SET:
826     case ARG_FOREGROUND_GDK_SET:
827       GTK_VALUE_BOOL(*arg) = tag->fg_color_set;
828       break;
829
830     case ARG_BACKGROUND_STIPPLE_SET:
831       GTK_VALUE_BOOL(*arg) = tag->bg_stipple_set;
832       break;
833
834     case ARG_FOREGROUND_STIPPLE_SET:
835       GTK_VALUE_BOOL(*arg) = tag->fg_stipple_set;
836       break;
837
838     case ARG_FONT_SET:
839       GTK_VALUE_BOOL(*arg) = tag->font_set;
840       break;
841
842     case ARG_PIXELS_ABOVE_LINES_SET:
843       GTK_VALUE_BOOL(*arg) = tag->pixels_above_lines_set;
844       break;
845
846     case ARG_PIXELS_BELOW_LINES_SET:
847       GTK_VALUE_BOOL(*arg) = tag->pixels_below_lines_set;
848       break;
849
850     case ARG_PIXELS_INSIDE_WRAP_SET:
851       GTK_VALUE_BOOL(*arg) = tag->pixels_inside_wrap_set;
852       break;
853
854     case ARG_EDITABLE_SET:
855       GTK_VALUE_BOOL(*arg) = tag->editable_set;
856       break;
857
858     case ARG_WRAP_MODE_SET:
859       GTK_VALUE_BOOL(*arg) = tag->wrap_mode_set;
860       break;
861
862     case ARG_JUSTIFY_SET:
863       GTK_VALUE_BOOL(*arg) = tag->justify_set;
864       break;
865
866     case ARG_LEFT_MARGIN_SET:
867       GTK_VALUE_BOOL(*arg) = tag->left_margin_set;
868       break;
869
870     case ARG_LEFT_WRAPPED_LINE_MARGIN_SET:
871       GTK_VALUE_BOOL(*arg) = tag->left_wrapped_line_margin_set;
872       break;
873
874     case ARG_OVERSTRIKE_SET:
875       GTK_VALUE_BOOL(*arg) = tag->overstrike_set;
876       break;
877
878     case ARG_RIGHT_MARGIN_SET:
879       GTK_VALUE_BOOL(*arg) = tag->right_margin_set;
880       break;
881
882     case ARG_UNDERLINE_SET:
883       GTK_VALUE_BOOL(*arg) = tag->underline_set;
884       break;
885
886     case ARG_OFFSET_SET:
887       GTK_VALUE_BOOL(*arg) = tag->offset_set;
888       break;
889
890     case ARG_BG_FULL_HEIGHT_SET:
891       GTK_VALUE_BOOL(*arg) = tag->bg_full_height_set;
892       break;
893
894     case ARG_LANGUAGE_SET:
895       GTK_VALUE_BOOL(*arg) = tag->language_set;
896       break;
897       
898     case ARG_BACKGROUND:
899     case ARG_FOREGROUND:
900     default:
901       arg->type = GTK_TYPE_INVALID;
902       break;
903     }
904   /* FIXME */
905   arg->type = GTK_TYPE_INVALID;
906 }
907
908 /*
909  * Tag operations
910  */
911
912 typedef struct {
913   gint high;
914   gint low;
915   gint delta;
916 } DeltaData;
917
918 static void
919 delta_priority_foreach(GtkTextTag *tag, gpointer user_data)
920 {
921   DeltaData *dd = user_data;
922
923   if (tag->priority >= dd->low && tag->priority <= dd->high)
924     tag->priority += dd->delta;
925 }
926
927 gint
928 gtk_text_tag_get_priority (GtkTextTag *tag)
929 {
930   g_return_val_if_fail(GTK_IS_TEXT_TAG(tag), 0);
931
932   return tag->priority;
933 }
934
935 void
936 gtk_text_tag_set_priority(GtkTextTag *tag,
937                            gint priority)
938 {
939     DeltaData dd;
940     
941     g_return_if_fail(GTK_IS_TEXT_TAG(tag));
942     g_return_if_fail(tag->table != NULL);
943     g_return_if_fail(priority >= 0);
944     g_return_if_fail(priority < gtk_text_tag_table_size(tag->table));
945
946     if (priority == tag->priority)
947       return;
948
949     if (priority < tag->priority) {
950       dd.low = priority;
951       dd.high = tag->priority - 1;
952       dd.delta = 1;
953     } else {
954       dd.low = tag->priority + 1;
955       dd.high = priority;
956       dd.delta = -1;
957     }
958
959     gtk_text_tag_table_foreach(tag->table, delta_priority_foreach,
960                                &dd);
961     
962     tag->priority = priority;
963 }
964
965 gint
966 gtk_text_tag_event(GtkTextTag *tag,
967                     GtkObject *event_object,
968                     GdkEvent *event,
969                     const GtkTextIter *iter)
970 {
971   gint retval = FALSE;
972
973   g_return_val_if_fail(GTK_IS_TEXT_TAG(tag), FALSE);
974   g_return_val_if_fail(GTK_IS_OBJECT(event_object), FALSE);
975   g_return_val_if_fail(event != NULL, FALSE);
976   
977   gtk_signal_emit(GTK_OBJECT(tag),
978                   signals[EVENT],
979                   event_object,
980                   event,
981                   iter,
982                   &retval);
983
984   return retval;
985 }
986
987 static int
988 tag_sort_func(gconstpointer first, gconstpointer second)
989 {
990     GtkTextTag *tag1, *tag2;
991
992     tag1 = * (GtkTextTag **) first;
993     tag2 = * (GtkTextTag **) second;
994     return tag1->priority - tag2->priority;
995 }
996
997 void
998 gtk_text_tag_array_sort(GtkTextTag** tag_array_p,
999                          guint len)
1000 {
1001   int i, j, prio;
1002   GtkTextTag **tag;
1003   GtkTextTag **maxPtrPtr, *tmp;
1004
1005   g_return_if_fail(tag_array_p != NULL);
1006   g_return_if_fail(len > 0);
1007   
1008   if (len < 2) {
1009     return;
1010   }
1011   if (len < 20) {
1012     GtkTextTag **iter = tag_array_p;
1013
1014     for (i = len-1; i > 0; i--, iter++) {
1015       maxPtrPtr = tag = iter;
1016       prio = tag[0]->priority;
1017       for (j = i, tag++; j > 0; j--, tag++) {
1018         if (tag[0]->priority < prio) {
1019           prio = tag[0]->priority;
1020           maxPtrPtr = tag;
1021         }
1022       }
1023       tmp = *maxPtrPtr;
1024       *maxPtrPtr = *iter;
1025       *iter = tmp;
1026     }
1027   } else {
1028     qsort((void *) tag_array_p, (unsigned) len, sizeof (GtkTextTag *),
1029           tag_sort_func);
1030   }
1031
1032 #if 0
1033   {
1034     printf("Sorted tag array: \n");
1035     i = 0;
1036     while (i < len)
1037       {
1038         GtkTextTag *t = tag_array_p[i];
1039         printf("  %s priority %d\n", t->name, t->priority);
1040         
1041         ++i;
1042       }
1043   }
1044 #endif
1045 }
1046
1047 /*
1048  * Attributes
1049  */
1050
1051 GtkTextAttributes*
1052 gtk_text_attributes_new(void)
1053 {
1054   GtkTextAttributes *values;
1055
1056   values = g_new0(GtkTextAttributes, 1);
1057
1058   /* 0 is a valid value for most of the struct */
1059
1060   values->refcount = 1;
1061
1062   values->language = gtk_get_default_language ();
1063   
1064   return values;
1065 }
1066
1067 void
1068 gtk_text_attributes_copy(GtkTextAttributes *src,
1069                            GtkTextAttributes *dest)
1070 {
1071   guint orig_refcount;
1072
1073   g_return_if_fail(!dest->realized);
1074
1075   if (src == dest)
1076     return;
1077   
1078   /* Add refs */
1079   
1080   if (src->appearance.bg_stipple)
1081     gdk_bitmap_ref(src->appearance.bg_stipple);
1082
1083   if (src->appearance.fg_stipple)
1084     gdk_bitmap_ref(src->appearance.fg_stipple);
1085
1086   if (src->tab_array)
1087     gtk_text_view_tab_array_ref(src->tab_array);
1088
1089   /* Remove refs */
1090   
1091   if (dest->appearance.bg_stipple)
1092     gdk_bitmap_unref(dest->appearance.bg_stipple);
1093
1094   if (dest->appearance.fg_stipple)
1095     gdk_bitmap_unref(dest->appearance.fg_stipple);
1096
1097   if (dest->tab_array)
1098     gtk_text_view_tab_array_unref(dest->tab_array);
1099
1100   /* Copy */
1101   orig_refcount = dest->refcount;
1102   
1103   *dest = *src;
1104
1105   dest->font_desc = pango_font_description_copy (src->font_desc);
1106   dest->language = g_strdup (src->language);
1107   
1108   dest->refcount = orig_refcount;
1109   dest->realized = FALSE;
1110 }
1111
1112 void
1113 gtk_text_attributes_ref(GtkTextAttributes *values)
1114 {
1115   g_return_if_fail(values != NULL);
1116
1117   values->refcount += 1;
1118 }
1119
1120 void
1121 gtk_text_attributes_unref(GtkTextAttributes *values)
1122 {
1123   g_return_if_fail(values != NULL);
1124   g_return_if_fail(values->refcount > 0);
1125
1126   values->refcount -= 1;
1127
1128   if (values->refcount == 0)
1129     {
1130       g_assert(!values->realized);
1131       
1132       if (values->appearance.bg_stipple)
1133         gdk_bitmap_unref(values->appearance.bg_stipple);
1134       
1135       if (values->font_desc)
1136         pango_font_description_free (values->font_desc);
1137       
1138       if (values->appearance.fg_stipple)
1139         gdk_bitmap_unref(values->appearance.fg_stipple);
1140
1141       if (values->tab_array)
1142         gtk_text_view_tab_array_unref(values->tab_array);
1143
1144       if (values->language)
1145         g_free (values->language);
1146       
1147       g_free(values);
1148     }
1149 }
1150
1151 void
1152 gtk_text_attributes_realize(GtkTextAttributes *values,
1153                               GdkColormap *cmap,
1154                               GdkVisual *visual)
1155 {
1156   g_return_if_fail(values != NULL);
1157   g_return_if_fail(values->refcount > 0);
1158   g_return_if_fail(!values->realized);
1159   
1160   /* It is wrong to use this colormap, FIXME */
1161   gdk_colormap_alloc_color(cmap,
1162                            &values->appearance.fg_color,
1163                            FALSE, TRUE);
1164
1165   gdk_colormap_alloc_color(cmap,
1166                            &values->appearance.bg_color,
1167                            FALSE, TRUE);
1168
1169   values->realized = TRUE;
1170 }
1171
1172 void
1173 gtk_text_attributes_unrealize(GtkTextAttributes *values,
1174                                 GdkColormap *cmap,
1175                                 GdkVisual *visual)
1176 {
1177   g_return_if_fail(values != NULL);
1178   g_return_if_fail(values->refcount > 0);
1179   g_return_if_fail(values->realized);
1180   
1181   gdk_colormap_free_colors(cmap,
1182                            &values->appearance.fg_color, 1);
1183   
1184   
1185   gdk_colormap_free_colors(cmap,
1186                            &values->appearance.bg_color, 1);
1187
1188   values->appearance.fg_color.pixel = 0;
1189   values->appearance.bg_color.pixel = 0;
1190
1191   values->realized = FALSE;
1192 }
1193
1194 void
1195 gtk_text_attributes_fill_from_tags(GtkTextAttributes *dest,
1196                                      GtkTextTag**        tags,
1197                                      guint               n_tags)
1198 {
1199   guint n = 0;
1200
1201   g_return_if_fail(!dest->realized);  
1202   
1203   while (n < n_tags)
1204     {
1205       GtkTextTag *tag = tags[n];
1206       GtkTextAttributes *vals = tag->values;
1207
1208       if (n > 0)
1209         g_assert(tags[n]->priority > tags[n-1]->priority);
1210       
1211       if (tag->bg_color_set)
1212         {
1213           dest->appearance.bg_color = vals->appearance.bg_color;
1214           
1215           dest->appearance.draw_bg = TRUE;
1216         }
1217       
1218       if (tag->border_width_set)
1219         dest->border_width = vals->border_width;
1220
1221       if (tag->relief_set)
1222         dest->relief = vals->relief;
1223
1224       if (tag->bg_stipple_set)
1225         {
1226           gdk_bitmap_ref(vals->appearance.bg_stipple);
1227           if (dest->appearance.bg_stipple)
1228             gdk_bitmap_unref(dest->appearance.bg_stipple);
1229           dest->appearance.bg_stipple = vals->appearance.bg_stipple;
1230
1231           dest->appearance.draw_bg = TRUE;
1232         }
1233
1234       if (tag->fg_color_set)
1235         dest->appearance.fg_color = vals->appearance.fg_color;
1236          
1237       if (tag->font_set)
1238         {
1239           if (dest->font_desc)
1240             pango_font_description_free (dest->font_desc);
1241           dest->font_desc = pango_font_description_copy (vals->font_desc);
1242         }
1243
1244       if (tag->fg_stipple_set)
1245         {
1246           gdk_bitmap_ref(vals->appearance.fg_stipple);
1247           if (dest->appearance.fg_stipple)
1248             gdk_bitmap_unref(dest->appearance.fg_stipple);
1249           dest->appearance.fg_stipple = vals->appearance.fg_stipple;
1250         }
1251
1252       if (tag->justify_set)
1253         dest->justify = vals->justify;
1254
1255       if (vals->direction != GTK_TEXT_DIR_NONE)
1256         dest->direction = vals->direction;
1257       
1258       if (tag->left_margin_set)
1259         dest->left_margin = vals->left_margin;
1260
1261       if (tag->left_wrapped_line_margin_set)
1262         dest->left_wrapped_line_margin = vals->left_wrapped_line_margin;
1263
1264       if (tag->offset_set)
1265         dest->offset = vals->offset;
1266
1267       if (tag->right_margin_set)
1268         dest->right_margin = vals->right_margin;
1269
1270       if (tag->pixels_above_lines_set)
1271         dest->pixels_above_lines = vals->pixels_above_lines;
1272
1273       if (tag->pixels_below_lines_set)
1274         dest->pixels_below_lines = vals->pixels_below_lines;
1275
1276       if (tag->pixels_inside_wrap_set)
1277         dest->pixels_inside_wrap = vals->pixels_inside_wrap;
1278
1279       if (tag->tab_array_set)
1280         {
1281           gtk_text_view_tab_array_ref(vals->tab_array);
1282           if (dest->tab_array)
1283             gtk_text_view_tab_array_unref(dest->tab_array);
1284           dest->tab_array = vals->tab_array;
1285         }
1286
1287       if (tag->wrap_mode_set)
1288         dest->wrap_mode = vals->wrap_mode;
1289
1290       if (tag->underline_set)
1291         dest->appearance.underline = vals->appearance.underline;
1292
1293       if (tag->overstrike_set)
1294         dest->appearance.overstrike = vals->appearance.overstrike;
1295
1296       if (tag->invisible_set)
1297         dest->invisible = vals->invisible;
1298
1299       if (tag->editable_set)
1300         dest->editable = vals->editable;
1301
1302       if (tag->bg_full_height_set)
1303         dest->bg_full_height = vals->bg_full_height;
1304
1305       if (tag->language_set)
1306         {
1307           g_free (dest->language);
1308           dest->language = g_strdup (vals->language);
1309         }
1310       
1311       ++n;
1312     }
1313 }