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#include "gtktexttagprivate.h"
54
55/**
56 * gtk_text_attributes_new:
57 *
58 * Creates a `GtkTextAttributes`, which describes
59 * a set of properties on some text.
60 *
61 * Returns: a new `GtkTextAttributes`,
62 * free with gtk_text_attributes_unref().
63 */
64GtkTextAttributes*
65gtk_text_attributes_new (void)
66{
67 GtkTextAttributes *values;
68
69 values = g_slice_new0 (GtkTextAttributes);
70
71 /* 0 is a valid value for most of the struct */
72 values->refcount = 1;
73
74 values->language = gtk_get_default_language ();
75
76 values->font_scale = 1.0;
77
78 values->editable = TRUE;
79
80 return values;
81}
82
83/**
84 * gtk_text_attributes_copy:
85 * @src: a `GtkTextAttributes` to be copied
86 *
87 * Copies @src and returns a new `GtkTextAttributes`.
88 *
89 * Returns: a copy of @src,
90 * free with gtk_text_attributes_unref()
91 */
92GtkTextAttributes*
93gtk_text_attributes_copy (GtkTextAttributes *src)
94{
95 GtkTextAttributes *dest;
96
97 dest = gtk_text_attributes_new ();
98 gtk_text_attributes_copy_values (src, dest);
99
100 return dest;
101}
102
103/**
104 * gtk_text_attributes_copy_values:
105 * @src: a `GtkTextAttributes`
106 * @dest: another `GtkTextAttributes`
107 *
108 * Copies the values from @src to @dest so that @dest has
109 * the same values as @src. Frees existing values in @dest.
110 */
111void
112gtk_text_attributes_copy_values (GtkTextAttributes *src,
113 GtkTextAttributes *dest)
114{
115 guint orig_refcount;
116
117 if (src == dest)
118 return;
119
120 /* Remove refs */
121 if (dest->tabs)
122 pango_tab_array_free (tab_array: dest->tabs);
123
124 if (dest->font)
125 pango_font_description_free (desc: dest->font);
126
127 if (dest->pg_bg_rgba)
128 gdk_rgba_free (rgba: dest->pg_bg_rgba);
129
130 if (dest->appearance.fg_rgba)
131 gdk_rgba_free (rgba: dest->appearance.fg_rgba);
132
133 if (dest->appearance.bg_rgba)
134 gdk_rgba_free (rgba: dest->appearance.bg_rgba);
135
136 if (dest->appearance.underline_rgba)
137 gdk_rgba_free (rgba: dest->appearance.underline_rgba);
138
139 if (dest->appearance.overline_rgba)
140 gdk_rgba_free (rgba: dest->appearance.overline_rgba);
141
142 if (dest->appearance.strikethrough_rgba)
143 gdk_rgba_free (rgba: dest->appearance.strikethrough_rgba);
144
145 if (dest->font_features)
146 g_free (mem: dest->font_features);
147
148 /* Copy */
149 orig_refcount = dest->refcount;
150
151 *dest = *src;
152
153 if (src->tabs)
154 dest->tabs = pango_tab_array_copy (src: src->tabs);
155
156 dest->language = src->language;
157
158 if (src->font)
159 dest->font = pango_font_description_copy (desc: src->font);
160
161 if (src->pg_bg_rgba)
162 dest->pg_bg_rgba = gdk_rgba_copy (rgba: src->pg_bg_rgba);
163
164 if (src->appearance.fg_rgba)
165 dest->appearance.fg_rgba = gdk_rgba_copy (rgba: src->appearance.fg_rgba);
166
167 if (src->appearance.bg_rgba)
168 dest->appearance.bg_rgba = gdk_rgba_copy (rgba: src->appearance.bg_rgba);
169
170 if (src->appearance.underline_rgba)
171 dest->appearance.underline_rgba = gdk_rgba_copy (rgba: src->appearance.underline_rgba);
172
173 if (src->appearance.overline_rgba)
174 dest->appearance.overline_rgba = gdk_rgba_copy (rgba: src->appearance.overline_rgba);
175
176 if (src->appearance.strikethrough_rgba)
177 dest->appearance.strikethrough_rgba = gdk_rgba_copy (rgba: src->appearance.strikethrough_rgba);
178
179 if (src->font_features)
180 dest->font_features = g_strdup (str: src->font_features);
181
182 dest->refcount = orig_refcount;
183}
184
185/**
186 * gtk_text_attributes_ref:
187 * @values: a `GtkTextAttributes`
188 *
189 * Increments the reference count on @values.
190 *
191 * Returns: the `GtkTextAttributes` that were passed in
192 **/
193GtkTextAttributes *
194gtk_text_attributes_ref (GtkTextAttributes *values)
195{
196 g_return_val_if_fail (values != NULL, NULL);
197
198 values->refcount += 1;
199
200 return values;
201}
202
203/**
204 * gtk_text_attributes_unref:
205 * @values: a `GtkTextAttributes`
206 *
207 * Decrements the reference count on @values, freeing the structure
208 * if the reference count reaches 0.
209 **/
210void
211gtk_text_attributes_unref (GtkTextAttributes *values)
212{
213 g_return_if_fail (values != NULL);
214 g_return_if_fail (values->refcount > 0);
215
216 values->refcount -= 1;
217
218 if (values->refcount == 0)
219 {
220 if (values->tabs)
221 pango_tab_array_free (tab_array: values->tabs);
222
223 if (values->font)
224 pango_font_description_free (desc: values->font);
225
226 if (values->pg_bg_rgba)
227 gdk_rgba_free (rgba: values->pg_bg_rgba);
228
229 if (values->appearance.fg_rgba)
230 gdk_rgba_free (rgba: values->appearance.fg_rgba);
231
232 if (values->appearance.bg_rgba)
233 gdk_rgba_free (rgba: values->appearance.bg_rgba);
234
235 if (values->appearance.underline_rgba)
236 gdk_rgba_free (rgba: values->appearance.underline_rgba);
237
238 if (values->appearance.overline_rgba)
239 gdk_rgba_free (rgba: values->appearance.underline_rgba);
240
241 if (values->appearance.strikethrough_rgba)
242 gdk_rgba_free (rgba: values->appearance.strikethrough_rgba);
243
244 if (values->font_features)
245 g_free (mem: values->font_features);
246
247 g_slice_free (GtkTextAttributes, values);
248 }
249}
250
251void
252_gtk_text_attributes_fill_from_tags (GtkTextAttributes *dest,
253 GPtrArray *tags)
254{
255 guint left_margin_accumulative = 0;
256 guint right_margin_accumulative = 0;
257
258 for (guint n = 0; n < tags->len; n++)
259 {
260 GtkTextTag *tag = g_ptr_array_index (tags, n);
261 GtkTextAttributes *vals = tag->priv->values;
262
263 g_assert (tag->priv->table != NULL);
264 if (n > 0)
265 g_assert (((GtkTextTag*)g_ptr_array_index (tags, n))->priv->priority > ((GtkTextTag *)g_ptr_array_index (tags, n - 1))->priv->priority);
266
267 if (tag->priv->bg_color_set)
268 {
269 if (dest->appearance.bg_rgba)
270 {
271 gdk_rgba_free (rgba: dest->appearance.bg_rgba);
272 dest->appearance.bg_rgba = NULL;
273 }
274
275 if (vals->appearance.bg_rgba)
276 dest->appearance.bg_rgba = gdk_rgba_copy (rgba: vals->appearance.bg_rgba);
277
278 dest->appearance.draw_bg = TRUE;
279 }
280
281 if (tag->priv->fg_color_set)
282 {
283 if (dest->appearance.fg_rgba)
284 {
285 gdk_rgba_free (rgba: dest->appearance.fg_rgba);
286 dest->appearance.fg_rgba = NULL;
287 }
288
289 if (vals->appearance.fg_rgba)
290 dest->appearance.fg_rgba = gdk_rgba_copy (rgba: vals->appearance.fg_rgba);
291 }
292
293 if (tag->priv->underline_rgba_set)
294 {
295 if (dest->appearance.underline_rgba)
296 {
297 gdk_rgba_free (rgba: dest->appearance.underline_rgba);
298 dest->appearance.underline_rgba = NULL;
299 }
300
301 if (vals->appearance.underline_rgba)
302 dest->appearance.underline_rgba = gdk_rgba_copy (rgba: vals->appearance.underline_rgba);
303 }
304
305 if (tag->priv->overline_rgba_set)
306 {
307 if (dest->appearance.overline_rgba)
308 {
309 gdk_rgba_free (rgba: dest->appearance.overline_rgba);
310 dest->appearance.overline_rgba = NULL;
311 }
312
313 if (vals->appearance.overline_rgba)
314 dest->appearance.overline_rgba = gdk_rgba_copy (rgba: vals->appearance.overline_rgba);
315 }
316
317 if (tag->priv->strikethrough_rgba_set)
318 {
319 if (dest->appearance.strikethrough_rgba)
320 {
321 gdk_rgba_free (rgba: dest->appearance.strikethrough_rgba);
322 dest->appearance.strikethrough_rgba = NULL;
323 }
324
325 if (vals->appearance.strikethrough_rgba)
326 dest->appearance.strikethrough_rgba = gdk_rgba_copy (rgba: vals->appearance.strikethrough_rgba);
327 }
328
329 if (tag->priv->pg_bg_color_set)
330 {
331 if (dest->pg_bg_rgba)
332 {
333 gdk_rgba_free (rgba: dest->pg_bg_rgba);
334 dest->pg_bg_rgba = NULL;
335 }
336
337 if (vals->pg_bg_rgba)
338 dest->pg_bg_rgba = gdk_rgba_copy (rgba: vals->pg_bg_rgba);
339 }
340
341 if (vals->font)
342 {
343 if (dest->font)
344 pango_font_description_merge (desc: dest->font, desc_to_merge: vals->font, TRUE);
345 else
346 dest->font = pango_font_description_copy (desc: vals->font);
347 }
348
349 /* multiply all the scales together to get a composite */
350 if (tag->priv->scale_set)
351 dest->font_scale *= vals->font_scale;
352
353 if (tag->priv->justification_set)
354 dest->justification = vals->justification;
355
356 if (vals->direction != GTK_TEXT_DIR_NONE)
357 dest->direction = vals->direction;
358
359 if (tag->priv->left_margin_set)
360 {
361 if (tag->priv->accumulative_margin)
362 left_margin_accumulative += vals->left_margin;
363 else
364 dest->left_margin = vals->left_margin;
365 }
366
367 if (tag->priv->indent_set)
368 dest->indent = vals->indent;
369
370 if (tag->priv->rise_set)
371 dest->appearance.rise = vals->appearance.rise;
372
373 if (tag->priv->right_margin_set)
374 {
375 if (tag->priv->accumulative_margin)
376 right_margin_accumulative += vals->right_margin;
377 else
378 dest->right_margin = vals->right_margin;
379 }
380
381 if (tag->priv->pixels_above_lines_set)
382 dest->pixels_above_lines = vals->pixels_above_lines;
383
384 if (tag->priv->pixels_below_lines_set)
385 dest->pixels_below_lines = vals->pixels_below_lines;
386
387 if (tag->priv->pixels_inside_wrap_set)
388 dest->pixels_inside_wrap = vals->pixels_inside_wrap;
389
390 if (tag->priv->line_height_set)
391 dest->line_height = vals->line_height;
392
393 if (tag->priv->tabs_set)
394 {
395 if (dest->tabs)
396 pango_tab_array_free (tab_array: dest->tabs);
397 dest->tabs = pango_tab_array_copy (src: vals->tabs);
398 }
399
400 if (tag->priv->wrap_mode_set)
401 dest->wrap_mode = vals->wrap_mode;
402
403 if (tag->priv->underline_set)
404 dest->appearance.underline = vals->appearance.underline;
405
406 if (tag->priv->overline_set)
407 dest->appearance.overline = vals->appearance.overline;
408
409 if (tag->priv->strikethrough_set)
410 dest->appearance.strikethrough = vals->appearance.strikethrough;
411
412 if (tag->priv->invisible_set)
413 dest->invisible = vals->invisible;
414
415 if (tag->priv->editable_set)
416 dest->editable = vals->editable;
417
418 if (tag->priv->bg_full_height_set)
419 dest->bg_full_height = vals->bg_full_height;
420
421 if (tag->priv->language_set)
422 dest->language = vals->language;
423
424 if (tag->priv->fallback_set)
425 dest->no_fallback = vals->no_fallback;
426
427 if (tag->priv->letter_spacing_set)
428 dest->letter_spacing = vals->letter_spacing;
429
430 if (tag->priv->font_features_set)
431 dest->font_features = g_strdup (str: vals->font_features);
432
433 if (tag->priv->allow_breaks_set)
434 dest->no_breaks = vals->no_breaks;
435
436 if (tag->priv->show_spaces_set)
437 dest->show_spaces = vals->show_spaces;
438
439 if (tag->priv->insert_hyphens_set)
440 dest->no_hyphens = vals->no_hyphens;
441
442 if (tag->priv->text_transform_set)
443 dest->text_transform = vals->text_transform;
444
445 if (tag->priv->word_set)
446 dest->word = vals->word;
447
448 if (tag->priv->sentence_set)
449 dest->sentence = vals->sentence;
450 }
451
452 dest->left_margin += left_margin_accumulative;
453 dest->right_margin += right_margin_accumulative;
454}
455
456gboolean
457_gtk_text_tag_affects_size (GtkTextTag *tag)
458{
459 GtkTextTagPrivate *priv = tag->priv;
460
461 return
462 (priv->values->font && pango_font_description_get_set_fields (desc: priv->values->font) != 0) ||
463 priv->scale_set ||
464 priv->justification_set ||
465 priv->left_margin_set ||
466 priv->indent_set ||
467 priv->rise_set ||
468 priv->right_margin_set ||
469 priv->pixels_above_lines_set ||
470 priv->pixels_below_lines_set ||
471 priv->pixels_inside_wrap_set ||
472 priv->line_height_set ||
473 priv->tabs_set ||
474 priv->underline_set ||
475 priv->overline_set ||
476 priv->wrap_mode_set ||
477 priv->invisible_set ||
478 priv->font_features_set ||
479 priv->letter_spacing_set ||
480 priv->text_transform_set;
481}
482
483gboolean
484_gtk_text_tag_affects_nonsize_appearance (GtkTextTag *tag)
485{
486 GtkTextTagPrivate *priv = tag->priv;
487
488 return
489 priv->bg_color_set ||
490 priv->fg_color_set ||
491 priv->strikethrough_set ||
492 priv->bg_full_height_set ||
493 priv->pg_bg_color_set ||
494 priv->fallback_set ||
495 priv->underline_rgba_set ||
496 priv->overline_rgba_set ||
497 priv->strikethrough_rgba_set ||
498 priv->show_spaces_set;
499}
500

source code of gtk/gtk/gtktextattributes.c