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

source code of gtk/gtk/gtktexttag.c