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