]> Pileus Git - ~andy/gtk/blob - gtk/gtktextattributes.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / gtk / gtktextattributes.c
1 /* gtktextattributes.c - text attributes
2  *
3  * Copyright (c) 1992-1994 The Regents of the University of California.
4  * Copyright (c) 1994-1997 Sun Microsystems, Inc.
5  * Copyright (c) 2000      Red Hat, Inc.
6  * Tk -> Gtk port by Havoc Pennington <hp@redhat.com>
7  *
8  * This software is copyrighted by the Regents of the University of
9  * California, Sun Microsystems, Inc., and other parties.  The
10  * following terms apply to all files associated with the software
11  * unless explicitly disclaimed in individual files.
12  *
13  * The authors hereby grant permission to use, copy, modify,
14  * distribute, and license this software and its documentation for any
15  * purpose, provided that existing copyright notices are retained in
16  * all copies and that this notice is included verbatim in any
17  * distributions. No written agreement, license, or royalty fee is
18  * required for any of the authorized uses.  Modifications to this
19  * software may be copyrighted by their authors and need not follow
20  * the licensing terms described here, provided that the new terms are
21  * clearly indicated on the first page of each file where they apply.
22  *
23  * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY
24  * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
25  * DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION,
26  * OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED
27  * OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
30  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
31  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
32  * NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
33  * AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
34  * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
35  *
36  * GOVERNMENT USE: If you are acquiring this software on behalf of the
37  * U.S. government, the Government shall have only "Restricted Rights"
38  * in the software and related documentation as defined in the Federal
39  * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
40  * are acquiring the software on behalf of the Department of Defense,
41  * the software shall be classified as "Commercial Computer Software"
42  * and the Government shall have only "Restricted Rights" as defined
43  * in Clause 252.227-7013 (c) (1) of DFARs.  Notwithstanding the
44  * foregoing, the authors grant the U.S. Government and others acting
45  * in its behalf permission to use and distribute the software in
46  * accordance with the terms specified in this license.
47  *
48  */
49
50 #include "config.h"
51
52 #include "gtktextattributes.h"
53
54 #include "gtktexttag.h"
55 #include "gtktexttypes.h"
56
57 /**
58  * gtk_text_attributes_new:
59  * 
60  * Creates a #GtkTextAttributes, which describes
61  * a set of properties on some text.
62  * 
63  * Return value: a new #GtkTextAttributes,
64  *     free with gtk_text_attributes_unref().
65  */
66 GtkTextAttributes*
67 gtk_text_attributes_new (void)
68 {
69   GtkTextAttributes *values;
70
71   values = g_slice_new0 (GtkTextAttributes);
72
73   /* 0 is a valid value for most of the struct */
74   values->refcount = 1;
75
76   values->language = gtk_get_default_language ();
77
78   values->font_scale = 1.0;
79
80   values->editable = TRUE;
81
82   return values;
83 }
84
85 /**
86  * gtk_text_attributes_copy:
87  * @src: a #GtkTextAttributes to be copied
88  *
89  * Copies @src and returns a new #GtkTextAttributes.
90  *
91  * Return value: a copy of @src,
92  *     free with gtk_text_attributes_unref()
93  */
94 GtkTextAttributes*
95 gtk_text_attributes_copy (GtkTextAttributes *src)
96 {
97   GtkTextAttributes *dest;
98
99   dest = gtk_text_attributes_new ();
100   gtk_text_attributes_copy_values (src, dest);
101
102   return dest;
103 }
104
105 G_DEFINE_BOXED_TYPE (GtkTextAttributes, gtk_text_attributes,
106                      gtk_text_attributes_ref,
107                      gtk_text_attributes_unref)
108
109 /**
110  * gtk_text_attributes_copy_values:
111  * @src: a #GtkTextAttributes
112  * @dest: another #GtkTextAttributes
113  *
114  * Copies the values from @src to @dest so that @dest has
115  * the same values as @src. Frees existing values in @dest.
116  */
117 void
118 gtk_text_attributes_copy_values (GtkTextAttributes *src,
119                                  GtkTextAttributes *dest)
120 {
121   guint orig_refcount;
122
123   if (src == dest)
124     return;
125
126   /* Remove refs */
127   if (dest->tabs)
128     pango_tab_array_free (dest->tabs);
129
130   if (dest->font)
131     pango_font_description_free (dest->font);
132
133   if (dest->pg_bg_color)
134     gdk_color_free (dest->pg_bg_color);
135
136   if (dest->pg_bg_rgba)
137     gdk_rgba_free (dest->pg_bg_rgba);
138
139   if (dest->appearance.rgba[0])
140     gdk_rgba_free (dest->appearance.rgba[0]);
141
142   if (dest->appearance.rgba[1])
143     gdk_rgba_free (dest->appearance.rgba[1]);
144
145   /* Copy */
146   orig_refcount = dest->refcount;
147
148   *dest = *src;
149
150   if (src->tabs)
151     dest->tabs = pango_tab_array_copy (src->tabs);
152
153   dest->language = src->language;
154
155   if (src->font)
156     dest->font = pango_font_description_copy (src->font);
157
158   if (src->pg_bg_color)
159     dest->pg_bg_color = gdk_color_copy (src->pg_bg_color);
160
161   if (src->pg_bg_rgba)
162     dest->pg_bg_rgba = gdk_rgba_copy (src->pg_bg_rgba);
163
164   if (src->appearance.rgba[0])
165     dest->appearance.rgba[0] = gdk_rgba_copy (src->appearance.rgba[0]);
166
167   if (src->appearance.rgba[1])
168     dest->appearance.rgba[1] = gdk_rgba_copy (src->appearance.rgba[1]);
169
170   dest->refcount = orig_refcount;
171 }
172
173 /**
174  * gtk_text_attributes_ref:
175  * @values: a #GtkTextAttributes
176  * 
177  * Increments the reference count on @values.
178  *
179  * Returns: the #GtkTextAttributes that were passed in
180  **/
181 GtkTextAttributes *
182 gtk_text_attributes_ref (GtkTextAttributes *values)
183 {
184   g_return_val_if_fail (values != NULL, NULL);
185
186   values->refcount += 1;
187
188   return values;
189 }
190
191 /**
192  * gtk_text_attributes_unref:
193  * @values: a #GtkTextAttributes
194  * 
195  * Decrements the reference count on @values, freeing the structure
196  * if the reference count reaches 0.
197  **/
198 void
199 gtk_text_attributes_unref (GtkTextAttributes *values)
200 {
201   g_return_if_fail (values != NULL);
202   g_return_if_fail (values->refcount > 0);
203
204   values->refcount -= 1;
205
206   if (values->refcount == 0)
207     {
208       if (values->tabs)
209         pango_tab_array_free (values->tabs);
210
211       if (values->font)
212         pango_font_description_free (values->font);
213
214       if (values->pg_bg_color)
215         gdk_color_free (values->pg_bg_color);
216
217       if (values->pg_bg_rgba)
218         gdk_rgba_free (values->pg_bg_rgba);
219
220       if (values->appearance.rgba[0])
221         gdk_rgba_free (values->appearance.rgba[0]);
222
223       if (values->appearance.rgba[1])
224         gdk_rgba_free (values->appearance.rgba[1]);
225
226       g_slice_free (GtkTextAttributes, values);
227     }
228 }
229
230 void
231 _gtk_text_attributes_fill_from_tags (GtkTextAttributes *dest,
232                                      GtkTextTag**       tags,
233                                      guint              n_tags)
234 {
235   guint n = 0;
236
237   guint left_margin_accumulative = 0;
238   guint right_margin_accumulative = 0;
239
240   while (n < n_tags)
241     {
242       GtkTextTag *tag = tags[n];
243       GtkTextAttributes *vals = tag->priv->values;
244
245       g_assert (tag->priv->table != NULL);
246       if (n > 0)
247         g_assert (tags[n]->priv->priority > tags[n-1]->priv->priority);
248
249       if (tag->priv->bg_color_set)
250         {
251           if (dest->appearance.rgba[0])
252             {
253               gdk_rgba_free (dest->appearance.rgba[0]);
254               dest->appearance.rgba[0] = NULL;
255             }
256
257           if (vals->appearance.rgba[0])
258             dest->appearance.rgba[0] = gdk_rgba_copy (vals->appearance.rgba[0]);
259
260           dest->appearance.draw_bg = TRUE;
261         }
262
263       if (tag->priv->fg_color_set)
264         {
265           if (dest->appearance.rgba[1])
266             {
267               gdk_rgba_free (dest->appearance.rgba[1]);
268               dest->appearance.rgba[1] = NULL;
269             }
270
271           if (vals->appearance.rgba[1])
272             dest->appearance.rgba[1] = gdk_rgba_copy (vals->appearance.rgba[1]);
273         }
274
275       if (tag->priv->pg_bg_color_set)
276         {
277           if (dest->pg_bg_rgba)
278             {
279               gdk_rgba_free (dest->pg_bg_rgba);
280               dest->pg_bg_rgba = NULL;
281             }
282
283           if (dest->pg_bg_color)
284             {
285               gdk_color_free (dest->pg_bg_color);
286               dest->pg_bg_color = NULL;
287             }
288
289           if (vals->pg_bg_rgba)
290             dest->pg_bg_rgba = gdk_rgba_copy (vals->pg_bg_rgba);
291
292           if (vals->pg_bg_color)
293             dest->pg_bg_color = gdk_color_copy (vals->pg_bg_color);
294         }
295
296       if (vals->font)
297         {
298           if (dest->font)
299             pango_font_description_merge (dest->font, vals->font, TRUE);
300           else
301             dest->font = pango_font_description_copy (vals->font);
302         }
303
304       /* multiply all the scales together to get a composite */
305       if (tag->priv->scale_set)
306         dest->font_scale *= vals->font_scale;
307
308       if (tag->priv->justification_set)
309         dest->justification = vals->justification;
310
311       if (vals->direction != GTK_TEXT_DIR_NONE)
312         dest->direction = vals->direction;
313
314       if (tag->priv->left_margin_set)
315         {
316           if (tag->priv->accumulative_margin)
317             left_margin_accumulative += vals->left_margin;
318           else
319             dest->left_margin = vals->left_margin;
320         }
321
322       if (tag->priv->indent_set)
323         dest->indent = vals->indent;
324
325       if (tag->priv->rise_set)
326         dest->appearance.rise = vals->appearance.rise;
327
328       if (tag->priv->right_margin_set)
329         {
330           if (tag->priv->accumulative_margin)
331             right_margin_accumulative += vals->right_margin;
332           else
333             dest->right_margin = vals->right_margin;
334         }
335
336       if (tag->priv->pixels_above_lines_set)
337         dest->pixels_above_lines = vals->pixels_above_lines;
338
339       if (tag->priv->pixels_below_lines_set)
340         dest->pixels_below_lines = vals->pixels_below_lines;
341
342       if (tag->priv->pixels_inside_wrap_set)
343         dest->pixels_inside_wrap = vals->pixels_inside_wrap;
344
345       if (tag->priv->tabs_set)
346         {
347           if (dest->tabs)
348             pango_tab_array_free (dest->tabs);
349           dest->tabs = pango_tab_array_copy (vals->tabs);
350         }
351
352       if (tag->priv->wrap_mode_set)
353         dest->wrap_mode = vals->wrap_mode;
354
355       if (tag->priv->underline_set)
356         dest->appearance.underline = vals->appearance.underline;
357
358       if (tag->priv->strikethrough_set)
359         dest->appearance.strikethrough = vals->appearance.strikethrough;
360
361       if (tag->priv->invisible_set)
362         dest->invisible = vals->invisible;
363
364       if (tag->priv->editable_set)
365         dest->editable = vals->editable;
366
367       if (tag->priv->bg_full_height_set)
368         dest->bg_full_height = vals->bg_full_height;
369
370       if (tag->priv->language_set)
371         dest->language = vals->language;
372
373       ++n;
374     }
375
376   dest->left_margin += left_margin_accumulative;
377   dest->right_margin += right_margin_accumulative;
378 }
379
380 gboolean
381 _gtk_text_tag_affects_size (GtkTextTag *tag)
382 {
383   GtkTextTagPrivate *priv = tag->priv;
384
385   return
386     (priv->values->font && pango_font_description_get_set_fields (priv->values->font) != 0) ||
387     priv->scale_set ||
388     priv->justification_set ||
389     priv->left_margin_set ||
390     priv->indent_set ||
391     priv->rise_set ||
392     priv->right_margin_set ||
393     priv->pixels_above_lines_set ||
394     priv->pixels_below_lines_set ||
395     priv->pixels_inside_wrap_set ||
396     priv->tabs_set ||
397     priv->underline_set ||
398     priv->wrap_mode_set ||
399     priv->invisible_set;
400 }
401
402 gboolean
403 _gtk_text_tag_affects_nonsize_appearance (GtkTextTag *tag)
404 {
405   GtkTextTagPrivate *priv = tag->priv;
406
407   return
408     priv->bg_color_set ||
409     priv->fg_color_set ||
410     priv->strikethrough_set ||
411     priv->bg_full_height_set ||
412     priv->pg_bg_color_set;
413 }