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 /**
51 * SECTION:gtktexttag
52 * @Title: GtkTextTag
53 * @Short_description: A tag that can be applied to text in a GtkTextBuffer
54 *
55 * You may wish to begin by reading the
56 * [text widget conceptual overview][TextWidget]
57 * which gives an overview of all the objects and
58 * data types related to the text widget and how they work together.
59 *
60 * Tags should be in the #GtkTextTagTable for a given #GtkTextBuffer
61 * before using them with that buffer.
62 *
63 * gtk_text_buffer_create_tag() is the best way to create tags.
64 * See “gtk3-demo” for numerous examples.
65 *
66 * For each property of #GtkTextTag, there is a “set” property, e.g.
67 * “font-set” corresponds to “font”. These “set” properties reflect
68 * whether a property has been set or not.
69 * They are maintained by GTK+ and you should not set them independently.
70 */
71
72 #include "config.h"
73
74 #include <stdlib.h>
75 #include <string.h>
76
77 #include "gtktextattributesprivate.h"
78 #include "gtktexttag.h"
79 #include "gtktexttypes.h"
80 #include "gtktexttagtable.h"
81 #include "gtktexttagtableprivate.h"
82 #include "gtkintl.h"
83 #include "gtkmarshalers.h"
84 #include "gtkprivate.h"
85 #include "gtktypebuiltins.h"
86
87 enum {
88 EVENT,
89 LAST_SIGNAL
90 };
91
92 enum {
93 PROP_0,
94 /* Construct args */
95 PROP_NAME,
96
97 /* Style args */
98 PROP_BACKGROUND,
99 PROP_FOREGROUND,
100 PROP_BACKGROUND_GDK,
101 PROP_FOREGROUND_GDK,
102 PROP_BACKGROUND_RGBA,
103 PROP_FOREGROUND_RGBA,
104 PROP_FONT,
105 PROP_FONT_DESC,
106 PROP_FAMILY,
107 PROP_STYLE,
108 PROP_VARIANT,
109 PROP_WEIGHT,
110 PROP_STRETCH,
111 PROP_SIZE,
112 PROP_SIZE_POINTS,
113 PROP_SCALE,
114 PROP_PIXELS_ABOVE_LINES,
115 PROP_PIXELS_BELOW_LINES,
116 PROP_PIXELS_INSIDE_WRAP,
117 PROP_EDITABLE,
118 PROP_WRAP_MODE,
119 PROP_JUSTIFICATION,
120 PROP_DIRECTION,
121 PROP_LEFT_MARGIN,
122 PROP_INDENT,
123 PROP_STRIKETHROUGH,
124 PROP_STRIKETHROUGH_RGBA,
125 PROP_RIGHT_MARGIN,
126 PROP_UNDERLINE,
127 PROP_UNDERLINE_RGBA,
128 PROP_RISE,
129 PROP_BACKGROUND_FULL_HEIGHT,
130 PROP_LANGUAGE,
131 PROP_TABS,
132 PROP_INVISIBLE,
133 PROP_PARAGRAPH_BACKGROUND,
134 PROP_PARAGRAPH_BACKGROUND_GDK,
135 PROP_PARAGRAPH_BACKGROUND_RGBA,
136 PROP_FALLBACK,
137 PROP_LETTER_SPACING,
138 PROP_FONT_FEATURES,
139
140 /* Behavior args */
141 PROP_ACCUMULATIVE_MARGIN,
142
143 /* Whether-a-style-arg-is-set args */
144 PROP_BACKGROUND_SET,
145 PROP_FOREGROUND_SET,
146 PROP_FAMILY_SET,
147 PROP_STYLE_SET,
148 PROP_VARIANT_SET,
149 PROP_WEIGHT_SET,
150 PROP_STRETCH_SET,
151 PROP_SIZE_SET,
152 PROP_SCALE_SET,
153 PROP_PIXELS_ABOVE_LINES_SET,
154 PROP_PIXELS_BELOW_LINES_SET,
155 PROP_PIXELS_INSIDE_WRAP_SET,
156 PROP_EDITABLE_SET,
157 PROP_WRAP_MODE_SET,
158 PROP_JUSTIFICATION_SET,
159 PROP_LEFT_MARGIN_SET,
160 PROP_INDENT_SET,
161 PROP_STRIKETHROUGH_SET,
162 PROP_STRIKETHROUGH_RGBA_SET,
163 PROP_RIGHT_MARGIN_SET,
164 PROP_UNDERLINE_SET,
165 PROP_UNDERLINE_RGBA_SET,
166 PROP_RISE_SET,
167 PROP_BACKGROUND_FULL_HEIGHT_SET,
168 PROP_LANGUAGE_SET,
169 PROP_TABS_SET,
170 PROP_INVISIBLE_SET,
171 PROP_PARAGRAPH_BACKGROUND_SET,
172 PROP_FALLBACK_SET,
173 PROP_LETTER_SPACING_SET,
174 PROP_FONT_FEATURES_SET,
175
176 LAST_ARG
177 };
178 static void gtk_text_tag_finalize (GObject *object);
179 static void gtk_text_tag_set_property (GObject *object,
180 guint prop_id,
181 const GValue *value,
182 GParamSpec *pspec);
183 static void gtk_text_tag_get_property (GObject *object,
184 guint prop_id,
185 GValue *value,
186 GParamSpec *pspec);
187
188 static guint signals[LAST_SIGNAL] = { 0 };
189
G_DEFINE_TYPE_WITH_PRIVATE(GtkTextTag,gtk_text_tag,G_TYPE_OBJECT)190 G_DEFINE_TYPE_WITH_PRIVATE (GtkTextTag, gtk_text_tag, G_TYPE_OBJECT)
191
192 static void
193 gtk_text_tag_class_init (GtkTextTagClass *klass)
194 {
195 GObjectClass *object_class = G_OBJECT_CLASS (klass);
196
197 object_class->set_property = gtk_text_tag_set_property;
198 object_class->get_property = gtk_text_tag_get_property;
199
200 object_class->finalize = gtk_text_tag_finalize;
201
202 /* Construct */
203 g_object_class_install_property (object_class,
204 PROP_NAME,
205 g_param_spec_string ("name",
206 P_("Tag name"),
207 P_("Name used to refer to the text tag. NULL for anonymous tags"),
208 NULL,
209 GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
210
211 /* Style args */
212
213 g_object_class_install_property (object_class,
214 PROP_BACKGROUND,
215 g_param_spec_string ("background",
216 P_("Background color name"),
217 P_("Background color as a string"),
218 NULL,
219 GTK_PARAM_WRITABLE));
220
221 /**
222 * GtkTextTag:background-gdk:
223 *
224 * Background color as a #GdkColor.
225 *
226 * Deprecated: 3.4: Use #GtkTextTag:background-rgba instead.
227 */
228 g_object_class_install_property (object_class,
229 PROP_BACKGROUND_GDK,
230 g_param_spec_boxed ("background-gdk",
231 P_("Background color"),
232 P_("Background color as a GdkColor"),
233 g_type_from_name ("GdkColor"),
234 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED));
235
236 /**
237 * GtkTextTag:background-rgba:
238 *
239 * Background color as a #GdkRGBA.
240 *
241 * Since: 3.2
242 */
243 g_object_class_install_property (object_class,
244 PROP_BACKGROUND_RGBA,
245 g_param_spec_boxed ("background-rgba",
246 P_("Background RGBA"),
247 P_("Background color as a GdkRGBA"),
248 GDK_TYPE_RGBA,
249 GTK_PARAM_READWRITE));
250
251 g_object_class_install_property (object_class,
252 PROP_BACKGROUND_FULL_HEIGHT,
253 g_param_spec_boolean ("background-full-height",
254 P_("Background full height"),
255 P_("Whether the background color fills the entire line height or only the height of the tagged characters"),
256 FALSE,
257 GTK_PARAM_READWRITE));
258
259 g_object_class_install_property (object_class,
260 PROP_FOREGROUND,
261 g_param_spec_string ("foreground",
262 P_("Foreground color name"),
263 P_("Foreground color as a string"),
264 NULL,
265 GTK_PARAM_WRITABLE));
266
267 /**
268 * GtkTextTag:foreground-gdk:
269 *
270 * Foreground color as a #GdkColor.
271 *
272 * Deprecated: 3.4: Use #GtkTextTag:foreground-rgba instead.
273 */
274 g_object_class_install_property (object_class,
275 PROP_FOREGROUND_GDK,
276 g_param_spec_boxed ("foreground-gdk",
277 P_("Foreground color"),
278 P_("Foreground color as a GdkColor"),
279 g_type_from_name ("GdkColor"),
280 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED));
281
282 /**
283 * GtkTextTag:foreground-rgba:
284 *
285 * Foreground color as a #GdkRGBA.
286 *
287 * Since: 3.2
288 */
289 g_object_class_install_property (object_class,
290 PROP_FOREGROUND_RGBA,
291 g_param_spec_boxed ("foreground-rgba",
292 P_("Foreground RGBA"),
293 P_("Foreground color as a GdkRGBA"),
294 GDK_TYPE_RGBA,
295 GTK_PARAM_READWRITE));
296
297 g_object_class_install_property (object_class,
298 PROP_DIRECTION,
299 g_param_spec_enum ("direction",
300 P_("Text direction"),
301 P_("Text direction, e.g. right-to-left or left-to-right"),
302 GTK_TYPE_TEXT_DIRECTION,
303 GTK_TEXT_DIR_NONE,
304 GTK_PARAM_READWRITE));
305
306 g_object_class_install_property (object_class,
307 PROP_EDITABLE,
308 g_param_spec_boolean ("editable",
309 P_("Editable"),
310 P_("Whether the text can be modified by the user"),
311 TRUE,
312 GTK_PARAM_READWRITE));
313
314 /**
315 * GtkTextTag:font:
316 *
317 * Font description as string, e.g. \"Sans Italic 12\".
318 *
319 * Note that the initial value of this property depends on
320 * the internals of #PangoFontDescription.
321 */
322 g_object_class_install_property (object_class,
323 PROP_FONT,
324 g_param_spec_string ("font",
325 P_("Font"),
326 P_("Font description as a string, e.g. \"Sans Italic 12\""),
327 NULL,
328 GTK_PARAM_READWRITE));
329
330 g_object_class_install_property (object_class,
331 PROP_FONT_DESC,
332 g_param_spec_boxed ("font-desc",
333 P_("Font"),
334 P_("Font description as a PangoFontDescription struct"),
335 PANGO_TYPE_FONT_DESCRIPTION,
336 GTK_PARAM_READWRITE));
337
338 g_object_class_install_property (object_class,
339 PROP_FAMILY,
340 g_param_spec_string ("family",
341 P_("Font family"),
342 P_("Name of the font family, e.g. Sans, Helvetica, Times, Monospace"),
343 NULL,
344 GTK_PARAM_READWRITE));
345
346 g_object_class_install_property (object_class,
347 PROP_STYLE,
348 g_param_spec_enum ("style",
349 P_("Font style"),
350 P_("Font style as a PangoStyle, e.g. PANGO_STYLE_ITALIC"),
351 PANGO_TYPE_STYLE,
352 PANGO_STYLE_NORMAL,
353 GTK_PARAM_READWRITE));
354
355 g_object_class_install_property (object_class,
356 PROP_VARIANT,
357 g_param_spec_enum ("variant",
358 P_("Font variant"),
359 P_("Font variant as a PangoVariant, e.g. PANGO_VARIANT_SMALL_CAPS"),
360 PANGO_TYPE_VARIANT,
361 PANGO_VARIANT_NORMAL,
362 GTK_PARAM_READWRITE));
363
364 g_object_class_install_property (object_class,
365 PROP_WEIGHT,
366 g_param_spec_int ("weight",
367 P_("Font weight"),
368 P_("Font weight as an integer, see predefined values in PangoWeight; for example, PANGO_WEIGHT_BOLD"),
369 0,
370 G_MAXINT,
371 PANGO_WEIGHT_NORMAL,
372 GTK_PARAM_READWRITE));
373
374
375 g_object_class_install_property (object_class,
376 PROP_STRETCH,
377 g_param_spec_enum ("stretch",
378 P_("Font stretch"),
379 P_("Font stretch as a PangoStretch, e.g. PANGO_STRETCH_CONDENSED"),
380 PANGO_TYPE_STRETCH,
381 PANGO_STRETCH_NORMAL,
382 GTK_PARAM_READWRITE));
383
384 g_object_class_install_property (object_class,
385 PROP_SIZE,
386 g_param_spec_int ("size",
387 P_("Font size"),
388 P_("Font size in Pango units"),
389 0,
390 G_MAXINT,
391 0,
392 GTK_PARAM_READWRITE));
393
394 g_object_class_install_property (object_class,
395 PROP_SCALE,
396 g_param_spec_double ("scale",
397 P_("Font scale"),
398 P_("Font size as a scale factor relative to the default font size. This properly adapts to theme changes etc. so is recommended. Pango predefines some scales such as PANGO_SCALE_X_LARGE"),
399 0.0,
400 G_MAXDOUBLE,
401 1.0,
402 GTK_PARAM_READWRITE));
403
404 g_object_class_install_property (object_class,
405 PROP_SIZE_POINTS,
406 g_param_spec_double ("size-points",
407 P_("Font points"),
408 P_("Font size in points"),
409 0.0,
410 G_MAXDOUBLE,
411 0.0,
412 GTK_PARAM_READWRITE));
413
414 g_object_class_install_property (object_class,
415 PROP_JUSTIFICATION,
416 g_param_spec_enum ("justification",
417 P_("Justification"),
418 P_("Left, right, or center justification"),
419 GTK_TYPE_JUSTIFICATION,
420 GTK_JUSTIFY_LEFT,
421 GTK_PARAM_READWRITE));
422
423 /**
424 * GtkTextTag:language:
425 *
426 * The language this text is in, as an ISO code. Pango can use this as a
427 * hint when rendering the text. If not set, an appropriate default will be
428 * used.
429 *
430 * Note that the initial value of this property depends on the current
431 * locale, see also gtk_get_default_language().
432 */
433 g_object_class_install_property (object_class,
434 PROP_LANGUAGE,
435 g_param_spec_string ("language",
436 P_("Language"),
437 P_("The language this text is in, as an ISO code. Pango can use this as a hint when rendering the text. If not set, an appropriate default will be used."),
438 NULL,
439 GTK_PARAM_READWRITE));
440
441 g_object_class_install_property (object_class,
442 PROP_LEFT_MARGIN,
443 g_param_spec_int ("left-margin",
444 P_("Left margin"),
445 P_("Width of the left margin in pixels"),
446 0,
447 G_MAXINT,
448 0,
449 GTK_PARAM_READWRITE));
450
451 g_object_class_install_property (object_class,
452 PROP_RIGHT_MARGIN,
453 g_param_spec_int ("right-margin",
454 P_("Right margin"),
455 P_("Width of the right margin in pixels"),
456 0,
457 G_MAXINT,
458 0,
459 GTK_PARAM_READWRITE));
460
461
462 g_object_class_install_property (object_class,
463 PROP_INDENT,
464 g_param_spec_int ("indent",
465 P_("Indent"),
466 P_("Amount to indent the paragraph, in pixels"),
467 G_MININT,
468 G_MAXINT,
469 0,
470 GTK_PARAM_READWRITE));
471
472
473 g_object_class_install_property (object_class,
474 PROP_RISE,
475 g_param_spec_int ("rise",
476 P_("Rise"),
477 P_("Offset of text above the baseline (below the baseline if rise is negative) in Pango units"),
478 G_MININT,
479 G_MAXINT,
480 0,
481 GTK_PARAM_READWRITE));
482
483 g_object_class_install_property (object_class,
484 PROP_PIXELS_ABOVE_LINES,
485 g_param_spec_int ("pixels-above-lines",
486 P_("Pixels above lines"),
487 P_("Pixels of blank space above paragraphs"),
488 0,
489 G_MAXINT,
490 0,
491 GTK_PARAM_READWRITE));
492
493 g_object_class_install_property (object_class,
494 PROP_PIXELS_BELOW_LINES,
495 g_param_spec_int ("pixels-below-lines",
496 P_("Pixels below lines"),
497 P_("Pixels of blank space below paragraphs"),
498 0,
499 G_MAXINT,
500 0,
501 GTK_PARAM_READWRITE));
502
503 g_object_class_install_property (object_class,
504 PROP_PIXELS_INSIDE_WRAP,
505 g_param_spec_int ("pixels-inside-wrap",
506 P_("Pixels inside wrap"),
507 P_("Pixels of blank space between wrapped lines in a paragraph"),
508 0,
509 G_MAXINT,
510 0,
511 GTK_PARAM_READWRITE));
512
513 g_object_class_install_property (object_class,
514 PROP_STRIKETHROUGH,
515 g_param_spec_boolean ("strikethrough",
516 P_("Strikethrough"),
517 P_("Whether to strike through the text"),
518 FALSE,
519 GTK_PARAM_READWRITE));
520
521 g_object_class_install_property (object_class,
522 PROP_UNDERLINE,
523 g_param_spec_enum ("underline",
524 P_("Underline"),
525 P_("Style of underline for this text"),
526 PANGO_TYPE_UNDERLINE,
527 PANGO_UNDERLINE_NONE,
528 GTK_PARAM_READWRITE));
529
530 /**
531 * GtkTextTag:underline-rgba:
532 *
533 * This property modifies the color of underlines. If not set, underlines
534 * will use the forground color.
535 *
536 * If #GtkTextTag:underline is set to %PANGO_UNDERLINE_ERROR, an alternate
537 * color may be applied instead of the foreground. Setting this property
538 * will always override those defaults.
539 *
540 * Since: 3.16
541 */
542 g_object_class_install_property (object_class,
543 PROP_UNDERLINE_RGBA,
544 g_param_spec_boxed ("underline-rgba",
545 P_("Underline RGBA"),
546 P_("Color of underline for this text"),
547 GDK_TYPE_RGBA,
548 GTK_PARAM_READWRITE));
549
550 /**
551 * GtkTextTag:strikethrough-rgba:
552 *
553 * This property modifies the color of strikeouts. If not set, strikeouts
554 * will use the forground color.
555 *
556 * Since: 3.16
557 */
558 g_object_class_install_property (object_class,
559 PROP_STRIKETHROUGH_RGBA,
560 g_param_spec_boxed ("strikethrough-rgba",
561 P_("Strikethrough RGBA"),
562 P_("Color of strikethrough for this text"),
563 GDK_TYPE_RGBA,
564 GTK_PARAM_READWRITE));
565
566 g_object_class_install_property (object_class,
567 PROP_WRAP_MODE,
568 g_param_spec_enum ("wrap-mode",
569 P_("Wrap mode"),
570 P_("Whether to wrap lines never, at word boundaries, or at character boundaries"),
571 GTK_TYPE_WRAP_MODE,
572 GTK_WRAP_NONE,
573 GTK_PARAM_READWRITE));
574
575
576 g_object_class_install_property (object_class,
577 PROP_TABS,
578 g_param_spec_boxed ("tabs",
579 P_("Tabs"),
580 P_("Custom tabs for this text"),
581 PANGO_TYPE_TAB_ARRAY,
582 GTK_PARAM_READWRITE));
583
584 /**
585 * GtkTextTag:invisible:
586 *
587 * Whether this text is hidden.
588 *
589 * Note that there may still be problems with the support for invisible
590 * text, in particular when navigating programmatically inside a buffer
591 * containing invisible segments.
592 *
593 * Since: 2.8
594 */
595 g_object_class_install_property (object_class,
596 PROP_INVISIBLE,
597 g_param_spec_boolean ("invisible",
598 P_("Invisible"),
599 P_("Whether this text is hidden."),
600 FALSE,
601 GTK_PARAM_READWRITE));
602
603 /**
604 * GtkTextTag:paragraph-background:
605 *
606 * The paragraph background color as a string.
607 *
608 * Since: 2.8
609 */
610 g_object_class_install_property (object_class,
611 PROP_PARAGRAPH_BACKGROUND,
612 g_param_spec_string ("paragraph-background",
613 P_("Paragraph background color name"),
614 P_("Paragraph background color as a string"),
615 NULL,
616 GTK_PARAM_WRITABLE));
617
618 /**
619 * GtkTextTag:paragraph-background-gdk:
620 *
621 * The paragraph background color as a #GdkColor.
622 *
623 * Since: 2.8
624 *
625 * Deprecated: 3.4: Use #GtkTextTag:paragraph-background-rgba instead.
626 */
627 g_object_class_install_property (object_class,
628 PROP_PARAGRAPH_BACKGROUND_GDK,
629 g_param_spec_boxed ("paragraph-background-gdk",
630 P_("Paragraph background color"),
631 P_("Paragraph background color as a GdkColor"),
632 g_type_from_name ("GdkColor"),
633 GTK_PARAM_READWRITE | G_PARAM_DEPRECATED));
634
635 /**
636 * GtkTextTag:paragraph-background-rgba:
637 *
638 * The paragraph background color as a #GdkRGBA.
639 *
640 * Since: 3.2
641 */
642 g_object_class_install_property (object_class,
643 PROP_PARAGRAPH_BACKGROUND_RGBA,
644 g_param_spec_boxed ("paragraph-background-rgba",
645 P_("Paragraph background RGBA"),
646 P_("Paragraph background RGBA as a GdkRGBA"),
647 GDK_TYPE_RGBA,
648 GTK_PARAM_READWRITE));
649
650 /**
651 * GtkTextTag:fallback:
652 *
653 * Whether font fallback is enabled.
654 *
655 * When set to %TRUE, other fonts will be substituted
656 * where the current font is missing glyphs.
657 *
658 * Since: 3.16
659 */
660 g_object_class_install_property (object_class,
661 PROP_FALLBACK,
662 g_param_spec_boolean ("fallback",
663 P_("Fallback"),
664 P_("Whether font fallback is enabled."),
665 TRUE,
666 GTK_PARAM_READWRITE));
667
668 /**
669 * GtkTextTag:letter-spacing:
670 *
671 * Extra spacing between graphemes, in Pango units.
672 *
673 * Since: 3.16
674 */
675 g_object_class_install_property (object_class,
676 PROP_LETTER_SPACING,
677 g_param_spec_int ("letter-spacing",
678 P_("Letter Spacing"),
679 P_("Extra spacing between graphemes"),
680 0, G_MAXINT, 0,
681 GTK_PARAM_READWRITE));
682
683 /**
684 * GtkTextTag:font-features:
685 *
686 * OpenType font features, as a string.
687 *
688 * Since: 3.18
689 */
690 g_object_class_install_property (object_class,
691 PROP_FONT_FEATURES,
692 g_param_spec_string ("font-features",
693 P_("Font Features"),
694 P_("OpenType Font Features to use"),
695 NULL,
696 GTK_PARAM_READWRITE));
697
698 /**
699 * GtkTextTag:accumulative-margin:
700 *
701 * Whether the margins accumulate or override each other.
702 *
703 * When set to %TRUE the margins of this tag are added to the margins
704 * of any other non-accumulative margins present. When set to %FALSE
705 * the margins override one another (the default).
706 *
707 * Since: 2.12
708 */
709 g_object_class_install_property (object_class,
710 PROP_ACCUMULATIVE_MARGIN,
711 g_param_spec_boolean ("accumulative-margin",
712 P_("Margin Accumulates"),
713 P_("Whether left and right margins accumulate."),
714 FALSE,
715 GTK_PARAM_READWRITE));
716
717 /* Style props are set or not */
718
719 #define ADD_SET_PROP(propname, propval, nick, blurb) g_object_class_install_property (object_class, propval, g_param_spec_boolean (propname, nick, blurb, FALSE, GTK_PARAM_READWRITE))
720
721 ADD_SET_PROP ("background-set", PROP_BACKGROUND_SET,
722 P_("Background set"),
723 P_("Whether this tag affects the background color"));
724
725 ADD_SET_PROP ("background-full-height-set", PROP_BACKGROUND_FULL_HEIGHT_SET,
726 P_("Background full height set"),
727 P_("Whether this tag affects background height"));
728
729 ADD_SET_PROP ("foreground-set", PROP_FOREGROUND_SET,
730 P_("Foreground set"),
731 P_("Whether this tag affects the foreground color"));
732
733 ADD_SET_PROP ("editable-set", PROP_EDITABLE_SET,
734 P_("Editability set"),
735 P_("Whether this tag affects text editability"));
736
737 ADD_SET_PROP ("family-set", PROP_FAMILY_SET,
738 P_("Font family set"),
739 P_("Whether this tag affects the font family"));
740
741 ADD_SET_PROP ("style-set", PROP_STYLE_SET,
742 P_("Font style set"),
743 P_("Whether this tag affects the font style"));
744
745 ADD_SET_PROP ("variant-set", PROP_VARIANT_SET,
746 P_("Font variant set"),
747 P_("Whether this tag affects the font variant"));
748
749 ADD_SET_PROP ("weight-set", PROP_WEIGHT_SET,
750 P_("Font weight set"),
751 P_("Whether this tag affects the font weight"));
752
753 ADD_SET_PROP ("stretch-set", PROP_STRETCH_SET,
754 P_("Font stretch set"),
755 P_("Whether this tag affects the font stretch"));
756
757 ADD_SET_PROP ("size-set", PROP_SIZE_SET,
758 P_("Font size set"),
759 P_("Whether this tag affects the font size"));
760
761 ADD_SET_PROP ("scale-set", PROP_SCALE_SET,
762 P_("Font scale set"),
763 P_("Whether this tag scales the font size by a factor"));
764
765 ADD_SET_PROP ("justification-set", PROP_JUSTIFICATION_SET,
766 P_("Justification set"),
767 P_("Whether this tag affects paragraph justification"));
768
769 ADD_SET_PROP ("language-set", PROP_LANGUAGE_SET,
770 P_("Language set"),
771 P_("Whether this tag affects the language the text is rendered as"));
772
773 ADD_SET_PROP ("left-margin-set", PROP_LEFT_MARGIN_SET,
774 P_("Left margin set"),
775 P_("Whether this tag affects the left margin"));
776
777 ADD_SET_PROP ("indent-set", PROP_INDENT_SET,
778 P_("Indent set"),
779 P_("Whether this tag affects indentation"));
780
781 ADD_SET_PROP ("rise-set", PROP_RISE_SET,
782 P_("Rise set"),
783 P_("Whether this tag affects the rise"));
784
785 ADD_SET_PROP ("pixels-above-lines-set", PROP_PIXELS_ABOVE_LINES_SET,
786 P_("Pixels above lines set"),
787 P_("Whether this tag affects the number of pixels above lines"));
788
789 ADD_SET_PROP ("pixels-below-lines-set", PROP_PIXELS_BELOW_LINES_SET,
790 P_("Pixels below lines set"),
791 P_("Whether this tag affects the number of pixels above lines"));
792
793 ADD_SET_PROP ("pixels-inside-wrap-set", PROP_PIXELS_INSIDE_WRAP_SET,
794 P_("Pixels inside wrap set"),
795 P_("Whether this tag affects the number of pixels between wrapped lines"));
796
797 ADD_SET_PROP ("strikethrough-set", PROP_STRIKETHROUGH_SET,
798 P_("Strikethrough set"),
799 P_("Whether this tag affects strikethrough"));
800
801 ADD_SET_PROP ("right-margin-set", PROP_RIGHT_MARGIN_SET,
802 P_("Right margin set"),
803 P_("Whether this tag affects the right margin"));
804
805 ADD_SET_PROP ("underline-set", PROP_UNDERLINE_SET,
806 P_("Underline set"),
807 P_("Whether this tag affects underlining"));
808
809 /**
810 * GtkTextTag:underline-rgba-set:
811 *
812 * If the #GtkTextTag:underline-rgba property has been set.
813 *
814 * Since: 3.16
815 */
816 ADD_SET_PROP ("underline-rgba-set", PROP_UNDERLINE_RGBA_SET,
817 P_("Underline RGBA set"),
818 P_("Whether this tag affects underlining color"));
819
820 /**
821 * GtkTextTag:strikethrough-rgba-set:
822 *
823 * If the #GtkTextTag:strikethrough-rgba property has been set.
824 *
825 * Since: 3.16
826 */
827 ADD_SET_PROP ("strikethrough-rgba-set", PROP_STRIKETHROUGH_RGBA_SET,
828 P_("Strikethrough RGBA set"),
829 P_("Whether this tag affects strikethrough color"));
830
831 ADD_SET_PROP ("wrap-mode-set", PROP_WRAP_MODE_SET,
832 P_("Wrap mode set"),
833 P_("Whether this tag affects line wrap mode"));
834
835 ADD_SET_PROP ("tabs-set", PROP_TABS_SET,
836 P_("Tabs set"),
837 P_("Whether this tag affects tabs"));
838
839 ADD_SET_PROP ("invisible-set", PROP_INVISIBLE_SET,
840 P_("Invisible set"),
841 P_("Whether this tag affects text visibility"));
842
843 ADD_SET_PROP ("paragraph-background-set", PROP_PARAGRAPH_BACKGROUND_SET,
844 P_("Paragraph background set"),
845 P_("Whether this tag affects the paragraph background color"));
846
847 ADD_SET_PROP ("fallback-set", PROP_FALLBACK_SET,
848 P_("Fallback set"),
849 P_("Whether this tag affects font fallback"));
850
851 ADD_SET_PROP ("letter-spacing-set", PROP_LETTER_SPACING_SET,
852 P_("Letter spacing set"),
853 P_("Whether this tag affects letter spacing"));
854
855 ADD_SET_PROP ("font-features-set", PROP_FONT_FEATURES_SET,
856 P_("Font features set"),
857 P_("Whether this tag affects font features"));
858
859 /**
860 * GtkTextTag::event:
861 * @tag: the #GtkTextTag on which the signal is emitted
862 * @object: the object the event was fired from (typically a #GtkTextView)
863 * @event: the event which triggered the signal
864 * @iter: a #GtkTextIter pointing at the location the event occurred
865 *
866 * The ::event signal is emitted when an event occurs on a region of the
867 * buffer marked with this tag.
868 *
869 * Returns: %TRUE to stop other handlers from being invoked for the
870 * event. %FALSE to propagate the event further.
871 */
872 signals[EVENT] =
873 g_signal_new (I_("event"),
874 G_OBJECT_CLASS_TYPE (object_class),
875 G_SIGNAL_RUN_LAST,
876 G_STRUCT_OFFSET (GtkTextTagClass, event),
877 _gtk_boolean_handled_accumulator, NULL,
878 _gtk_marshal_BOOLEAN__OBJECT_BOXED_BOXED,
879 G_TYPE_BOOLEAN,
880 3,
881 G_TYPE_OBJECT,
882 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE,
883 GTK_TYPE_TEXT_ITER);
884 g_signal_set_va_marshaller (signals[EVENT],
885 G_OBJECT_CLASS_TYPE (object_class),
886 _gtk_marshal_BOOLEAN__OBJECT_BOXED_BOXEDv);
887 }
888
889 static void
gtk_text_tag_init(GtkTextTag * text_tag)890 gtk_text_tag_init (GtkTextTag *text_tag)
891 {
892 text_tag->priv = gtk_text_tag_get_instance_private (text_tag);
893 text_tag->priv->values = gtk_text_attributes_new ();
894 }
895
896 /**
897 * gtk_text_tag_new:
898 * @name: (allow-none): tag name, or %NULL
899 *
900 * Creates a #GtkTextTag. Configure the tag using object arguments,
901 * i.e. using g_object_set().
902 *
903 * Returns: a new #GtkTextTag
904 **/
905 GtkTextTag*
gtk_text_tag_new(const gchar * name)906 gtk_text_tag_new (const gchar *name)
907 {
908 GtkTextTag *tag;
909
910 tag = g_object_new (GTK_TYPE_TEXT_TAG, "name", name, NULL);
911
912 return tag;
913 }
914
915 static void
gtk_text_tag_finalize(GObject * object)916 gtk_text_tag_finalize (GObject *object)
917 {
918 GtkTextTag *text_tag = GTK_TEXT_TAG (object);
919 GtkTextTagPrivate *priv = text_tag->priv;
920
921 if (priv->table)
922 gtk_text_tag_table_remove (priv->table, text_tag);
923
924 g_assert (priv->table == NULL);
925
926 gtk_text_attributes_unref (priv->values);
927 priv->values = NULL;
928
929 g_free (priv->name);
930 priv->name = NULL;
931
932 G_OBJECT_CLASS (gtk_text_tag_parent_class)->finalize (object);
933 }
934
935 static void
copy_rgba_to_gdk_color(GdkRGBA * src,GdkColor * dest)936 copy_rgba_to_gdk_color (GdkRGBA *src,
937 GdkColor *dest)
938 {
939 dest->red = CLAMP (src->red, 0.0, 1.0) * 65535.0;
940 dest->green = CLAMP (src->green, 0.0, 1.0) * 65535.0;
941 dest->blue = CLAMP (src->blue, 0.0, 1.0) * 65535.0;
942 }
943
944 static void
copy_gdk_color_to_rgba(GdkColor * src,GdkRGBA * dest)945 copy_gdk_color_to_rgba (GdkColor *src,
946 GdkRGBA *dest)
947 {
948 dest->red = src->red / 65535.;
949 dest->green = src->green / 65535.;
950 dest->blue = src->blue / 65535.;
951 dest->alpha = 1;
952 }
953
954 static void
set_underline_rgba(GtkTextTag * tag,const GdkRGBA * rgba)955 set_underline_rgba (GtkTextTag *tag,
956 const GdkRGBA *rgba)
957 {
958 GtkTextTagPrivate *priv = tag->priv;
959
960 if (rgba)
961 {
962 GTK_TEXT_APPEARANCE_SET_UNDERLINE_RGBA (&priv->values->appearance, rgba);
963
964 if (!GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA_SET (&priv->values->appearance))
965 {
966 GTK_TEXT_APPEARANCE_SET_UNDERLINE_RGBA_SET (&priv->values->appearance, TRUE);
967 g_object_notify (G_OBJECT (tag), "underline-rgba-set");
968 }
969 }
970 else
971 {
972 GdkRGBA black = { 0 };
973
974 GTK_TEXT_APPEARANCE_SET_UNDERLINE_RGBA (&priv->values->appearance, &black);
975
976 if (GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA_SET (&priv->values->appearance))
977 {
978 GTK_TEXT_APPEARANCE_SET_UNDERLINE_RGBA_SET (&priv->values->appearance, FALSE);
979 g_object_notify (G_OBJECT (tag), "underline-rgba-set");
980 }
981 }
982 }
983
984 static void
set_strikethrough_rgba(GtkTextTag * tag,const GdkRGBA * rgba)985 set_strikethrough_rgba (GtkTextTag *tag,
986 const GdkRGBA *rgba)
987 {
988 GtkTextTagPrivate *priv = tag->priv;
989
990 if (rgba)
991 {
992 GTK_TEXT_APPEARANCE_SET_STRIKETHROUGH_RGBA (&priv->values->appearance, rgba);
993
994 if (!GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA_SET (&priv->values->appearance))
995 {
996 GTK_TEXT_APPEARANCE_SET_STRIKETHROUGH_RGBA_SET (&priv->values->appearance, TRUE);
997 g_object_notify (G_OBJECT (tag), "strikethrough-rgba-set");
998 }
999 }
1000 else
1001 {
1002 GdkRGBA black = { 0 };
1003
1004 GTK_TEXT_APPEARANCE_SET_STRIKETHROUGH_RGBA (&priv->values->appearance, &black);
1005
1006 if (GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA_SET (&priv->values->appearance))
1007 {
1008 GTK_TEXT_APPEARANCE_SET_STRIKETHROUGH_RGBA_SET (&priv->values->appearance, FALSE);
1009 g_object_notify (G_OBJECT (tag), "strikethrough-rgba-set");
1010 }
1011 }
1012 }
1013
1014 static void
set_bg_rgba(GtkTextTag * tag,GdkRGBA * rgba)1015 set_bg_rgba (GtkTextTag *tag, GdkRGBA *rgba)
1016 {
1017 GtkTextTagPrivate *priv = tag->priv;
1018
1019 if (priv->values->appearance.rgba[0])
1020 gdk_rgba_free (priv->values->appearance.rgba[0]);
1021
1022 priv->values->appearance.rgba[0] = NULL;
1023
1024 if (rgba)
1025 {
1026 if (!priv->bg_color_set)
1027 {
1028 priv->bg_color_set = TRUE;
1029 g_object_notify (G_OBJECT (tag), "background-set");
1030 }
1031
1032 priv->values->appearance.rgba[0] = gdk_rgba_copy (rgba);
1033
1034 copy_rgba_to_gdk_color (rgba, &priv->values->appearance.bg_color);
1035 }
1036 else
1037 {
1038 if (priv->bg_color_set)
1039 {
1040 priv->bg_color_set = FALSE;
1041 g_object_notify (G_OBJECT (tag), "background-set");
1042 }
1043 }
1044 }
1045
1046 static void
set_fg_rgba(GtkTextTag * tag,GdkRGBA * rgba)1047 set_fg_rgba (GtkTextTag *tag, GdkRGBA *rgba)
1048 {
1049 GtkTextTagPrivate *priv = tag->priv;
1050
1051 if (priv->values->appearance.rgba[1])
1052 gdk_rgba_free (priv->values->appearance.rgba[1]);
1053
1054 priv->values->appearance.rgba[1] = NULL;
1055
1056 if (rgba)
1057 {
1058 if (!priv->fg_color_set)
1059 {
1060 priv->fg_color_set = TRUE;
1061 g_object_notify (G_OBJECT (tag), "foreground-set");
1062 }
1063
1064 priv->values->appearance.rgba[1] = gdk_rgba_copy (rgba);
1065
1066 copy_rgba_to_gdk_color (rgba, &priv->values->appearance.fg_color);
1067 }
1068 else
1069 {
1070 if (priv->fg_color_set)
1071 {
1072 priv->fg_color_set = FALSE;
1073 g_object_notify (G_OBJECT (tag), "foreground-set");
1074 }
1075 }
1076 }
1077
1078 static void
set_pg_bg_rgba(GtkTextTag * tag,GdkRGBA * rgba)1079 set_pg_bg_rgba (GtkTextTag *tag, GdkRGBA *rgba)
1080 {
1081 GtkTextTagPrivate *priv = tag->priv;
1082
1083 if (priv->values->pg_bg_rgba)
1084 gdk_rgba_free (priv->values->pg_bg_rgba);
1085
1086 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1087 if (priv->values->pg_bg_color)
1088 gdk_color_free (priv->values->pg_bg_color);
1089 G_GNUC_END_IGNORE_DEPRECATIONS
1090
1091 priv->values->pg_bg_rgba = NULL;
1092 priv->values->pg_bg_color = NULL;
1093
1094 if (rgba)
1095 {
1096 GdkColor color = { 0, };
1097
1098 if (!priv->pg_bg_color_set)
1099 {
1100 priv->pg_bg_color_set = TRUE;
1101 g_object_notify (G_OBJECT (tag), "paragraph-background-set");
1102 }
1103
1104 priv->values->pg_bg_rgba = gdk_rgba_copy (rgba);
1105
1106 copy_rgba_to_gdk_color (rgba, &color);
1107 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1108 priv->values->pg_bg_color = gdk_color_copy (&color);
1109 G_GNUC_END_IGNORE_DEPRECATIONS
1110 }
1111 else
1112 {
1113 if (priv->pg_bg_color_set)
1114 {
1115 priv->pg_bg_color_set = FALSE;
1116 g_object_notify (G_OBJECT (tag), "paragraph-background-set");
1117 }
1118 }
1119 }
1120
1121
1122 static void
set_bg_color(GtkTextTag * tag,GdkColor * color)1123 set_bg_color (GtkTextTag *tag, GdkColor *color)
1124 {
1125 if (color)
1126 {
1127 GdkRGBA rgba;
1128
1129 copy_gdk_color_to_rgba (color, &rgba);
1130 set_bg_rgba (tag, &rgba);
1131 }
1132 else
1133 set_bg_rgba (tag, NULL);
1134 }
1135
1136 static void
set_fg_color(GtkTextTag * tag,GdkColor * color)1137 set_fg_color (GtkTextTag *tag, GdkColor *color)
1138 {
1139 if (color)
1140 {
1141 GdkRGBA rgba;
1142
1143 copy_gdk_color_to_rgba (color, &rgba);
1144 set_fg_rgba (tag, &rgba);
1145 }
1146 else
1147 set_fg_rgba (tag, NULL);
1148 }
1149
1150 static void
set_pg_bg_color(GtkTextTag * tag,GdkColor * color)1151 set_pg_bg_color (GtkTextTag *tag, GdkColor *color)
1152 {
1153 if (color)
1154 {
1155 GdkRGBA rgba;
1156
1157 copy_gdk_color_to_rgba (color, &rgba);
1158 set_pg_bg_rgba (tag, &rgba);
1159 }
1160 else
1161 set_pg_bg_rgba (tag, NULL);
1162 }
1163
1164 static PangoFontMask
get_property_font_set_mask(guint prop_id)1165 get_property_font_set_mask (guint prop_id)
1166 {
1167 switch (prop_id)
1168 {
1169 case PROP_FAMILY_SET:
1170 return PANGO_FONT_MASK_FAMILY;
1171 case PROP_STYLE_SET:
1172 return PANGO_FONT_MASK_STYLE;
1173 case PROP_VARIANT_SET:
1174 return PANGO_FONT_MASK_VARIANT;
1175 case PROP_WEIGHT_SET:
1176 return PANGO_FONT_MASK_WEIGHT;
1177 case PROP_STRETCH_SET:
1178 return PANGO_FONT_MASK_STRETCH;
1179 case PROP_SIZE_SET:
1180 return PANGO_FONT_MASK_SIZE;
1181 }
1182
1183 return 0;
1184 }
1185
1186 static PangoFontMask
set_font_desc_fields(PangoFontDescription * desc,PangoFontMask to_set)1187 set_font_desc_fields (PangoFontDescription *desc,
1188 PangoFontMask to_set)
1189 {
1190 PangoFontMask changed_mask = 0;
1191
1192 if (to_set & PANGO_FONT_MASK_FAMILY)
1193 {
1194 const char *family = pango_font_description_get_family (desc);
1195 if (!family)
1196 {
1197 family = "sans";
1198 changed_mask |= PANGO_FONT_MASK_FAMILY;
1199 }
1200
1201 pango_font_description_set_family (desc, family);
1202 }
1203 if (to_set & PANGO_FONT_MASK_STYLE)
1204 pango_font_description_set_style (desc, pango_font_description_get_style (desc));
1205 if (to_set & PANGO_FONT_MASK_VARIANT)
1206 pango_font_description_set_variant (desc, pango_font_description_get_variant (desc));
1207 if (to_set & PANGO_FONT_MASK_WEIGHT)
1208 pango_font_description_set_weight (desc, pango_font_description_get_weight (desc));
1209 if (to_set & PANGO_FONT_MASK_STRETCH)
1210 pango_font_description_set_stretch (desc, pango_font_description_get_stretch (desc));
1211 if (to_set & PANGO_FONT_MASK_SIZE)
1212 {
1213 gint size = pango_font_description_get_size (desc);
1214 if (size <= 0)
1215 {
1216 size = 10 * PANGO_SCALE;
1217 changed_mask |= PANGO_FONT_MASK_SIZE;
1218 }
1219
1220 pango_font_description_set_size (desc, size);
1221 }
1222
1223 return changed_mask;
1224 }
1225
1226 static void
notify_set_changed(GObject * object,PangoFontMask changed_mask)1227 notify_set_changed (GObject *object,
1228 PangoFontMask changed_mask)
1229 {
1230 if (changed_mask & PANGO_FONT_MASK_FAMILY)
1231 g_object_notify (object, "family-set");
1232 if (changed_mask & PANGO_FONT_MASK_STYLE)
1233 g_object_notify (object, "style-set");
1234 if (changed_mask & PANGO_FONT_MASK_VARIANT)
1235 g_object_notify (object, "variant-set");
1236 if (changed_mask & PANGO_FONT_MASK_WEIGHT)
1237 g_object_notify (object, "weight-set");
1238 if (changed_mask & PANGO_FONT_MASK_STRETCH)
1239 g_object_notify (object, "stretch-set");
1240 if (changed_mask & PANGO_FONT_MASK_SIZE)
1241 g_object_notify (object, "size-set");
1242 }
1243
1244 static void
notify_fields_changed(GObject * object,PangoFontMask changed_mask)1245 notify_fields_changed (GObject *object,
1246 PangoFontMask changed_mask)
1247 {
1248 if (changed_mask & PANGO_FONT_MASK_FAMILY)
1249 g_object_notify (object, "family");
1250 if (changed_mask & PANGO_FONT_MASK_STYLE)
1251 g_object_notify (object, "style");
1252 if (changed_mask & PANGO_FONT_MASK_VARIANT)
1253 g_object_notify (object, "variant");
1254 if (changed_mask & PANGO_FONT_MASK_WEIGHT)
1255 g_object_notify (object, "weight");
1256 if (changed_mask & PANGO_FONT_MASK_STRETCH)
1257 g_object_notify (object, "stretch");
1258 if (changed_mask & PANGO_FONT_MASK_SIZE)
1259 g_object_notify (object, "size");
1260 }
1261
1262 static void
set_font_description(GtkTextTag * text_tag,PangoFontDescription * font_desc)1263 set_font_description (GtkTextTag *text_tag,
1264 PangoFontDescription *font_desc)
1265 {
1266 GtkTextTagPrivate *priv = text_tag->priv;
1267 GObject *object = G_OBJECT (text_tag);
1268 PangoFontDescription *new_font_desc;
1269 PangoFontMask old_mask, new_mask, changed_mask, set_changed_mask;
1270
1271 if (font_desc)
1272 new_font_desc = pango_font_description_copy (font_desc);
1273 else
1274 new_font_desc = pango_font_description_new ();
1275
1276 if (priv->values->font)
1277 old_mask = pango_font_description_get_set_fields (priv->values->font);
1278 else
1279 old_mask = 0;
1280
1281 new_mask = pango_font_description_get_set_fields (new_font_desc);
1282
1283 changed_mask = old_mask | new_mask;
1284 set_changed_mask = old_mask ^ new_mask;
1285
1286 if (priv->values->font)
1287 pango_font_description_free (priv->values->font);
1288 priv->values->font = new_font_desc;
1289
1290 g_object_freeze_notify (object);
1291
1292 g_object_notify (object, "font-desc");
1293 g_object_notify (object, "font");
1294
1295 if (changed_mask & PANGO_FONT_MASK_FAMILY)
1296 g_object_notify (object, "family");
1297 if (changed_mask & PANGO_FONT_MASK_STYLE)
1298 g_object_notify (object, "style");
1299 if (changed_mask & PANGO_FONT_MASK_VARIANT)
1300 g_object_notify (object, "variant");
1301 if (changed_mask & PANGO_FONT_MASK_WEIGHT)
1302 g_object_notify (object, "weight");
1303 if (changed_mask & PANGO_FONT_MASK_STRETCH)
1304 g_object_notify (object, "stretch");
1305 if (changed_mask & PANGO_FONT_MASK_SIZE)
1306 {
1307 g_object_notify (object, "size");
1308 g_object_notify (object, "size-points");
1309 }
1310
1311 notify_set_changed (object, set_changed_mask);
1312
1313 g_object_thaw_notify (object);
1314 }
1315
1316 static void
gtk_text_tag_ensure_font(GtkTextTag * text_tag)1317 gtk_text_tag_ensure_font (GtkTextTag *text_tag)
1318 {
1319 GtkTextTagPrivate *priv = text_tag->priv;
1320
1321 if (!priv->values->font)
1322 priv->values->font = pango_font_description_new ();
1323 }
1324
1325 static void
gtk_text_tag_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1326 gtk_text_tag_set_property (GObject *object,
1327 guint prop_id,
1328 const GValue *value,
1329 GParamSpec *pspec)
1330 {
1331 GtkTextTag *text_tag = GTK_TEXT_TAG (object);
1332 GtkTextTagPrivate *priv = text_tag->priv;
1333 gboolean size_changed = FALSE;
1334
1335 switch (prop_id)
1336 {
1337 case PROP_NAME:
1338 g_return_if_fail (priv->name == NULL);
1339 priv->name = g_value_dup_string (value);
1340 break;
1341
1342 case PROP_BACKGROUND:
1343 {
1344 GdkRGBA rgba;
1345
1346 if (!g_value_get_string (value))
1347 set_bg_rgba (text_tag, NULL); /* reset background_set to FALSE */
1348 else if (gdk_rgba_parse (&rgba, g_value_get_string (value)))
1349 set_bg_rgba (text_tag, &rgba);
1350 else
1351 g_warning ("Don't know color '%s'", g_value_get_string (value));
1352
1353 g_object_notify (object, "background-gdk");
1354 }
1355 break;
1356
1357 case PROP_FOREGROUND:
1358 {
1359 GdkRGBA rgba;
1360
1361 if (!g_value_get_string (value))
1362 set_fg_rgba (text_tag, NULL); /* reset to foreground_set to FALSE */
1363 else if (gdk_rgba_parse (&rgba, g_value_get_string (value)))
1364 set_fg_rgba (text_tag, &rgba);
1365 else
1366 g_warning ("Don't know color '%s'", g_value_get_string (value));
1367
1368 g_object_notify (object, "foreground-gdk");
1369 }
1370 break;
1371
1372 case PROP_BACKGROUND_GDK:
1373 {
1374 GdkColor *color = g_value_get_boxed (value);
1375
1376 set_bg_color (text_tag, color);
1377 }
1378 break;
1379
1380 case PROP_FOREGROUND_GDK:
1381 {
1382 GdkColor *color = g_value_get_boxed (value);
1383
1384 set_fg_color (text_tag, color);
1385 }
1386 break;
1387
1388 case PROP_BACKGROUND_RGBA:
1389 {
1390 GdkRGBA *color = g_value_get_boxed (value);
1391
1392 set_bg_rgba (text_tag, color);
1393 }
1394 break;
1395
1396 case PROP_FOREGROUND_RGBA:
1397 {
1398 GdkRGBA *color = g_value_get_boxed (value);
1399
1400 set_fg_rgba (text_tag, color);
1401 }
1402 break;
1403
1404 case PROP_FONT:
1405 {
1406 PangoFontDescription *font_desc = NULL;
1407 const gchar *name;
1408
1409 name = g_value_get_string (value);
1410
1411 if (name)
1412 font_desc = pango_font_description_from_string (name);
1413
1414 set_font_description (text_tag, font_desc);
1415 if (font_desc)
1416 pango_font_description_free (font_desc);
1417
1418 size_changed = TRUE;
1419 }
1420 break;
1421
1422 case PROP_FONT_DESC:
1423 {
1424 PangoFontDescription *font_desc;
1425
1426 font_desc = g_value_get_boxed (value);
1427
1428 set_font_description (text_tag, font_desc);
1429
1430 size_changed = TRUE;
1431 }
1432 break;
1433
1434 case PROP_FAMILY:
1435 case PROP_STYLE:
1436 case PROP_VARIANT:
1437 case PROP_WEIGHT:
1438 case PROP_STRETCH:
1439 case PROP_SIZE:
1440 case PROP_SIZE_POINTS:
1441 {
1442 PangoFontMask old_set_mask;
1443
1444 gtk_text_tag_ensure_font (text_tag);
1445 old_set_mask = pango_font_description_get_set_fields (priv->values->font);
1446
1447 switch (prop_id)
1448 {
1449 case PROP_FAMILY:
1450 pango_font_description_set_family (priv->values->font,
1451 g_value_get_string (value));
1452 break;
1453 case PROP_STYLE:
1454 pango_font_description_set_style (priv->values->font,
1455 g_value_get_enum (value));
1456 break;
1457 case PROP_VARIANT:
1458 pango_font_description_set_variant (priv->values->font,
1459 g_value_get_enum (value));
1460 break;
1461 case PROP_WEIGHT:
1462 pango_font_description_set_weight (priv->values->font,
1463 g_value_get_int (value));
1464 break;
1465 case PROP_STRETCH:
1466 pango_font_description_set_stretch (priv->values->font,
1467 g_value_get_enum (value));
1468 break;
1469 case PROP_SIZE:
1470 pango_font_description_set_size (priv->values->font,
1471 g_value_get_int (value));
1472 g_object_notify (object, "size-points");
1473 break;
1474 case PROP_SIZE_POINTS:
1475 pango_font_description_set_size (priv->values->font,
1476 g_value_get_double (value) * PANGO_SCALE);
1477 g_object_notify (object, "size");
1478 break;
1479 }
1480
1481 size_changed = TRUE;
1482 notify_set_changed (object, old_set_mask & pango_font_description_get_set_fields (priv->values->font));
1483 g_object_notify (object, "font-desc");
1484 g_object_notify (object, "font");
1485
1486 break;
1487 }
1488
1489 case PROP_SCALE:
1490 priv->values->font_scale = g_value_get_double (value);
1491 priv->scale_set = TRUE;
1492 g_object_notify (object, "scale-set");
1493 size_changed = TRUE;
1494 break;
1495
1496 case PROP_PIXELS_ABOVE_LINES:
1497 priv->pixels_above_lines_set = TRUE;
1498 priv->values->pixels_above_lines = g_value_get_int (value);
1499 g_object_notify (object, "pixels-above-lines-set");
1500 size_changed = TRUE;
1501 break;
1502
1503 case PROP_PIXELS_BELOW_LINES:
1504 priv->pixels_below_lines_set = TRUE;
1505 priv->values->pixels_below_lines = g_value_get_int (value);
1506 g_object_notify (object, "pixels-below-lines-set");
1507 size_changed = TRUE;
1508 break;
1509
1510 case PROP_PIXELS_INSIDE_WRAP:
1511 priv->pixels_inside_wrap_set = TRUE;
1512 priv->values->pixels_inside_wrap = g_value_get_int (value);
1513 g_object_notify (object, "pixels-inside-wrap-set");
1514 size_changed = TRUE;
1515 break;
1516
1517 case PROP_EDITABLE:
1518 priv->editable_set = TRUE;
1519 priv->values->editable = g_value_get_boolean (value);
1520 g_object_notify (object, "editable-set");
1521 break;
1522
1523 case PROP_WRAP_MODE:
1524 priv->wrap_mode_set = TRUE;
1525 priv->values->wrap_mode = g_value_get_enum (value);
1526 g_object_notify (object, "wrap-mode-set");
1527 size_changed = TRUE;
1528 break;
1529
1530 case PROP_JUSTIFICATION:
1531 priv->justification_set = TRUE;
1532 priv->values->justification = g_value_get_enum (value);
1533 g_object_notify (object, "justification-set");
1534 size_changed = TRUE;
1535 break;
1536
1537 case PROP_DIRECTION:
1538 priv->values->direction = g_value_get_enum (value);
1539 break;
1540
1541 case PROP_LEFT_MARGIN:
1542 priv->left_margin_set = TRUE;
1543 priv->values->left_margin = g_value_get_int (value);
1544 g_object_notify (object, "left-margin-set");
1545 size_changed = TRUE;
1546 break;
1547
1548 case PROP_INDENT:
1549 priv->indent_set = TRUE;
1550 priv->values->indent = g_value_get_int (value);
1551 g_object_notify (object, "indent-set");
1552 size_changed = TRUE;
1553 break;
1554
1555 case PROP_STRIKETHROUGH:
1556 priv->strikethrough_set = TRUE;
1557 priv->values->appearance.strikethrough = g_value_get_boolean (value);
1558 g_object_notify (object, "strikethrough-set");
1559 break;
1560
1561 case PROP_STRIKETHROUGH_RGBA:
1562 {
1563 GdkRGBA *color = g_value_get_boxed (value);
1564 set_strikethrough_rgba (text_tag, color);
1565 }
1566 break;
1567
1568 case PROP_RIGHT_MARGIN:
1569 priv->right_margin_set = TRUE;
1570 priv->values->right_margin = g_value_get_int (value);
1571 g_object_notify (object, "right-margin-set");
1572 size_changed = TRUE;
1573 break;
1574
1575 case PROP_UNDERLINE:
1576 priv->underline_set = TRUE;
1577 priv->values->appearance.underline = g_value_get_enum (value);
1578 g_object_notify (object, "underline-set");
1579 break;
1580
1581 case PROP_UNDERLINE_RGBA:
1582 {
1583 GdkRGBA *color = g_value_get_boxed (value);
1584 set_underline_rgba (text_tag, color);
1585 }
1586 break;
1587
1588 case PROP_RISE:
1589 priv->rise_set = TRUE;
1590 priv->values->appearance.rise = g_value_get_int (value);
1591 g_object_notify (object, "rise-set");
1592 size_changed = TRUE;
1593 break;
1594
1595 case PROP_BACKGROUND_FULL_HEIGHT:
1596 priv->bg_full_height_set = TRUE;
1597 priv->values->bg_full_height = g_value_get_boolean (value);
1598 g_object_notify (object, "background-full-height-set");
1599 break;
1600
1601 case PROP_LANGUAGE:
1602 priv->language_set = TRUE;
1603 priv->values->language = pango_language_from_string (g_value_get_string (value));
1604 g_object_notify (object, "language-set");
1605 break;
1606
1607 case PROP_TABS:
1608 priv->tabs_set = TRUE;
1609
1610 if (priv->values->tabs)
1611 pango_tab_array_free (priv->values->tabs);
1612
1613 /* FIXME I'm not sure if this is a memleak or not */
1614 priv->values->tabs =
1615 pango_tab_array_copy (g_value_get_boxed (value));
1616
1617 g_object_notify (object, "tabs-set");
1618
1619 size_changed = TRUE;
1620 break;
1621
1622 case PROP_INVISIBLE:
1623 priv->invisible_set = TRUE;
1624 priv->values->invisible = g_value_get_boolean (value);
1625 g_object_notify (object, "invisible-set");
1626 size_changed = TRUE;
1627 break;
1628
1629 case PROP_PARAGRAPH_BACKGROUND:
1630 {
1631 GdkRGBA rgba;
1632
1633 if (!g_value_get_string (value))
1634 set_pg_bg_rgba (text_tag, NULL); /* reset paragraph_background_set to FALSE */
1635 else if (gdk_rgba_parse (&rgba, g_value_get_string (value)))
1636 set_pg_bg_rgba (text_tag, &rgba);
1637 else
1638 g_warning ("Don't know color '%s'", g_value_get_string (value));
1639
1640 g_object_notify (object, "paragraph-background-gdk");
1641 }
1642 break;
1643
1644 case PROP_PARAGRAPH_BACKGROUND_GDK:
1645 {
1646 GdkColor *color = g_value_get_boxed (value);
1647
1648 set_pg_bg_color (text_tag, color);
1649 }
1650 break;
1651
1652 case PROP_PARAGRAPH_BACKGROUND_RGBA:
1653 {
1654 GdkRGBA *color = g_value_get_boxed (value);
1655
1656 set_pg_bg_rgba (text_tag, color);
1657 }
1658 break;
1659
1660 case PROP_FALLBACK:
1661 priv->fallback_set = TRUE;
1662 priv->values->no_fallback = !g_value_get_boolean (value);
1663 g_object_notify (object, "fallback-set");
1664 break;
1665
1666 case PROP_LETTER_SPACING:
1667 priv->letter_spacing_set = TRUE;
1668 priv->values->letter_spacing = g_value_get_int (value);
1669 g_object_notify (object, "letter-spacing-set");
1670 break;
1671
1672 case PROP_FONT_FEATURES:
1673 priv->font_features_set = TRUE;
1674 priv->values->font_features = g_value_dup_string (value);
1675 g_object_notify (object, "font-features-set");
1676 break;
1677
1678 case PROP_ACCUMULATIVE_MARGIN:
1679 priv->accumulative_margin = g_value_get_boolean (value);
1680 g_object_notify (object, "accumulative-margin");
1681 size_changed = TRUE;
1682 break;
1683
1684 /* Whether the value should be used... */
1685
1686 case PROP_BACKGROUND_SET:
1687 priv->bg_color_set = g_value_get_boolean (value);
1688 break;
1689
1690 case PROP_FOREGROUND_SET:
1691 priv->fg_color_set = g_value_get_boolean (value);
1692 break;
1693
1694 case PROP_FAMILY_SET:
1695 case PROP_STYLE_SET:
1696 case PROP_VARIANT_SET:
1697 case PROP_WEIGHT_SET:
1698 case PROP_STRETCH_SET:
1699 case PROP_SIZE_SET:
1700 if (!g_value_get_boolean (value))
1701 {
1702 if (priv->values->font)
1703 pango_font_description_unset_fields (priv->values->font,
1704 get_property_font_set_mask (prop_id));
1705 }
1706 else
1707 {
1708 PangoFontMask changed_mask;
1709
1710 gtk_text_tag_ensure_font (text_tag);
1711 changed_mask = set_font_desc_fields (priv->values->font,
1712 get_property_font_set_mask (prop_id));
1713 notify_fields_changed (G_OBJECT (text_tag), changed_mask);
1714 }
1715 break;
1716
1717 case PROP_SCALE_SET:
1718 priv->scale_set = g_value_get_boolean (value);
1719 size_changed = TRUE;
1720 break;
1721
1722 case PROP_PIXELS_ABOVE_LINES_SET:
1723 priv->pixels_above_lines_set = g_value_get_boolean (value);
1724 size_changed = TRUE;
1725 break;
1726
1727 case PROP_PIXELS_BELOW_LINES_SET:
1728 priv->pixels_below_lines_set = g_value_get_boolean (value);
1729 size_changed = TRUE;
1730 break;
1731
1732 case PROP_PIXELS_INSIDE_WRAP_SET:
1733 priv->pixels_inside_wrap_set = g_value_get_boolean (value);
1734 size_changed = TRUE;
1735 break;
1736
1737 case PROP_EDITABLE_SET:
1738 priv->editable_set = g_value_get_boolean (value);
1739 break;
1740
1741 case PROP_WRAP_MODE_SET:
1742 priv->wrap_mode_set = g_value_get_boolean (value);
1743 size_changed = TRUE;
1744 break;
1745
1746 case PROP_JUSTIFICATION_SET:
1747 priv->justification_set = g_value_get_boolean (value);
1748 size_changed = TRUE;
1749 break;
1750
1751 case PROP_LEFT_MARGIN_SET:
1752 priv->left_margin_set = g_value_get_boolean (value);
1753 size_changed = TRUE;
1754 break;
1755
1756 case PROP_INDENT_SET:
1757 priv->indent_set = g_value_get_boolean (value);
1758 size_changed = TRUE;
1759 break;
1760
1761 case PROP_STRIKETHROUGH_SET:
1762 priv->strikethrough_set = g_value_get_boolean (value);
1763 break;
1764
1765 case PROP_STRIKETHROUGH_RGBA_SET:
1766 GTK_TEXT_APPEARANCE_SET_STRIKETHROUGH_RGBA_SET (&priv->values->appearance,
1767 g_value_get_boolean (value));
1768 break;
1769
1770 case PROP_RIGHT_MARGIN_SET:
1771 priv->right_margin_set = g_value_get_boolean (value);
1772 size_changed = TRUE;
1773 break;
1774
1775 case PROP_UNDERLINE_SET:
1776 priv->underline_set = g_value_get_boolean (value);
1777 break;
1778
1779 case PROP_UNDERLINE_RGBA_SET:
1780 GTK_TEXT_APPEARANCE_SET_UNDERLINE_RGBA_SET (&priv->values->appearance,
1781 g_value_get_boolean (value));
1782 break;
1783
1784 case PROP_RISE_SET:
1785 priv->rise_set = g_value_get_boolean (value);
1786 size_changed = TRUE;
1787 break;
1788
1789 case PROP_BACKGROUND_FULL_HEIGHT_SET:
1790 priv->bg_full_height_set = g_value_get_boolean (value);
1791 break;
1792
1793 case PROP_LANGUAGE_SET:
1794 priv->language_set = g_value_get_boolean (value);
1795 size_changed = TRUE;
1796 break;
1797
1798 case PROP_TABS_SET:
1799 priv->tabs_set = g_value_get_boolean (value);
1800 size_changed = TRUE;
1801 break;
1802
1803 case PROP_INVISIBLE_SET:
1804 priv->invisible_set = g_value_get_boolean (value);
1805 size_changed = TRUE;
1806 break;
1807
1808 case PROP_PARAGRAPH_BACKGROUND_SET:
1809 priv->pg_bg_color_set = g_value_get_boolean (value);
1810 break;
1811
1812 case PROP_FALLBACK_SET:
1813 priv->fallback_set = g_value_get_boolean (value);
1814 break;
1815
1816 case PROP_LETTER_SPACING_SET:
1817 priv->letter_spacing_set = g_value_get_boolean (value);
1818 break;
1819
1820 case PROP_FONT_FEATURES_SET:
1821 priv->font_features_set = g_value_get_boolean (value);
1822 break;
1823
1824 default:
1825 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1826 break;
1827 }
1828
1829 /* The signal is emitted for each set_property(). A possible optimization is
1830 * to send the signal only once when several properties are set at the same
1831 * time with e.g. g_object_set(). The signal could be emitted when the notify
1832 * signal is thawed.
1833 */
1834 gtk_text_tag_changed (text_tag, size_changed);
1835 }
1836
1837 static void
gtk_text_tag_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1838 gtk_text_tag_get_property (GObject *object,
1839 guint prop_id,
1840 GValue *value,
1841 GParamSpec *pspec)
1842 {
1843 GtkTextTag *tag = GTK_TEXT_TAG (object);
1844 GtkTextTagPrivate *priv = tag->priv;
1845
1846 switch (prop_id)
1847 {
1848 case PROP_NAME:
1849 g_value_set_string (value, priv->name);
1850 break;
1851
1852 case PROP_BACKGROUND_GDK:
1853 g_value_set_boxed (value, &priv->values->appearance.bg_color);
1854 break;
1855
1856 case PROP_BACKGROUND_RGBA:
1857 g_value_set_boxed (value, priv->values->appearance.rgba[0]);
1858 break;
1859
1860 case PROP_FOREGROUND_GDK:
1861 g_value_set_boxed (value, &priv->values->appearance.fg_color);
1862 break;
1863
1864 case PROP_FOREGROUND_RGBA:
1865 g_value_set_boxed (value, priv->values->appearance.rgba[1]);
1866 break;
1867
1868 case PROP_FONT:
1869 {
1870 gchar *str;
1871
1872 gtk_text_tag_ensure_font (tag);
1873
1874 str = pango_font_description_to_string (priv->values->font);
1875 g_value_take_string (value, str);
1876 }
1877 break;
1878
1879 case PROP_FONT_DESC:
1880 gtk_text_tag_ensure_font (tag);
1881 g_value_set_boxed (value, priv->values->font);
1882 break;
1883
1884 case PROP_FAMILY:
1885 case PROP_STYLE:
1886 case PROP_VARIANT:
1887 case PROP_WEIGHT:
1888 case PROP_STRETCH:
1889 case PROP_SIZE:
1890 case PROP_SIZE_POINTS:
1891 gtk_text_tag_ensure_font (tag);
1892 switch (prop_id)
1893 {
1894 case PROP_FAMILY:
1895 g_value_set_string (value, pango_font_description_get_family (priv->values->font));
1896 break;
1897
1898 case PROP_STYLE:
1899 g_value_set_enum (value, pango_font_description_get_style (priv->values->font));
1900 break;
1901
1902 case PROP_VARIANT:
1903 g_value_set_enum (value, pango_font_description_get_variant (priv->values->font));
1904 break;
1905
1906 case PROP_WEIGHT:
1907 g_value_set_int (value, pango_font_description_get_weight (priv->values->font));
1908 break;
1909
1910 case PROP_STRETCH:
1911 g_value_set_enum (value, pango_font_description_get_stretch (priv->values->font));
1912 break;
1913
1914 case PROP_SIZE:
1915 g_value_set_int (value, pango_font_description_get_size (priv->values->font));
1916 break;
1917
1918 case PROP_SIZE_POINTS:
1919 g_value_set_double (value, ((double)pango_font_description_get_size (priv->values->font)) / (double)PANGO_SCALE);
1920 break;
1921 }
1922 break;
1923
1924 case PROP_SCALE:
1925 g_value_set_double (value, priv->values->font_scale);
1926 break;
1927
1928 case PROP_PIXELS_ABOVE_LINES:
1929 g_value_set_int (value, priv->values->pixels_above_lines);
1930 break;
1931
1932 case PROP_PIXELS_BELOW_LINES:
1933 g_value_set_int (value, priv->values->pixels_below_lines);
1934 break;
1935
1936 case PROP_PIXELS_INSIDE_WRAP:
1937 g_value_set_int (value, priv->values->pixels_inside_wrap);
1938 break;
1939
1940 case PROP_EDITABLE:
1941 g_value_set_boolean (value, priv->values->editable);
1942 break;
1943
1944 case PROP_WRAP_MODE:
1945 g_value_set_enum (value, priv->values->wrap_mode);
1946 break;
1947
1948 case PROP_JUSTIFICATION:
1949 g_value_set_enum (value, priv->values->justification);
1950 break;
1951
1952 case PROP_DIRECTION:
1953 g_value_set_enum (value, priv->values->direction);
1954 break;
1955
1956 case PROP_LEFT_MARGIN:
1957 g_value_set_int (value, priv->values->left_margin);
1958 break;
1959
1960 case PROP_INDENT:
1961 g_value_set_int (value, priv->values->indent);
1962 break;
1963
1964 case PROP_STRIKETHROUGH:
1965 g_value_set_boolean (value, priv->values->appearance.strikethrough);
1966 break;
1967
1968 case PROP_STRIKETHROUGH_RGBA:
1969 if (GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA_SET (&priv->values->appearance))
1970 {
1971 GdkRGBA rgba;
1972
1973 GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA (&priv->values->appearance, &rgba);
1974 g_value_set_boxed (value, &rgba);
1975 }
1976 break;
1977
1978 case PROP_RIGHT_MARGIN:
1979 g_value_set_int (value, priv->values->right_margin);
1980 break;
1981
1982 case PROP_UNDERLINE:
1983 g_value_set_enum (value, priv->values->appearance.underline);
1984 break;
1985
1986 case PROP_UNDERLINE_RGBA:
1987 if (GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA_SET (&priv->values->appearance))
1988 {
1989 GdkRGBA rgba;
1990
1991 GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA (&priv->values->appearance, &rgba);
1992 g_value_set_boxed (value, &rgba);
1993 }
1994 break;
1995
1996 case PROP_RISE:
1997 g_value_set_int (value, priv->values->appearance.rise);
1998 break;
1999
2000 case PROP_BACKGROUND_FULL_HEIGHT:
2001 g_value_set_boolean (value, priv->values->bg_full_height);
2002 break;
2003
2004 case PROP_LANGUAGE:
2005 g_value_set_string (value, pango_language_to_string (priv->values->language));
2006 break;
2007
2008 case PROP_TABS:
2009 if (priv->values->tabs)
2010 g_value_set_boxed (value, priv->values->tabs);
2011 break;
2012
2013 case PROP_INVISIBLE:
2014 g_value_set_boolean (value, priv->values->invisible);
2015 break;
2016
2017 case PROP_PARAGRAPH_BACKGROUND_GDK:
2018 g_value_set_boxed (value, priv->values->pg_bg_color);
2019 break;
2020
2021 case PROP_PARAGRAPH_BACKGROUND_RGBA:
2022 g_value_set_boxed (value, priv->values->pg_bg_rgba);
2023 break;
2024
2025 case PROP_FALLBACK:
2026 g_value_set_boolean (value, !priv->values->no_fallback);
2027 break;
2028
2029 case PROP_LETTER_SPACING:
2030 g_value_set_int (value, priv->values->letter_spacing);
2031 break;
2032
2033 case PROP_FONT_FEATURES:
2034 g_value_set_string (value, priv->values->font_features);
2035 break;
2036
2037 case PROP_ACCUMULATIVE_MARGIN:
2038 g_value_set_boolean (value, priv->accumulative_margin);
2039 break;
2040
2041 case PROP_BACKGROUND_SET:
2042 g_value_set_boolean (value, priv->bg_color_set);
2043 break;
2044
2045 case PROP_FOREGROUND_SET:
2046 g_value_set_boolean (value, priv->fg_color_set);
2047 break;
2048
2049 case PROP_FAMILY_SET:
2050 case PROP_STYLE_SET:
2051 case PROP_VARIANT_SET:
2052 case PROP_WEIGHT_SET:
2053 case PROP_STRETCH_SET:
2054 case PROP_SIZE_SET:
2055 {
2056 PangoFontMask set_mask = priv->values->font ? pango_font_description_get_set_fields (priv->values->font) : 0;
2057 PangoFontMask test_mask = get_property_font_set_mask (prop_id);
2058 g_value_set_boolean (value, (set_mask & test_mask) != 0);
2059
2060 break;
2061 }
2062
2063 case PROP_SCALE_SET:
2064 g_value_set_boolean (value, priv->scale_set);
2065 break;
2066
2067 case PROP_PIXELS_ABOVE_LINES_SET:
2068 g_value_set_boolean (value, priv->pixels_above_lines_set);
2069 break;
2070
2071 case PROP_PIXELS_BELOW_LINES_SET:
2072 g_value_set_boolean (value, priv->pixels_below_lines_set);
2073 break;
2074
2075 case PROP_PIXELS_INSIDE_WRAP_SET:
2076 g_value_set_boolean (value, priv->pixels_inside_wrap_set);
2077 break;
2078
2079 case PROP_EDITABLE_SET:
2080 g_value_set_boolean (value, priv->editable_set);
2081 break;
2082
2083 case PROP_WRAP_MODE_SET:
2084 g_value_set_boolean (value, priv->wrap_mode_set);
2085 break;
2086
2087 case PROP_JUSTIFICATION_SET:
2088 g_value_set_boolean (value, priv->justification_set);
2089 break;
2090
2091 case PROP_LEFT_MARGIN_SET:
2092 g_value_set_boolean (value, priv->left_margin_set);
2093 break;
2094
2095 case PROP_INDENT_SET:
2096 g_value_set_boolean (value, priv->indent_set);
2097 break;
2098
2099 case PROP_STRIKETHROUGH_SET:
2100 g_value_set_boolean (value, priv->strikethrough_set);
2101 break;
2102
2103 case PROP_STRIKETHROUGH_RGBA_SET:
2104 g_value_set_boolean (value,
2105 GTK_TEXT_APPEARANCE_GET_STRIKETHROUGH_RGBA_SET (&priv->values->appearance));
2106 break;
2107
2108 case PROP_RIGHT_MARGIN_SET:
2109 g_value_set_boolean (value, priv->right_margin_set);
2110 break;
2111
2112 case PROP_UNDERLINE_SET:
2113 g_value_set_boolean (value, priv->underline_set);
2114 break;
2115
2116 case PROP_UNDERLINE_RGBA_SET:
2117 g_value_set_boolean (value,
2118 GTK_TEXT_APPEARANCE_GET_UNDERLINE_RGBA_SET (&priv->values->appearance));
2119 break;
2120
2121 case PROP_RISE_SET:
2122 g_value_set_boolean (value, priv->rise_set);
2123 break;
2124
2125 case PROP_BACKGROUND_FULL_HEIGHT_SET:
2126 g_value_set_boolean (value, priv->bg_full_height_set);
2127 break;
2128
2129 case PROP_LANGUAGE_SET:
2130 g_value_set_boolean (value, priv->language_set);
2131 break;
2132
2133 case PROP_TABS_SET:
2134 g_value_set_boolean (value, priv->tabs_set);
2135 break;
2136
2137 case PROP_INVISIBLE_SET:
2138 g_value_set_boolean (value, priv->invisible_set);
2139 break;
2140
2141 case PROP_PARAGRAPH_BACKGROUND_SET:
2142 g_value_set_boolean (value, priv->pg_bg_color_set);
2143 break;
2144
2145 case PROP_FALLBACK_SET:
2146 g_value_set_boolean (value, priv->fallback_set);
2147 break;
2148
2149 case PROP_LETTER_SPACING_SET:
2150 g_value_set_boolean (value, priv->letter_spacing_set);
2151 break;
2152
2153 case PROP_FONT_FEATURES_SET:
2154 g_value_set_boolean (value, priv->font_features_set);
2155 break;
2156
2157 case PROP_BACKGROUND:
2158 case PROP_FOREGROUND:
2159 case PROP_PARAGRAPH_BACKGROUND:
2160 g_warning ("'foreground', 'background' and 'paragraph_background' properties are not readable, use 'foreground_gdk', 'background_gdk' and 'paragraph_background_gdk'");
2161 break;
2162 default:
2163 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2164 break;
2165 }
2166 }
2167
2168 /*
2169 * Tag operations
2170 */
2171
2172 typedef struct {
2173 gint high;
2174 gint low;
2175 gint delta;
2176 } DeltaData;
2177
2178 static void
delta_priority_foreach(GtkTextTag * tag,gpointer user_data)2179 delta_priority_foreach (GtkTextTag *tag, gpointer user_data)
2180 {
2181 GtkTextTagPrivate *priv = tag->priv;
2182 DeltaData *dd = user_data;
2183
2184 if (priv->priority >= dd->low && priv->priority <= dd->high)
2185 priv->priority += dd->delta;
2186 }
2187
2188 /**
2189 * gtk_text_tag_get_priority:
2190 * @tag: a #GtkTextTag
2191 *
2192 * Get the tag priority.
2193 *
2194 * Returns: The tag’s priority.
2195 **/
2196 gint
gtk_text_tag_get_priority(GtkTextTag * tag)2197 gtk_text_tag_get_priority (GtkTextTag *tag)
2198 {
2199 g_return_val_if_fail (GTK_IS_TEXT_TAG (tag), 0);
2200
2201 return tag->priv->priority;
2202 }
2203
2204 /**
2205 * gtk_text_tag_set_priority:
2206 * @tag: a #GtkTextTag
2207 * @priority: the new priority
2208 *
2209 * Sets the priority of a #GtkTextTag. Valid priorities
2210 * start at 0 and go to one less than gtk_text_tag_table_get_size().
2211 * Each tag in a table has a unique priority; setting the priority
2212 * of one tag shifts the priorities of all the other tags in the
2213 * table to maintain a unique priority for each tag. Higher priority
2214 * tags “win” if two tags both set the same text attribute. When adding
2215 * a tag to a tag table, it will be assigned the highest priority in
2216 * the table by default; so normally the precedence of a set of tags
2217 * is the order in which they were added to the table, or created with
2218 * gtk_text_buffer_create_tag(), which adds the tag to the buffer’s table
2219 * automatically.
2220 **/
2221 void
gtk_text_tag_set_priority(GtkTextTag * tag,gint priority)2222 gtk_text_tag_set_priority (GtkTextTag *tag,
2223 gint priority)
2224 {
2225 GtkTextTagPrivate *priv;
2226 DeltaData dd;
2227
2228 g_return_if_fail (GTK_IS_TEXT_TAG (tag));
2229
2230 priv = tag->priv;
2231
2232 g_return_if_fail (priv->table != NULL);
2233 g_return_if_fail (priority >= 0);
2234 g_return_if_fail (priority < gtk_text_tag_table_get_size (priv->table));
2235
2236 if (priority == priv->priority)
2237 return;
2238
2239 if (priority < priv->priority)
2240 {
2241 dd.low = priority;
2242 dd.high = priv->priority - 1;
2243 dd.delta = 1;
2244 }
2245 else
2246 {
2247 dd.low = priv->priority + 1;
2248 dd.high = priority;
2249 dd.delta = -1;
2250 }
2251
2252 gtk_text_tag_table_foreach (priv->table,
2253 delta_priority_foreach,
2254 &dd);
2255
2256 priv->priority = priority;
2257 }
2258
2259 /**
2260 * gtk_text_tag_event:
2261 * @tag: a #GtkTextTag
2262 * @event_object: object that received the event, such as a widget
2263 * @event: the event
2264 * @iter: location where the event was received
2265 *
2266 * Emits the “event” signal on the #GtkTextTag.
2267 *
2268 * Returns: result of signal emission (whether the event was handled)
2269 **/
2270 gboolean
gtk_text_tag_event(GtkTextTag * tag,GObject * event_object,GdkEvent * event,const GtkTextIter * iter)2271 gtk_text_tag_event (GtkTextTag *tag,
2272 GObject *event_object,
2273 GdkEvent *event,
2274 const GtkTextIter *iter)
2275 {
2276 gboolean retval = FALSE;
2277
2278 g_return_val_if_fail (GTK_IS_TEXT_TAG (tag), FALSE);
2279 g_return_val_if_fail (G_IS_OBJECT (event_object), FALSE);
2280 g_return_val_if_fail (event != NULL, FALSE);
2281
2282 g_signal_emit (tag,
2283 signals[EVENT],
2284 0,
2285 event_object,
2286 event,
2287 iter,
2288 &retval);
2289
2290 return retval;
2291 }
2292
2293 /**
2294 * gtk_text_tag_changed:
2295 * @tag: a #GtkTextTag.
2296 * @size_changed: whether the change affects the #GtkTextView layout.
2297 *
2298 * Emits the #GtkTextTagTable::tag-changed signal on the #GtkTextTagTable where
2299 * the tag is included.
2300 *
2301 * The signal is already emitted when setting a #GtkTextTag property. This
2302 * function is useful for a #GtkTextTag subclass.
2303 *
2304 * Since: 3.20
2305 */
2306 void
gtk_text_tag_changed(GtkTextTag * tag,gboolean size_changed)2307 gtk_text_tag_changed (GtkTextTag *tag,
2308 gboolean size_changed)
2309 {
2310 GtkTextTagPrivate *priv;
2311
2312 g_return_if_fail (GTK_IS_TEXT_TAG (tag));
2313
2314 priv = tag->priv;
2315
2316 /* This is somewhat weird since we emit another object's signal here, but the
2317 * two objects are already tightly bound. If a GtkTextTag::changed signal is
2318 * added, this would increase significantly the number of signal connections.
2319 */
2320 if (priv->table != NULL)
2321 _gtk_text_tag_table_tag_changed (priv->table, tag, size_changed);
2322 }
2323
2324 static int
tag_sort_func(gconstpointer first,gconstpointer second)2325 tag_sort_func (gconstpointer first, gconstpointer second)
2326 {
2327 GtkTextTag *tag1, *tag2;
2328
2329 tag1 = * (GtkTextTag **) first;
2330 tag2 = * (GtkTextTag **) second;
2331 return tag1->priv->priority - tag2->priv->priority;
2332 }
2333
2334 void
_gtk_text_tag_array_sort(GtkTextTag ** tag_array_p,guint len)2335 _gtk_text_tag_array_sort (GtkTextTag** tag_array_p,
2336 guint len)
2337 {
2338 int i, j, prio;
2339 GtkTextTag **tag;
2340 GtkTextTag **maxPtrPtr, *tmp;
2341
2342 g_return_if_fail (tag_array_p != NULL);
2343 g_return_if_fail (len > 0);
2344
2345 if (len < 2) {
2346 return;
2347 }
2348 if (len < 20) {
2349 GtkTextTag **iter = tag_array_p;
2350
2351 for (i = len-1; i > 0; i--, iter++) {
2352 maxPtrPtr = tag = iter;
2353 prio = tag[0]->priv->priority;
2354 for (j = i, tag++; j > 0; j--, tag++) {
2355 if (tag[0]->priv->priority < prio) {
2356 prio = tag[0]->priv->priority;
2357 maxPtrPtr = tag;
2358 }
2359 }
2360 tmp = *maxPtrPtr;
2361 *maxPtrPtr = *iter;
2362 *iter = tmp;
2363 }
2364 } else {
2365 qsort ((void *) tag_array_p, (unsigned) len, sizeof (GtkTextTag *),
2366 tag_sort_func);
2367 }
2368
2369 #if 0
2370 {
2371 printf ("Sorted tag array: \n");
2372 i = 0;
2373 while (i < len)
2374 {
2375 GtkTextTag *t = tag_array_p[i];
2376 printf (" %s priority %d\n", t->name, t->priority);
2377
2378 ++i;
2379 }
2380 }
2381 #endif
2382 }
2383
2384