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