Bug Summary

File:ctk/ctklabel.c
Warning:line 3650, column 25
Dereference of null pointer (loaded from variable 'minimum_baseline')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ctklabel.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/ctk -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Ctk" -D G_LOG_USE_STRUCTURED=1 -D CTK_VERSION="3.25.5" -D CTK_BINARY_VERSION="3.0.0" -D CTK_COMPILATION -D CTK_PRINT_BACKEND_ENABLE_UNSUPPORTED -D CTK_LIBDIR="/usr/lib" -D CTK_LOCALEDIR="/usr/share/locale" -D CTK_DATADIR="/usr/share" -D CTK_DATA_PREFIX="/usr" -D CTK_SYSCONFDIR="/usr/etc" -D CTK_HOST="x86_64-pc-linux-gnu" -D CTK_PRINT_BACKENDS="file,cups" -D X11_DATA_PREFIX="/usr" -D ISO_CODES_PREFIX="" -I .. -I ../ctk -I .. -I ../cdk -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/pango-1.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/ctk -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-09-19-173409-43638-1 -x c ctklabel.c
1/* CTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.Free
16 */
17
18/*
19 * Modified by the CTK+ Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the CTK+ Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * CTK+ at ftp://ftp.ctk.org/pub/ctk/.
23 */
24
25#include "config.h"
26
27#include <math.h>
28#include <string.h>
29
30#include "ctklabel.h"
31#include "ctklabelprivate.h"
32#include "ctkaccellabel.h"
33#include "ctkbindings.h"
34#include "ctkbuildable.h"
35#include "ctkbuilderprivate.h"
36#include "ctkclipboard.h"
37#include "ctkcssshadowsvalueprivate.h"
38#include "ctkcssstylepropertyprivate.h"
39#include "ctkdnd.h"
40#include "ctkimage.h"
41#include "ctkintl.h"
42#include "ctkmain.h"
43#include "ctkmarshalers.h"
44#include "ctkmenuitem.h"
45#include "ctkmenushellprivate.h"
46#include "ctknotebook.h"
47#include "ctkpango.h"
48#include "ctkprivate.h"
49#include "ctkseparatormenuitem.h"
50#include "ctkshow.h"
51#include "ctkstylecontextprivate.h"
52#include "ctktextutil.h"
53#include "ctktooltip.h"
54#include "ctktypebuiltins.h"
55#include "ctkwidgetprivate.h"
56#include "ctkwindow.h"
57#include "ctkcssnodeprivate.h"
58#include "ctkcsscustomgadgetprivate.h"
59#include "ctkwidgetprivate.h"
60
61#include "a11y/ctklabelaccessibleprivate.h"
62
63/* this is in case rint() is not provided by the compiler,
64 * such as in the case of C89 compilers, like MSVC
65 */
66#include "fallback-c89.c"
67
68/**
69 * SECTION:ctklabel
70 * @Short_description: A widget that displays a small to medium amount of text
71 * @Title: CtkLabel
72 *
73 * The #CtkLabel widget displays a small amount of text. As the name
74 * implies, most labels are used to label another widget such as a
75 * #CtkButton, a #CtkMenuItem, or a #CtkComboBox.
76 *
77 * # CSS nodes
78 *
79 * |[<!-- language="plain" -->
80 * label
81 * ├── [selection]
82 * ├── [link]
83 * ┊
84 * ╰── [link]
85 * ]|
86 *
87 * CtkLabel has a single CSS node with the name label. A wide variety
88 * of style classes may be applied to labels, such as .title, .subtitle,
89 * .dim-label, etc. In the #CtkShortcutsWindow, labels are used wth the
90 * .keycap style class.
91 *
92 * If the label has a selection, it gets a subnode with name selection.
93 *
94 * If the label has links, there is one subnode per link. These subnodes
95 * carry the link or visited state depending on whether they have been
96 * visited.
97 *
98 * # CtkLabel as CtkBuildable
99 *
100 * The CtkLabel implementation of the CtkBuildable interface supports a
101 * custom <attributes> element, which supports any number of <attribute>
102 * elements. The <attribute> element has attributes named “name“, “value“,
103 * “start“ and “end“ and allows you to specify #PangoAttribute values for
104 * this label.
105 *
106 * An example of a UI definition fragment specifying Pango attributes:
107 * |[
108 * <object class="CtkLabel">
109 * <attributes>
110 * <attribute name="weight" value="PANGO_WEIGHT_BOLD"/>
111 * <attribute name="background" value="red" start="5" end="10"/>
112 * </attributes>
113 * </object>
114 * ]|
115 *
116 * The start and end attributes specify the range of characters to which the
117 * Pango attribute applies. If start and end are not specified, the attribute is
118 * applied to the whole text. Note that specifying ranges does not make much
119 * sense with translatable attributes. Use markup embedded in the translatable
120 * content instead.
121 *
122 * # Mnemonics
123 *
124 * Labels may contain “mnemonics”. Mnemonics are
125 * underlined characters in the label, used for keyboard navigation.
126 * Mnemonics are created by providing a string with an underscore before
127 * the mnemonic character, such as `"_File"`, to the
128 * functions ctk_label_new_with_mnemonic() or
129 * ctk_label_set_text_with_mnemonic().
130 *
131 * Mnemonics automatically activate any activatable widget the label is
132 * inside, such as a #CtkButton; if the label is not inside the
133 * mnemonic’s target widget, you have to tell the label about the target
134 * using ctk_label_set_mnemonic_widget(). Here’s a simple example where
135 * the label is inside a button:
136 *
137 * |[<!-- language="C" -->
138 * // Pressing Alt+H will activate this button
139 * CtkWidget *button = ctk_button_new ();
140 * CtkWidget *label = ctk_label_new_with_mnemonic ("_Hello");
141 * ctk_container_add (CTK_CONTAINER (button), label);
142 * ]|
143 *
144 * There’s a convenience function to create buttons with a mnemonic label
145 * already inside:
146 *
147 * |[<!-- language="C" -->
148 * // Pressing Alt+H will activate this button
149 * CtkWidget *button = ctk_button_new_with_mnemonic ("_Hello");
150 * ]|
151 *
152 * To create a mnemonic for a widget alongside the label, such as a
153 * #CtkEntry, you have to point the label at the entry with
154 * ctk_label_set_mnemonic_widget():
155 *
156 * |[<!-- language="C" -->
157 * // Pressing Alt+H will focus the entry
158 * CtkWidget *entry = ctk_entry_new ();
159 * CtkWidget *label = ctk_label_new_with_mnemonic ("_Hello");
160 * ctk_label_set_mnemonic_widget (CTK_LABEL (label), entry);
161 * ]|
162 *
163 * # Markup (styled text)
164 *
165 * To make it easy to format text in a label (changing colors,
166 * fonts, etc.), label text can be provided in a simple
167 * [markup format][PangoMarkupFormat].
168 *
169 * Here’s how to create a label with a small font:
170 * |[<!-- language="C" -->
171 * CtkWidget *label = ctk_label_new (NULL);
172 * ctk_label_set_markup (CTK_LABEL (label), "<small>Small text</small>");
173 * ]|
174 *
175 * (See [complete documentation][PangoMarkupFormat] of available
176 * tags in the Pango manual.)
177 *
178 * The markup passed to ctk_label_set_markup() must be valid; for example,
179 * literal <, > and & characters must be escaped as &lt;, &gt;, and &amp;.
180 * If you pass text obtained from the user, file, or a network to
181 * ctk_label_set_markup(), you’ll want to escape it with
182 * g_markup_escape_text() or g_markup_printf_escaped().
183 *
184 * Markup strings are just a convenient way to set the #PangoAttrList on
185 * a label; ctk_label_set_attributes() may be a simpler way to set
186 * attributes in some cases. Be careful though; #PangoAttrList tends to
187 * cause internationalization problems, unless you’re applying attributes
188 * to the entire string (i.e. unless you set the range of each attribute
189 * to [0, %G_MAXINT)). The reason is that specifying the start_index and
190 * end_index for a #PangoAttribute requires knowledge of the exact string
191 * being displayed, so translations will cause problems.
192 *
193 * # Selectable labels
194 *
195 * Labels can be made selectable with ctk_label_set_selectable().
196 * Selectable labels allow the user to copy the label contents to
197 * the clipboard. Only labels that contain useful-to-copy information
198 * — such as error messages — should be made selectable.
199 *
200 * # Text layout # {#label-text-layout}
201 *
202 * A label can contain any number of paragraphs, but will have
203 * performance problems if it contains more than a small number.
204 * Paragraphs are separated by newlines or other paragraph separators
205 * understood by Pango.
206 *
207 * Labels can automatically wrap text if you call
208 * ctk_label_set_line_wrap().
209 *
210 * ctk_label_set_justify() sets how the lines in a label align
211 * with one another. If you want to set how the label as a whole
212 * aligns in its available space, see the #CtkWidget:halign and
213 * #CtkWidget:valign properties.
214 *
215 * The #CtkLabel:width-chars and #CtkLabel:max-width-chars properties
216 * can be used to control the size allocation of ellipsized or wrapped
217 * labels. For ellipsizing labels, if either is specified (and less
218 * than the actual text size), it is used as the minimum width, and the actual
219 * text size is used as the natural width of the label. For wrapping labels,
220 * width-chars is used as the minimum width, if specified, and max-width-chars
221 * is used as the natural width. Even if max-width-chars specified, wrapping
222 * labels will be rewrapped to use all of the available width.
223 *
224 * Note that the interpretation of #CtkLabel:width-chars and
225 * #CtkLabel:max-width-chars has changed a bit with the introduction of
226 * [width-for-height geometry management.][geometry-management]
227 *
228 * # Links
229 *
230 * Since 2.18, CTK+ supports markup for clickable hyperlinks in addition
231 * to regular Pango markup. The markup for links is borrowed from HTML,
232 * using the `<a>` with “href“ and “title“ attributes. CTK+ renders links
233 * similar to the way they appear in web browsers, with colored, underlined
234 * text. The “title“ attribute is displayed as a tooltip on the link.
235 *
236 * An example looks like this:
237 *
238 * |[<!-- language="C" -->
239 * const gchar *text =
240 * "Go to the"
241 * "<a href=\"http://github.com/cafe-desktop/ctk title=\"&lt;i&gt;Our&lt;/i&gt; website\">"
242 * "CTK+ website</a> for more...";
243 * CtkWidget *label = ctk_label_new (NULL);
244 * ctk_label_set_markup (CTK_LABEL (label), text);
245 * ]|
246 *
247 * It is possible to implement custom handling for links and their tooltips with
248 * the #CtkLabel::activate-link signal and the ctk_label_get_current_uri() function.
249 */
250
251struct _CtkLabelPrivate
252{
253 CtkLabelSelectionInfo *select_info;
254 CtkWidget *mnemonic_widget;
255 CtkWindow *mnemonic_window;
256 CtkCssGadget *gadget;
257
258 PangoAttrList *attrs;
259 PangoAttrList *markup_attrs;
260 PangoLayout *layout;
261
262 gchar *label;
263 gchar *text;
264
265 gdouble angle;
266 gfloat xalign;
267 gfloat yalign;
268
269 guint mnemonics_visible : 1;
270 guint jtype : 2;
271 guint wrap : 1;
272 guint use_underline : 1;
273 guint use_markup : 1;
274 guint ellipsize : 3;
275 guint single_line_mode : 1;
276 guint have_transform : 1;
277 guint in_click : 1;
278 guint wrap_mode : 3;
279 guint pattern_set : 1;
280 guint track_links : 1;
281
282 guint mnemonic_keyval;
283
284 gint width_chars;
285 gint max_width_chars;
286 gint lines;
287};
288
289/* Notes about the handling of links:
290 *
291 * Links share the CtkLabelSelectionInfo struct with selectable labels.
292 * There are some new fields for links. The links field contains the list
293 * of CtkLabelLink structs that describe the links which are embedded in
294 * the label. The active_link field points to the link under the mouse
295 * pointer. For keyboard navigation, the “focus” link is determined by
296 * finding the link which contains the selection_anchor position.
297 * The link_clicked field is used with button press and release events
298 * to ensure that pressing inside a link and releasing outside of it
299 * does not activate the link.
300 *
301 * Links are rendered with the #CTK_STATE_FLAG_LINK/#CTK_STATE_FLAG_VISITED
302 * state flags. When the mouse pointer is over a link, the pointer is changed
303 * to indicate the link.
304 *
305 * Labels with links accept keyboard focus, and it is possible to move
306 * the focus between the embedded links using Tab/Shift-Tab. The focus
307 * is indicated by a focus rectangle that is drawn around the link text.
308 * Pressing Enter activates the focused link, and there is a suitable
309 * context menu for links that can be opened with the Menu key. Pressing
310 * Control-C copies the link URI to the clipboard.
311 *
312 * In selectable labels with links, link functionality is only available
313 * when the selection is empty.
314 */
315typedef struct
316{
317 gchar *uri;
318 gchar *title; /* the title attribute, used as tooltip */
319
320 CtkCssNode *cssnode;
321
322 gboolean visited; /* get set when the link is activated; this flag
323 * gets preserved over later set_markup() calls
324 */
325 gint start; /* position of the link in the PangoLayout */
326 gint end;
327} CtkLabelLink;
328
329struct _CtkLabelSelectionInfo
330{
331 CdkWindow *window;
332 gint selection_anchor;
333 gint selection_end;
334 CtkWidget *popup_menu;
335 CtkCssNode *selection_node;
336
337 GList *links;
338 CtkLabelLink *active_link;
339
340 CtkGesture *drag_gesture;
341 CtkGesture *multipress_gesture;
342
343 gint drag_start_x;
344 gint drag_start_y;
345
346 guint in_drag : 1;
347 guint select_words : 1;
348 guint selectable : 1;
349 guint link_clicked : 1;
350};
351
352enum {
353 MOVE_CURSOR,
354 COPY_CLIPBOARD,
355 POPULATE_POPUP,
356 ACTIVATE_LINK,
357 ACTIVATE_CURRENT_LINK,
358 LAST_SIGNAL
359};
360
361enum {
362 PROP_0,
363 PROP_LABEL,
364 PROP_ATTRIBUTES,
365 PROP_USE_MARKUP,
366 PROP_USE_UNDERLINE,
367 PROP_JUSTIFY,
368 PROP_PATTERN,
369 PROP_WRAP,
370 PROP_WRAP_MODE,
371 PROP_SELECTABLE,
372 PROP_MNEMONIC_KEYVAL,
373 PROP_MNEMONIC_WIDGET,
374 PROP_CURSOR_POSITION,
375 PROP_SELECTION_BOUND,
376 PROP_ELLIPSIZE,
377 PROP_WIDTH_CHARS,
378 PROP_SINGLE_LINE_MODE,
379 PROP_ANGLE,
380 PROP_MAX_WIDTH_CHARS,
381 PROP_TRACK_VISITED_LINKS,
382 PROP_LINES,
383 PROP_XALIGN,
384 PROP_YALIGN,
385 NUM_PROPERTIES
386};
387
388static GParamSpec *label_props[NUM_PROPERTIES] = { NULL((void*)0), };
389
390/* When rotating ellipsizable text we want the natural size to request
391 * more to ensure the label wont ever ellipsize in an allocation of full natural size.
392 * */
393#define ROTATION_ELLIPSIZE_PADDING2 2
394
395static guint signals[LAST_SIGNAL] = { 0 };
396
397static GQuark quark_shortcuts_connected;
398static GQuark quark_mnemonic_menu;
399static GQuark quark_mnemonics_visible_connected;
400static GQuark quark_ctk_signal;
401static GQuark quark_link;
402
403static void ctk_label_set_property (GObject *object,
404 guint prop_id,
405 const GValue *value,
406 GParamSpec *pspec);
407static void ctk_label_get_property (GObject *object,
408 guint prop_id,
409 GValue *value,
410 GParamSpec *pspec);
411static void ctk_label_finalize (GObject *object);
412static void ctk_label_destroy (CtkWidget *widget);
413static void ctk_label_size_allocate (CtkWidget *widget,
414 CtkAllocation *allocation);
415static void ctk_label_state_flags_changed (CtkWidget *widget,
416 CtkStateFlags prev_state);
417static void ctk_label_style_updated (CtkWidget *widget);
418static gboolean ctk_label_draw (CtkWidget *widget,
419 cairo_t *cr);
420static gboolean ctk_label_focus (CtkWidget *widget,
421 CtkDirectionType direction);
422
423static void ctk_label_realize (CtkWidget *widget);
424static void ctk_label_unrealize (CtkWidget *widget);
425static void ctk_label_map (CtkWidget *widget);
426static void ctk_label_unmap (CtkWidget *widget);
427
428static gboolean ctk_label_motion (CtkWidget *widget,
429 CdkEventMotion *event);
430static gboolean ctk_label_leave_notify (CtkWidget *widget,
431 CdkEventCrossing *event);
432
433static void ctk_label_grab_focus (CtkWidget *widget);
434
435static gboolean ctk_label_query_tooltip (CtkWidget *widget,
436 gint x,
437 gint y,
438 gboolean keyboard_tip,
439 CtkTooltip *tooltip);
440
441static void ctk_label_set_text_internal (CtkLabel *label,
442 gchar *str);
443static void ctk_label_set_label_internal (CtkLabel *label,
444 gchar *str);
445static gboolean ctk_label_set_use_markup_internal (CtkLabel *label,
446 gboolean val);
447static gboolean ctk_label_set_use_underline_internal (CtkLabel *label,
448 gboolean val);
449static void ctk_label_set_uline_text_internal (CtkLabel *label,
450 const gchar *str);
451static void ctk_label_set_pattern_internal (CtkLabel *label,
452 const gchar *pattern,
453 gboolean is_mnemonic);
454static void ctk_label_set_markup_internal (CtkLabel *label,
455 const gchar *str,
456 gboolean with_uline);
457static void ctk_label_recalculate (CtkLabel *label);
458static void ctk_label_hierarchy_changed (CtkWidget *widget,
459 CtkWidget *old_toplevel);
460static void ctk_label_screen_changed (CtkWidget *widget,
461 CdkScreen *old_screen);
462static gboolean ctk_label_popup_menu (CtkWidget *widget);
463
464static void ctk_label_create_window (CtkLabel *label);
465static void ctk_label_destroy_window (CtkLabel *label);
466static void ctk_label_ensure_select_info (CtkLabel *label);
467static void ctk_label_clear_select_info (CtkLabel *label);
468static void ctk_label_update_cursor (CtkLabel *label);
469static void ctk_label_clear_layout (CtkLabel *label);
470static void ctk_label_ensure_layout (CtkLabel *label);
471static void ctk_label_select_region_index (CtkLabel *label,
472 gint anchor_index,
473 gint end_index);
474
475static void ctk_label_update_active_link (CtkWidget *widget,
476 gdouble x,
477 gdouble y);
478
479static gboolean ctk_label_mnemonic_activate (CtkWidget *widget,
480 gboolean group_cycling);
481static void ctk_label_setup_mnemonic (CtkLabel *label,
482 guint last_key);
483static void ctk_label_drag_data_get (CtkWidget *widget,
484 CdkDragContext *context,
485 CtkSelectionData *selection_data,
486 guint info,
487 guint time);
488
489static void ctk_label_buildable_interface_init (CtkBuildableIface *iface);
490static gboolean ctk_label_buildable_custom_tag_start (CtkBuildable *buildable,
491 CtkBuilder *builder,
492 GObject *child,
493 const gchar *tagname,
494 GMarkupParser *parser,
495 gpointer *data);
496
497static void ctk_label_buildable_custom_finished (CtkBuildable *buildable,
498 CtkBuilder *builder,
499 GObject *child,
500 const gchar *tagname,
501 gpointer user_data);
502
503
504static void connect_mnemonics_visible_notify (CtkLabel *label);
505static gboolean separate_uline_pattern (const gchar *str,
506 guint *accel_key,
507 gchar **new_str,
508 gchar **pattern);
509
510
511/* For selectable labels: */
512static void ctk_label_move_cursor (CtkLabel *label,
513 CtkMovementStep step,
514 gint count,
515 gboolean extend_selection);
516static void ctk_label_copy_clipboard (CtkLabel *label);
517static void ctk_label_select_all (CtkLabel *label);
518static void ctk_label_do_popup (CtkLabel *label,
519 const CdkEvent *event);
520static gint ctk_label_move_forward_word (CtkLabel *label,
521 gint start);
522static gint ctk_label_move_backward_word (CtkLabel *label,
523 gint start);
524
525/* For links: */
526static void ctk_label_clear_links (CtkLabel *label);
527static gboolean ctk_label_activate_link (CtkLabel *label,
528 const gchar *uri);
529static void ctk_label_activate_current_link (CtkLabel *label);
530static CtkLabelLink *ctk_label_get_current_link (CtkLabel *label);
531static void emit_activate_link (CtkLabel *label,
532 CtkLabelLink *link);
533
534/* Event controller callbacks */
535static void ctk_label_multipress_gesture_pressed (CtkGestureMultiPress *gesture,
536 gint n_press,
537 gdouble x,
538 gdouble y,
539 CtkLabel *label);
540static void ctk_label_multipress_gesture_released (CtkGestureMultiPress *gesture,
541 gint n_press,
542 gdouble x,
543 gdouble y,
544 CtkLabel *label);
545static void ctk_label_drag_gesture_begin (CtkGestureDrag *gesture,
546 gdouble start_x,
547 gdouble start_y,
548 CtkLabel *label);
549static void ctk_label_drag_gesture_update (CtkGestureDrag *gesture,
550 gdouble offset_x,
551 gdouble offset_y,
552 CtkLabel *label);
553
554static CtkSizeRequestMode ctk_label_get_request_mode (CtkWidget *widget);
555static void ctk_label_get_preferred_width (CtkWidget *widget,
556 gint *minimum_size,
557 gint *natural_size);
558static void ctk_label_get_preferred_height (CtkWidget *widget,
559 gint *minimum_size,
560 gint *natural_size);
561static void ctk_label_get_preferred_width_for_height (CtkWidget *widget,
562 gint height,
563 gint *minimum_width,
564 gint *natural_width);
565static void ctk_label_get_preferred_height_for_width (CtkWidget *widget,
566 gint width,
567 gint *minimum_height,
568 gint *natural_height);
569static void ctk_label_get_preferred_height_and_baseline_for_width (CtkWidget *widget,
570 gint width,
571 gint *minimum_height,
572 gint *natural_height,
573 gint *minimum_baseline,
574 gint *natural_baseline);
575
576static void ctk_label_measure (CtkCssGadget *gadget,
577 CtkOrientation orientation,
578 int for_size,
579 int *minimum,
580 int *natural,
581 int *minimum_baseline,
582 int *natural_baseline,
583 gpointer unused);
584static gboolean ctk_label_render (CtkCssGadget *gadget,
585 cairo_t *cr,
586 int x,
587 int y,
588 int width,
589 int height,
590 gpointer data);
591
592static CtkBuildableIface *buildable_parent_iface = NULL((void*)0);
593
594G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
595G_DEFINE_TYPE_WITH_CODE (CtkLabel, ctk_label, CTK_TYPE_MISC,static void ctk_label_init (CtkLabel *self); static void ctk_label_class_init
(CtkLabelClass *klass); static GType ctk_label_get_type_once
(void); static gpointer ctk_label_parent_class = ((void*)0);
static gint CtkLabel_private_offset; static void ctk_label_class_intern_init
(gpointer klass) { ctk_label_parent_class = g_type_class_peek_parent
(klass); if (CtkLabel_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkLabel_private_offset); ctk_label_class_init (
(CtkLabelClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer ctk_label_get_instance_private (CtkLabel *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CtkLabel_private_offset
)))); } GType ctk_label_get_type (void) { static GType static_g_define_type_id
= 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) * (&static_g_define_type_id) : ((void*)
0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_label_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_label_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple ((ctk_misc_get_type
()), g_intern_static_string ("CtkLabel"), sizeof (CtkLabelClass
), (GClassInitFunc)(void (*)(void)) ctk_label_class_intern_init
, sizeof (CtkLabel), (GInstanceInitFunc)(void (*)(void)) ctk_label_init
, (GTypeFlags) 0); { {{ CtkLabel_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkLabelPrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) ctk_label_buildable_interface_init, ((void*)0), ((void
*)0) }; g_type_add_interface_static (g_define_type_id, (ctk_buildable_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
596 G_ADD_PRIVATE (CtkLabel)static void ctk_label_init (CtkLabel *self); static void ctk_label_class_init
(CtkLabelClass *klass); static GType ctk_label_get_type_once
(void); static gpointer ctk_label_parent_class = ((void*)0);
static gint CtkLabel_private_offset; static void ctk_label_class_intern_init
(gpointer klass) { ctk_label_parent_class = g_type_class_peek_parent
(klass); if (CtkLabel_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkLabel_private_offset); ctk_label_class_init (
(CtkLabelClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer ctk_label_get_instance_private (CtkLabel *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CtkLabel_private_offset
)))); } GType ctk_label_get_type (void) { static GType static_g_define_type_id
= 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) * (&static_g_define_type_id) : ((void*)
0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_label_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_label_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple ((ctk_misc_get_type
()), g_intern_static_string ("CtkLabel"), sizeof (CtkLabelClass
), (GClassInitFunc)(void (*)(void)) ctk_label_class_intern_init
, sizeof (CtkLabel), (GInstanceInitFunc)(void (*)(void)) ctk_label_init
, (GTypeFlags) 0); { {{ CtkLabel_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkLabelPrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) ctk_label_buildable_interface_init, ((void*)0), ((void
*)0) }; g_type_add_interface_static (g_define_type_id, (ctk_buildable_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
597 G_IMPLEMENT_INTERFACE (CTK_TYPE_BUILDABLE,static void ctk_label_init (CtkLabel *self); static void ctk_label_class_init
(CtkLabelClass *klass); static GType ctk_label_get_type_once
(void); static gpointer ctk_label_parent_class = ((void*)0);
static gint CtkLabel_private_offset; static void ctk_label_class_intern_init
(gpointer klass) { ctk_label_parent_class = g_type_class_peek_parent
(klass); if (CtkLabel_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkLabel_private_offset); ctk_label_class_init (
(CtkLabelClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer ctk_label_get_instance_private (CtkLabel *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CtkLabel_private_offset
)))); } GType ctk_label_get_type (void) { static GType static_g_define_type_id
= 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) * (&static_g_define_type_id) : ((void*)
0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_label_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_label_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple ((ctk_misc_get_type
()), g_intern_static_string ("CtkLabel"), sizeof (CtkLabelClass
), (GClassInitFunc)(void (*)(void)) ctk_label_class_intern_init
, sizeof (CtkLabel), (GInstanceInitFunc)(void (*)(void)) ctk_label_init
, (GTypeFlags) 0); { {{ CtkLabel_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkLabelPrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) ctk_label_buildable_interface_init, ((void*)0), ((void
*)0) }; g_type_add_interface_static (g_define_type_id, (ctk_buildable_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
598 ctk_label_buildable_interface_init))static void ctk_label_init (CtkLabel *self); static void ctk_label_class_init
(CtkLabelClass *klass); static GType ctk_label_get_type_once
(void); static gpointer ctk_label_parent_class = ((void*)0);
static gint CtkLabel_private_offset; static void ctk_label_class_intern_init
(gpointer klass) { ctk_label_parent_class = g_type_class_peek_parent
(klass); if (CtkLabel_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkLabel_private_offset); ctk_label_class_init (
(CtkLabelClass*) klass); } __attribute__ ((__unused__)) static
inline gpointer ctk_label_get_instance_private (CtkLabel *self
) { return (((gpointer) ((guint8*) (self) + (glong) (CtkLabel_private_offset
)))); } GType ctk_label_get_type (void) { static GType static_g_define_type_id
= 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) * (&static_g_define_type_id) : ((void*)
0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_label_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_label_get_type_once (void) {
GType g_define_type_id = g_type_register_static_simple ((ctk_misc_get_type
()), g_intern_static_string ("CtkLabel"), sizeof (CtkLabelClass
), (GClassInitFunc)(void (*)(void)) ctk_label_class_intern_init
, sizeof (CtkLabel), (GInstanceInitFunc)(void (*)(void)) ctk_label_init
, (GTypeFlags) 0); { {{ CtkLabel_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (CtkLabelPrivate)); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) ctk_label_buildable_interface_init, ((void*)0), ((void
*)0) }; g_type_add_interface_static (g_define_type_id, (ctk_buildable_get_type
()), &g_implement_interface_info); };} } return g_define_type_id
; }
599G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop
600
601static void
602add_move_binding (CtkBindingSet *binding_set,
603 guint keyval,
604 guint modmask,
605 CtkMovementStep step,
606 gint count)
607{
608 g_return_if_fail ((modmask & CDK_SHIFT_MASK) == 0)do { if (((modmask & CDK_SHIFT_MASK) == 0)) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "(modmask & CDK_SHIFT_MASK) == 0"
); return; } } while (0)
;
609
610 ctk_binding_entry_add_signal (binding_set, keyval, modmask,
611 "move-cursor", 3,
612 G_TYPE_ENUM((GType) ((12) << (2))), step,
613 G_TYPE_INT((GType) ((6) << (2))), count,
614 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0));
615
616 /* Selection-extending version */
617 ctk_binding_entry_add_signal (binding_set, keyval, modmask | CDK_SHIFT_MASK,
618 "move-cursor", 3,
619 G_TYPE_ENUM((GType) ((12) << (2))), step,
620 G_TYPE_INT((GType) ((6) << (2))), count,
621 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
622}
623
624static void
625ctk_label_class_init (CtkLabelClass *class)
626{
627 GObjectClass *gobject_class = G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), (((GType) ((20) << (2))))))))
;
628 CtkWidgetClass *widget_class = CTK_WIDGET_CLASS (class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((class)), ((ctk_widget_get_type ()))))))
;
629 CtkBindingSet *binding_set;
630
631 gobject_class->set_property = ctk_label_set_property;
632 gobject_class->get_property = ctk_label_get_property;
633 gobject_class->finalize = ctk_label_finalize;
634
635 widget_class->destroy = ctk_label_destroy;
636 widget_class->size_allocate = ctk_label_size_allocate;
637 widget_class->state_flags_changed = ctk_label_state_flags_changed;
638 widget_class->style_updated = ctk_label_style_updated;
639 widget_class->query_tooltip = ctk_label_query_tooltip;
640 widget_class->draw = ctk_label_draw;
641 widget_class->realize = ctk_label_realize;
642 widget_class->unrealize = ctk_label_unrealize;
643 widget_class->map = ctk_label_map;
644 widget_class->unmap = ctk_label_unmap;
645 widget_class->motion_notify_event = ctk_label_motion;
646 widget_class->leave_notify_event = ctk_label_leave_notify;
647 widget_class->hierarchy_changed = ctk_label_hierarchy_changed;
648 widget_class->screen_changed = ctk_label_screen_changed;
649 widget_class->mnemonic_activate = ctk_label_mnemonic_activate;
650 widget_class->drag_data_get = ctk_label_drag_data_get;
651 widget_class->grab_focus = ctk_label_grab_focus;
652 widget_class->popup_menu = ctk_label_popup_menu;
653 widget_class->focus = ctk_label_focus;
654 widget_class->get_request_mode = ctk_label_get_request_mode;
655 widget_class->get_preferred_width = ctk_label_get_preferred_width;
656 widget_class->get_preferred_height = ctk_label_get_preferred_height;
657 widget_class->get_preferred_width_for_height = ctk_label_get_preferred_width_for_height;
658 widget_class->get_preferred_height_for_width = ctk_label_get_preferred_height_for_width;
659 widget_class->get_preferred_height_and_baseline_for_width = ctk_label_get_preferred_height_and_baseline_for_width;
660
661 class->move_cursor = ctk_label_move_cursor;
662 class->copy_clipboard = ctk_label_copy_clipboard;
663 class->activate_link = ctk_label_activate_link;
664
665 /**
666 * CtkLabel::move-cursor:
667 * @entry: the object which received the signal
668 * @step: the granularity of the move, as a #CtkMovementStep
669 * @count: the number of @step units to move
670 * @extend_selection: %TRUE if the move should extend the selection
671 *
672 * The ::move-cursor signal is a
673 * [keybinding signal][CtkBindingSignal]
674 * which gets emitted when the user initiates a cursor movement.
675 * If the cursor is not visible in @entry, this signal causes
676 * the viewport to be moved instead.
677 *
678 * Applications should not connect to it, but may emit it with
679 * g_signal_emit_by_name() if they need to control the cursor
680 * programmatically.
681 *
682 * The default bindings for this signal come in two variants,
683 * the variant with the Shift modifier extends the selection,
684 * the variant without the Shift modifer does not.
685 * There are too many key combinations to list them all here.
686 * - Arrow keys move by individual characters/lines
687 * - Ctrl-arrow key combinations move by words/paragraphs
688 * - Home/End keys move to the ends of the buffer
689 */
690 signals[MOVE_CURSOR] =
691 g_signal_new (I_("move-cursor")g_intern_static_string ("move-cursor"),
692 G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)),
693 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
694 G_STRUCT_OFFSET (CtkLabelClass, move_cursor)((glong) __builtin_offsetof(CtkLabelClass, move_cursor)),
695 NULL((void*)0), NULL((void*)0),
696 _ctk_marshal_VOID__ENUM_INT_BOOLEAN,
697 G_TYPE_NONE((GType) ((1) << (2))), 3,
698 CTK_TYPE_MOVEMENT_STEP(ctk_movement_step_get_type ()),
699 G_TYPE_INT((GType) ((6) << (2))),
700 G_TYPE_BOOLEAN((GType) ((5) << (2))));
701
702 /**
703 * CtkLabel::copy-clipboard:
704 * @label: the object which received the signal
705 *
706 * The ::copy-clipboard signal is a
707 * [keybinding signal][CtkBindingSignal]
708 * which gets emitted to copy the selection to the clipboard.
709 *
710 * The default binding for this signal is Ctrl-c.
711 */
712 signals[COPY_CLIPBOARD] =
713 g_signal_new (I_("copy-clipboard")g_intern_static_string ("copy-clipboard"),
714 G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)),
715 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
716 G_STRUCT_OFFSET (CtkLabelClass, copy_clipboard)((glong) __builtin_offsetof(CtkLabelClass, copy_clipboard)),
717 NULL((void*)0), NULL((void*)0),
718 NULL((void*)0),
719 G_TYPE_NONE((GType) ((1) << (2))), 0);
720
721 /**
722 * CtkLabel::populate-popup:
723 * @label: The label on which the signal is emitted
724 * @menu: the menu that is being populated
725 *
726 * The ::populate-popup signal gets emitted before showing the
727 * context menu of the label. Note that only selectable labels
728 * have context menus.
729 *
730 * If you need to add items to the context menu, connect
731 * to this signal and append your menuitems to the @menu.
732 */
733 signals[POPULATE_POPUP] =
734 g_signal_new (I_("populate-popup")g_intern_static_string ("populate-popup"),
735 G_OBJECT_CLASS_TYPE (gobject_class)((((GTypeClass*) (gobject_class))->g_type)),
736 G_SIGNAL_RUN_LAST,
737 G_STRUCT_OFFSET (CtkLabelClass, populate_popup)((glong) __builtin_offsetof(CtkLabelClass, populate_popup)),
738 NULL((void*)0), NULL((void*)0),
739 NULL((void*)0),
740 G_TYPE_NONE((GType) ((1) << (2))), 1,
741 CTK_TYPE_MENU(ctk_menu_get_type ()));
742
743 /**
744 * CtkLabel::activate-current-link:
745 * @label: The label on which the signal was emitted
746 *
747 * A [keybinding signal][CtkBindingSignal]
748 * which gets emitted when the user activates a link in the label.
749 *
750 * Applications may also emit the signal with g_signal_emit_by_name()
751 * if they need to control activation of URIs programmatically.
752 *
753 * The default bindings for this signal are all forms of the Enter key.
754 *
755 * Since: 2.18
756 */
757 signals[ACTIVATE_CURRENT_LINK] =
758 g_signal_new_class_handler (I_("activate-current-link")g_intern_static_string ("activate-current-link"),
759 G_TYPE_FROM_CLASS (gobject_class)(((GTypeClass*) (gobject_class))->g_type),
760 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
761 G_CALLBACK (ctk_label_activate_current_link)((GCallback) (ctk_label_activate_current_link)),
762 NULL((void*)0), NULL((void*)0),
763 NULL((void*)0),
764 G_TYPE_NONE((GType) ((1) << (2))), 0);
765
766 /**
767 * CtkLabel::activate-link:
768 * @label: The label on which the signal was emitted
769 * @uri: the URI that is activated
770 *
771 * The signal which gets emitted to activate a URI.
772 * Applications may connect to it to override the default behaviour,
773 * which is to call ctk_show_uri_on_window().
774 *
775 * Returns: %TRUE if the link has been activated
776 *
777 * Since: 2.18
778 */
779 signals[ACTIVATE_LINK] =
780 g_signal_new (I_("activate-link")g_intern_static_string ("activate-link"),
781 G_TYPE_FROM_CLASS (gobject_class)(((GTypeClass*) (gobject_class))->g_type),
782 G_SIGNAL_RUN_LAST,
783 G_STRUCT_OFFSET (CtkLabelClass, activate_link)((glong) __builtin_offsetof(CtkLabelClass, activate_link)),
784 _ctk_boolean_handled_accumulator, NULL((void*)0),
785 _ctk_marshal_BOOLEAN__STRING,
786 G_TYPE_BOOLEAN((GType) ((5) << (2))), 1, G_TYPE_STRING((GType) ((16) << (2))));
787
788 /**
789 * CtkLabel:label:
790 *
791 * The contents of the label.
792 *
793 * If the string contains [Pango XML markup][PangoMarkupFormat], you will
794 * have to set the #CtkLabel:use-markup property to %TRUE in order for the
795 * label to display the markup attributes. See also ctk_label_set_markup()
796 * for a convenience function that sets both this property and the
797 * #CtkLabel:use-markup property at the same time.
798 *
799 * If the string contains underlines acting as mnemonics, you will have to
800 * set the #CtkLabel:use-underline property to %TRUE in order for the label
801 * to display them.
802 */
803 label_props[PROP_LABEL] =
804 g_param_spec_string ("label",
805 P_("Label")g_dgettext("ctk30" "-properties","Label"),
806 P_("The text of the label")g_dgettext("ctk30" "-properties","The text of the label"),
807 "",
808 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
809
810 label_props[PROP_ATTRIBUTES] =
811 g_param_spec_boxed ("attributes",
812 P_("Attributes")g_dgettext("ctk30" "-properties","Attributes"),
813 P_("A list of style attributes to apply to the text of the label")g_dgettext("ctk30" "-properties","A list of style attributes to apply to the text of the label"
)
,
814 PANGO_TYPE_ATTR_LISTpango_attr_list_get_type (),
815 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
816
817 label_props[PROP_USE_MARKUP] =
818 g_param_spec_boolean ("use-markup",
819 P_("Use markup")g_dgettext("ctk30" "-properties","Use markup"),
820 P_("The text of the label includes XML markup. See pango_parse_markup()")g_dgettext("ctk30" "-properties","The text of the label includes XML markup. See pango_parse_markup()"
)
,
821 FALSE(0),
822 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
823
824 label_props[PROP_USE_UNDERLINE] =
825 g_param_spec_boolean ("use-underline",
826 P_("Use underline")g_dgettext("ctk30" "-properties","Use underline"),
827 P_("If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key")g_dgettext("ctk30" "-properties","If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key"
)
,
828 FALSE(0),
829 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
830
831 label_props[PROP_JUSTIFY] =
832 g_param_spec_enum ("justify",
833 P_("Justification")g_dgettext("ctk30" "-properties","Justification"),
834 P_("The alignment of the lines in the text of the label relative to each other. This does NOT affect the alignment of the label within its allocation. See CtkLabel:xalign for that")g_dgettext("ctk30" "-properties","The alignment of the lines in the text of the label relative to each other. This does NOT affect the alignment of the label within its allocation. See CtkLabel:xalign for that"
)
,
835 CTK_TYPE_JUSTIFICATION(ctk_justification_get_type ()),
836 CTK_JUSTIFY_LEFT,
837 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
838
839 /**
840 * CtkLabel:xalign:
841 *
842 * The xalign property determines the horizontal aligment of the label text
843 * inside the labels size allocation. Compare this to #CtkWidget:halign,
844 * which determines how the labels size allocation is positioned in the
845 * space available for the label.
846 *
847 * Since: 3.16
848 */
849 label_props[PROP_XALIGN] =
850 g_param_spec_float ("xalign",
851 P_("X align")g_dgettext("ctk30" "-properties","X align"),
852 P_("The horizontal alignment, from 0 (left) to 1 (right). Reversed for RTL layouts.")g_dgettext("ctk30" "-properties","The horizontal alignment, from 0 (left) to 1 (right). Reversed for RTL layouts."
)
,
853 0.0, 1.0,
854 0.5,
855 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
856
857 /**
858 * CtkLabel:yalign:
859 *
860 * The yalign property determines the vertical aligment of the label text
861 * inside the labels size allocation. Compare this to #CtkWidget:valign,
862 * which determines how the labels size allocation is positioned in the
863 * space available for the label.
864 *
865 * Since: 3.16
866 */
867 label_props[PROP_YALIGN] =
868 g_param_spec_float ("yalign",
869 P_("Y align")g_dgettext("ctk30" "-properties","Y align"),
870 P_("The vertical alignment, from 0 (top) to 1 (bottom)")g_dgettext("ctk30" "-properties","The vertical alignment, from 0 (top) to 1 (bottom)"
)
,
871 0.0, 1.0,
872 0.5,
873 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
874
875 label_props[PROP_PATTERN] =
876 g_param_spec_string ("pattern",
877 P_("Pattern")g_dgettext("ctk30" "-properties","Pattern"),
878 P_("A string with _ characters in positions correspond to characters in the text to underline")g_dgettext("ctk30" "-properties","A string with _ characters in positions correspond to characters in the text to underline"
)
,
879 NULL((void*)0),
880 CTK_PARAM_WRITABLEG_PARAM_WRITABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
881
882 label_props[PROP_WRAP] =
883 g_param_spec_boolean ("wrap",
884 P_("Line wrap")g_dgettext("ctk30" "-properties","Line wrap"),
885 P_("If set, wrap lines if the text becomes too wide")g_dgettext("ctk30" "-properties","If set, wrap lines if the text becomes too wide"
)
,
886 FALSE(0),
887 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
888
889 /**
890 * CtkLabel:wrap-mode:
891 *
892 * If line wrapping is on (see the #CtkLabel:wrap property) this controls
893 * how the line wrapping is done. The default is %PANGO_WRAP_WORD, which
894 * means wrap on word boundaries.
895 *
896 * Since: 2.10
897 */
898 label_props[PROP_WRAP_MODE] =
899 g_param_spec_enum ("wrap-mode",
900 P_("Line wrap mode")g_dgettext("ctk30" "-properties","Line wrap mode"),
901 P_("If wrap is set, controls how linewrapping is done")g_dgettext("ctk30" "-properties","If wrap is set, controls how linewrapping is done"
)
,
902 PANGO_TYPE_WRAP_MODE(pango_wrap_mode_get_type ()),
903 PANGO_WRAP_WORD,
904 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
905
906 label_props[PROP_SELECTABLE] =
907 g_param_spec_boolean ("selectable",
908 P_("Selectable")g_dgettext("ctk30" "-properties","Selectable"),
909 P_("Whether the label text can be selected with the mouse")g_dgettext("ctk30" "-properties","Whether the label text can be selected with the mouse"
)
,
910 FALSE(0),
911 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
912
913 label_props[PROP_MNEMONIC_KEYVAL] =
914 g_param_spec_uint ("mnemonic-keyval",
915 P_("Mnemonic key")g_dgettext("ctk30" "-properties","Mnemonic key"),
916 P_("The mnemonic accelerator key for this label")g_dgettext("ctk30" "-properties","The mnemonic accelerator key for this label"
)
,
917 0, G_MAXUINT(2147483647 *2U +1U),
918 CDK_KEY_VoidSymbol0xffffff,
919 CTK_PARAM_READABLEG_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
920
921 label_props[PROP_MNEMONIC_WIDGET] =
922 g_param_spec_object ("mnemonic-widget",
923 P_("Mnemonic widget")g_dgettext("ctk30" "-properties","Mnemonic widget"),
924 P_("The widget to be activated when the label's mnemonic key is pressed")g_dgettext("ctk30" "-properties","The widget to be activated when the label's mnemonic key is pressed"
)
,
925 CTK_TYPE_WIDGET(ctk_widget_get_type ()),
926 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
927
928 label_props[PROP_CURSOR_POSITION] =
929 g_param_spec_int ("cursor-position",
930 P_("Cursor Position")g_dgettext("ctk30" "-properties","Cursor Position"),
931 P_("The current position of the insertion cursor in chars")g_dgettext("ctk30" "-properties","The current position of the insertion cursor in chars"
)
,
932 0, G_MAXINT2147483647,
933 0,
934 CTK_PARAM_READABLEG_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
935
936 label_props[PROP_SELECTION_BOUND] =
937 g_param_spec_int ("selection-bound",
938 P_("Selection Bound")g_dgettext("ctk30" "-properties","Selection Bound"),
939 P_("The position of the opposite end of the selection from the cursor in chars")g_dgettext("ctk30" "-properties","The position of the opposite end of the selection from the cursor in chars"
)
,
940 0, G_MAXINT2147483647,
941 0,
942 CTK_PARAM_READABLEG_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB);
943
944 /**
945 * CtkLabel:ellipsize:
946 *
947 * The preferred place to ellipsize the string, if the label does
948 * not have enough room to display the entire string, specified as a
949 * #PangoEllipsizeMode.
950 *
951 * Note that setting this property to a value other than
952 * %PANGO_ELLIPSIZE_NONE has the side-effect that the label requests
953 * only enough space to display the ellipsis "...". In particular, this
954 * means that ellipsizing labels do not work well in notebook tabs, unless
955 * the #CtkNotebook tab-expand child property is set to %TRUE. Other ways
956 * to set a label's width are ctk_widget_set_size_request() and
957 * ctk_label_set_width_chars().
958 *
959 * Since: 2.6
960 */
961 label_props[PROP_ELLIPSIZE] =
962 g_param_spec_enum ("ellipsize",
963 P_("Ellipsize")g_dgettext("ctk30" "-properties","Ellipsize"),
964 P_("The preferred place to ellipsize the string, if the label does not have enough room to display the entire string")g_dgettext("ctk30" "-properties","The preferred place to ellipsize the string, if the label does not have enough room to display the entire string"
)
,
965 PANGO_TYPE_ELLIPSIZE_MODE(pango_ellipsize_mode_get_type ()),
966 PANGO_ELLIPSIZE_NONE,
967 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
968
969 /**
970 * CtkLabel:width-chars:
971 *
972 * The desired width of the label, in characters. If this property is set to
973 * -1, the width will be calculated automatically.
974 *
975 * See the section on [text layout][label-text-layout]
976 * for details of how #CtkLabel:width-chars and #CtkLabel:max-width-chars
977 * determine the width of ellipsized and wrapped labels.
978 *
979 * Since: 2.6
980 **/
981 label_props[PROP_WIDTH_CHARS] =
982 g_param_spec_int ("width-chars",
983 P_("Width In Characters")g_dgettext("ctk30" "-properties","Width In Characters"),
984 P_("The desired width of the label, in characters")g_dgettext("ctk30" "-properties","The desired width of the label, in characters"
)
,
985 -1, G_MAXINT2147483647,
986 -1,
987 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
988
989 /**
990 * CtkLabel:single-line-mode:
991 *
992 * Whether the label is in single line mode. In single line mode,
993 * the height of the label does not depend on the actual text, it
994 * is always set to ascent + descent of the font. This can be an
995 * advantage in situations where resizing the label because of text
996 * changes would be distracting, e.g. in a statusbar.
997 *
998 * Since: 2.6
999 **/
1000 label_props[PROP_SINGLE_LINE_MODE] =
1001 g_param_spec_boolean ("single-line-mode",
1002 P_("Single Line Mode")g_dgettext("ctk30" "-properties","Single Line Mode"),
1003 P_("Whether the label is in single line mode")g_dgettext("ctk30" "-properties","Whether the label is in single line mode"
)
,
1004 FALSE(0),
1005 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1006
1007 /**
1008 * CtkLabel:angle:
1009 *
1010 * The angle that the baseline of the label makes with the horizontal,
1011 * in degrees, measured counterclockwise. An angle of 90 reads from
1012 * from bottom to top, an angle of 270, from top to bottom. Ignored
1013 * if the label is selectable.
1014 *
1015 * Since: 2.6
1016 **/
1017 label_props[PROP_ANGLE] =
1018 g_param_spec_double ("angle",
1019 P_("Angle")g_dgettext("ctk30" "-properties","Angle"),
1020 P_("Angle at which the label is rotated")g_dgettext("ctk30" "-properties","Angle at which the label is rotated"
)
,
1021 0.0, 360.0,
1022 0.0,
1023 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1024
1025 /**
1026 * CtkLabel:max-width-chars:
1027 *
1028 * The desired maximum width of the label, in characters. If this property
1029 * is set to -1, the width will be calculated automatically.
1030 *
1031 * See the section on [text layout][label-text-layout]
1032 * for details of how #CtkLabel:width-chars and #CtkLabel:max-width-chars
1033 * determine the width of ellipsized and wrapped labels.
1034 *
1035 * Since: 2.6
1036 **/
1037 label_props[PROP_MAX_WIDTH_CHARS] =
1038 g_param_spec_int ("max-width-chars",
1039 P_("Maximum Width In Characters")g_dgettext("ctk30" "-properties","Maximum Width In Characters"
)
,
1040 P_("The desired maximum width of the label, in characters")g_dgettext("ctk30" "-properties","The desired maximum width of the label, in characters"
)
,
1041 -1, G_MAXINT2147483647,
1042 -1,
1043 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1044
1045 /**
1046 * CtkLabel:track-visited-links:
1047 *
1048 * Set this property to %TRUE to make the label track which links
1049 * have been visited. It will then apply the #CTK_STATE_FLAG_VISITED
1050 * when rendering this link, in addition to #CTK_STATE_FLAG_LINK.
1051 *
1052 * Since: 2.18
1053 */
1054 label_props[PROP_TRACK_VISITED_LINKS] =
1055 g_param_spec_boolean ("track-visited-links",
1056 P_("Track visited links")g_dgettext("ctk30" "-properties","Track visited links"),
1057 P_("Whether visited links should be tracked")g_dgettext("ctk30" "-properties","Whether visited links should be tracked"
)
,
1058 TRUE(!(0)),
1059 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1060
1061 /**
1062 * CtkLabel:lines:
1063 *
1064 * The number of lines to which an ellipsized, wrapping label
1065 * should be limited. This property has no effect if the
1066 * label is not wrapping or ellipsized. Set this property to
1067 * -1 if you don't want to limit the number of lines.
1068 *
1069 * Since: 3.10
1070 */
1071 label_props[PROP_LINES] =
1072 g_param_spec_int ("lines",
1073 P_("Number of lines")g_dgettext("ctk30" "-properties","Number of lines"),
1074 P_("The desired number of lines, when ellipsizing a wrapping label")g_dgettext("ctk30" "-properties","The desired number of lines, when ellipsizing a wrapping label"
)
,
1075 -1, G_MAXINT2147483647,
1076 -1,
1077 CTK_PARAM_READWRITEG_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB|G_PARAM_EXPLICIT_NOTIFY);
1078
1079 g_object_class_install_properties (gobject_class, NUM_PROPERTIES, label_props);
1080
1081 /*
1082 * Key bindings
1083 */
1084 binding_set = ctk_binding_set_by_class (class);
1085
1086 /* Moving the insertion point */
1087 add_move_binding (binding_set, CDK_KEY_Right0xff53, 0,
1088 CTK_MOVEMENT_VISUAL_POSITIONS, 1);
1089
1090 add_move_binding (binding_set, CDK_KEY_Left0xff51, 0,
1091 CTK_MOVEMENT_VISUAL_POSITIONS, -1);
1092
1093 add_move_binding (binding_set, CDK_KEY_KP_Right0xff98, 0,
1094 CTK_MOVEMENT_VISUAL_POSITIONS, 1);
1095
1096 add_move_binding (binding_set, CDK_KEY_KP_Left0xff96, 0,
1097 CTK_MOVEMENT_VISUAL_POSITIONS, -1);
1098
1099 add_move_binding (binding_set, CDK_KEY_f0x066, CDK_CONTROL_MASK,
1100 CTK_MOVEMENT_LOGICAL_POSITIONS, 1);
1101
1102 add_move_binding (binding_set, CDK_KEY_b0x062, CDK_CONTROL_MASK,
1103 CTK_MOVEMENT_LOGICAL_POSITIONS, -1);
1104
1105 add_move_binding (binding_set, CDK_KEY_Right0xff53, CDK_CONTROL_MASK,
1106 CTK_MOVEMENT_WORDS, 1);
1107
1108 add_move_binding (binding_set, CDK_KEY_Left0xff51, CDK_CONTROL_MASK,
1109 CTK_MOVEMENT_WORDS, -1);
1110
1111 add_move_binding (binding_set, CDK_KEY_KP_Right0xff98, CDK_CONTROL_MASK,
1112 CTK_MOVEMENT_WORDS, 1);
1113
1114 add_move_binding (binding_set, CDK_KEY_KP_Left0xff96, CDK_CONTROL_MASK,
1115 CTK_MOVEMENT_WORDS, -1);
1116
1117 /* select all */
1118 ctk_binding_entry_add_signal (binding_set, CDK_KEY_a0x061, CDK_CONTROL_MASK,
1119 "move-cursor", 3,
1120 G_TYPE_ENUM((GType) ((12) << (2))), CTK_MOVEMENT_PARAGRAPH_ENDS,
1121 G_TYPE_INT((GType) ((6) << (2))), -1,
1122 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0));
1123
1124 ctk_binding_entry_add_signal (binding_set, CDK_KEY_a0x061, CDK_CONTROL_MASK,
1125 "move-cursor", 3,
1126 G_TYPE_ENUM((GType) ((12) << (2))), CTK_MOVEMENT_PARAGRAPH_ENDS,
1127 G_TYPE_INT((GType) ((6) << (2))), 1,
1128 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1129
1130 ctk_binding_entry_add_signal (binding_set, CDK_KEY_slash0x02f, CDK_CONTROL_MASK,
1131 "move-cursor", 3,
1132 G_TYPE_ENUM((GType) ((12) << (2))), CTK_MOVEMENT_PARAGRAPH_ENDS,
1133 G_TYPE_INT((GType) ((6) << (2))), -1,
1134 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0));
1135
1136 ctk_binding_entry_add_signal (binding_set, CDK_KEY_slash0x02f, CDK_CONTROL_MASK,
1137 "move-cursor", 3,
1138 G_TYPE_ENUM((GType) ((12) << (2))), CTK_MOVEMENT_PARAGRAPH_ENDS,
1139 G_TYPE_INT((GType) ((6) << (2))), 1,
1140 G_TYPE_BOOLEAN((GType) ((5) << (2))), TRUE(!(0)));
1141
1142 /* unselect all */
1143 ctk_binding_entry_add_signal (binding_set, CDK_KEY_a0x061, CDK_SHIFT_MASK | CDK_CONTROL_MASK,
1144 "move-cursor", 3,
1145 G_TYPE_ENUM((GType) ((12) << (2))), CTK_MOVEMENT_PARAGRAPH_ENDS,
1146 G_TYPE_INT((GType) ((6) << (2))), 0,
1147 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0));
1148
1149 ctk_binding_entry_add_signal (binding_set, CDK_KEY_backslash0x05c, CDK_CONTROL_MASK,
1150 "move-cursor", 3,
1151 G_TYPE_ENUM((GType) ((12) << (2))), CTK_MOVEMENT_PARAGRAPH_ENDS,
1152 G_TYPE_INT((GType) ((6) << (2))), 0,
1153 G_TYPE_BOOLEAN((GType) ((5) << (2))), FALSE(0));
1154
1155 add_move_binding (binding_set, CDK_KEY_f0x066, CDK_MOD1_MASK,
1156 CTK_MOVEMENT_WORDS, 1);
1157
1158 add_move_binding (binding_set, CDK_KEY_b0x062, CDK_MOD1_MASK,
1159 CTK_MOVEMENT_WORDS, -1);
1160
1161 add_move_binding (binding_set, CDK_KEY_Home0xff50, 0,
1162 CTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
1163
1164 add_move_binding (binding_set, CDK_KEY_End0xff57, 0,
1165 CTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
1166
1167 add_move_binding (binding_set, CDK_KEY_KP_Home0xff95, 0,
1168 CTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
1169
1170 add_move_binding (binding_set, CDK_KEY_KP_End0xff9c, 0,
1171 CTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
1172
1173 add_move_binding (binding_set, CDK_KEY_Home0xff50, CDK_CONTROL_MASK,
1174 CTK_MOVEMENT_BUFFER_ENDS, -1);
1175
1176 add_move_binding (binding_set, CDK_KEY_End0xff57, CDK_CONTROL_MASK,
1177 CTK_MOVEMENT_BUFFER_ENDS, 1);
1178
1179 add_move_binding (binding_set, CDK_KEY_KP_Home0xff95, CDK_CONTROL_MASK,
1180 CTK_MOVEMENT_BUFFER_ENDS, -1);
1181
1182 add_move_binding (binding_set, CDK_KEY_KP_End0xff9c, CDK_CONTROL_MASK,
1183 CTK_MOVEMENT_BUFFER_ENDS, 1);
1184
1185 /* copy */
1186 ctk_binding_entry_add_signal (binding_set, CDK_KEY_c0x063, CDK_CONTROL_MASK,
1187 "copy-clipboard", 0);
1188
1189 ctk_binding_entry_add_signal (binding_set, CDK_KEY_Return0xff0d, 0,
1190 "activate-current-link", 0);
1191 ctk_binding_entry_add_signal (binding_set, CDK_KEY_ISO_Enter0xfe34, 0,
1192 "activate-current-link", 0);
1193 ctk_binding_entry_add_signal (binding_set, CDK_KEY_KP_Enter0xff8d, 0,
1194 "activate-current-link", 0);
1195
1196 ctk_widget_class_set_accessible_type (widget_class, CTK_TYPE_LABEL_ACCESSIBLE(ctk_label_accessible_get_type ()));
1197
1198 ctk_widget_class_set_css_name (widget_class, "label");
1199
1200 quark_shortcuts_connected = g_quark_from_static_string ("ctk-label-shortcuts-connected");
1201 quark_mnemonic_menu = g_quark_from_static_string ("ctk-mnemonic-menu");
1202 quark_mnemonics_visible_connected = g_quark_from_static_string ("ctk-label-mnemonics-visible-connected");
1203 quark_ctk_signal = g_quark_from_static_string ("ctk-signal");
1204 quark_link = g_quark_from_static_string ("link");
1205}
1206
1207static void
1208ctk_label_set_property (GObject *object,
1209 guint prop_id,
1210 const GValue *value,
1211 GParamSpec *pspec)
1212{
1213 CtkLabel *label = CTK_LABEL (object)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_label_get_type ()))))))
;
1214
1215 switch (prop_id)
1216 {
1217 case PROP_LABEL:
1218 ctk_label_set_label (label, g_value_get_string (value));
1219 break;
1220 case PROP_ATTRIBUTES:
1221 ctk_label_set_attributes (label, g_value_get_boxed (value));
1222 break;
1223 case PROP_USE_MARKUP:
1224 ctk_label_set_use_markup (label, g_value_get_boolean (value));
1225 break;
1226 case PROP_USE_UNDERLINE:
1227 ctk_label_set_use_underline (label, g_value_get_boolean (value));
1228 break;
1229 case PROP_JUSTIFY:
1230 ctk_label_set_justify (label, g_value_get_enum (value));
1231 break;
1232 case PROP_PATTERN:
1233 ctk_label_set_pattern (label, g_value_get_string (value));
1234 break;
1235 case PROP_WRAP:
1236 ctk_label_set_line_wrap (label, g_value_get_boolean (value));
1237 break;
1238 case PROP_WRAP_MODE:
1239 ctk_label_set_line_wrap_mode (label, g_value_get_enum (value));
1240 break;
1241 case PROP_SELECTABLE:
1242 ctk_label_set_selectable (label, g_value_get_boolean (value));
1243 break;
1244 case PROP_MNEMONIC_WIDGET:
1245 ctk_label_set_mnemonic_widget (label, (CtkWidget*) g_value_get_object (value));
1246 break;
1247 case PROP_ELLIPSIZE:
1248 ctk_label_set_ellipsize (label, g_value_get_enum (value));
1249 break;
1250 case PROP_WIDTH_CHARS:
1251 ctk_label_set_width_chars (label, g_value_get_int (value));
1252 break;
1253 case PROP_SINGLE_LINE_MODE:
1254 ctk_label_set_single_line_mode (label, g_value_get_boolean (value));
1255 break;
1256 case PROP_ANGLE:
1257 ctk_label_set_angle (label, g_value_get_double (value));
1258 break;
1259 case PROP_MAX_WIDTH_CHARS:
1260 ctk_label_set_max_width_chars (label, g_value_get_int (value));
1261 break;
1262 case PROP_TRACK_VISITED_LINKS:
1263 ctk_label_set_track_visited_links (label, g_value_get_boolean (value));
1264 break;
1265 case PROP_LINES:
1266 ctk_label_set_lines (label, g_value_get_int (value));
1267 break;
1268 case PROP_XALIGN:
1269 ctk_label_set_xalign (label, g_value_get_float (value));
1270 break;
1271 case PROP_YALIGN:
1272 ctk_label_set_yalign (label, g_value_get_float (value));
1273 break;
1274 default:
1275 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctklabel.c", 1275, ("property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
1276 break;
1277 }
1278}
1279
1280static void
1281ctk_label_get_property (GObject *object,
1282 guint prop_id,
1283 GValue *value,
1284 GParamSpec *pspec)
1285{
1286 CtkLabel *label = CTK_LABEL (object)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_label_get_type ()))))))
;
1287 CtkLabelPrivate *priv = label->priv;
1288
1289 switch (prop_id)
1290 {
1291 case PROP_LABEL:
1292 g_value_set_string (value, priv->label);
1293 break;
1294 case PROP_ATTRIBUTES:
1295 g_value_set_boxed (value, priv->attrs);
1296 break;
1297 case PROP_USE_MARKUP:
1298 g_value_set_boolean (value, priv->use_markup);
1299 break;
1300 case PROP_USE_UNDERLINE:
1301 g_value_set_boolean (value, priv->use_underline);
1302 break;
1303 case PROP_JUSTIFY:
1304 g_value_set_enum (value, priv->jtype);
1305 break;
1306 case PROP_WRAP:
1307 g_value_set_boolean (value, priv->wrap);
1308 break;
1309 case PROP_WRAP_MODE:
1310 g_value_set_enum (value, priv->wrap_mode);
1311 break;
1312 case PROP_SELECTABLE:
1313 g_value_set_boolean (value, ctk_label_get_selectable (label));
1314 break;
1315 case PROP_MNEMONIC_KEYVAL:
1316 g_value_set_uint (value, priv->mnemonic_keyval);
1317 break;
1318 case PROP_MNEMONIC_WIDGET:
1319 g_value_set_object (value, (GObject*) priv->mnemonic_widget);
1320 break;
1321 case PROP_CURSOR_POSITION:
1322 g_value_set_int (value, _ctk_label_get_cursor_position (label));
1323 break;
1324 case PROP_SELECTION_BOUND:
1325 g_value_set_int (value, _ctk_label_get_selection_bound (label));
1326 break;
1327 case PROP_ELLIPSIZE:
1328 g_value_set_enum (value, priv->ellipsize);
1329 break;
1330 case PROP_WIDTH_CHARS:
1331 g_value_set_int (value, ctk_label_get_width_chars (label));
1332 break;
1333 case PROP_SINGLE_LINE_MODE:
1334 g_value_set_boolean (value, ctk_label_get_single_line_mode (label));
1335 break;
1336 case PROP_ANGLE:
1337 g_value_set_double (value, ctk_label_get_angle (label));
1338 break;
1339 case PROP_MAX_WIDTH_CHARS:
1340 g_value_set_int (value, ctk_label_get_max_width_chars (label));
1341 break;
1342 case PROP_TRACK_VISITED_LINKS:
1343 g_value_set_boolean (value, ctk_label_get_track_visited_links (label));
1344 break;
1345 case PROP_LINES:
1346 g_value_set_int (value, ctk_label_get_lines (label));
1347 break;
1348 case PROP_XALIGN:
1349 g_value_set_float (value, ctk_label_get_xalign (label));
1350 break;
1351 case PROP_YALIGN:
1352 g_value_set_float (value, ctk_label_get_yalign (label));
1353 break;
1354 default:
1355 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "ctklabel.c", 1355, ("property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
1356 break;
1357 }
1358}
1359
1360static void
1361ctk_label_init (CtkLabel *label)
1362{
1363 CtkLabelPrivate *priv;
1364
1365 label->priv = ctk_label_get_instance_private (label);
1366 priv = label->priv;
1367
1368 ctk_widget_set_has_window (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
, FALSE(0));
1369
1370 priv->width_chars = -1;
1371 priv->max_width_chars = -1;
1372 priv->label = g_strdup ("")g_strdup_inline ("");
1373 priv->lines = -1;
1374
1375 priv->xalign = 0.5;
1376 priv->yalign = 0.5;
1377
1378 priv->jtype = CTK_JUSTIFY_LEFT;
1379 priv->wrap = FALSE(0);
1380 priv->wrap_mode = PANGO_WRAP_WORD;
1381 priv->ellipsize = PANGO_ELLIPSIZE_NONE;
1382
1383 priv->use_underline = FALSE(0);
1384 priv->use_markup = FALSE(0);
1385 priv->pattern_set = FALSE(0);
1386 priv->track_links = TRUE(!(0));
1387
1388 priv->mnemonic_keyval = CDK_KEY_VoidSymbol0xffffff;
1389 priv->layout = NULL((void*)0);
1390 priv->text = g_strdup ("")g_strdup_inline ("");
1391 priv->attrs = NULL((void*)0);
1392
1393 priv->mnemonic_widget = NULL((void*)0);
1394 priv->mnemonic_window = NULL((void*)0);
1395
1396 priv->mnemonics_visible = TRUE(!(0));
1397
1398 priv->gadget = ctk_css_custom_gadget_new_for_node (ctk_widget_get_css_node (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
),
1399 CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
,
1400 ctk_label_measure,
1401 NULL((void*)0),
1402 ctk_label_render,
1403 NULL((void*)0),
1404 NULL((void*)0));
1405}
1406
1407
1408static void
1409ctk_label_buildable_interface_init (CtkBuildableIface *iface)
1410{
1411 buildable_parent_iface = g_type_interface_peek_parent (iface);
1412
1413 iface->custom_tag_start = ctk_label_buildable_custom_tag_start;
1414 iface->custom_finished = ctk_label_buildable_custom_finished;
1415}
1416
1417typedef struct {
1418 CtkBuilder *builder;
1419 GObject *object;
1420 PangoAttrList *attrs;
1421} PangoParserData;
1422
1423static PangoAttribute *
1424attribute_from_text (CtkBuilder *builder,
1425 const gchar *name,
1426 const gchar *value,
1427 GError **error)
1428{
1429 PangoAttribute *attribute = NULL((void*)0);
1430 PangoAttrType type;
1431 PangoLanguage *language;
1432 PangoFontDescription *font_desc;
1433 CdkColor *color;
1434 GValue val = G_VALUE_INIT{ 0, { { 0 } } };
1435
1436 if (!ctk_builder_value_from_string_type (builder, PANGO_TYPE_ATTR_TYPE(pango_attr_type_get_type ()), name, &val, error))
1437 return NULL((void*)0);
1438
1439 type = g_value_get_enum (&val);
1440 g_value_unset (&val);
1441
1442 switch (type)
1443 {
1444 /* PangoAttrLanguage */
1445 case PANGO_ATTR_LANGUAGE:
1446 if ((language = pango_language_from_string (value)))
1447 {
1448 attribute = pango_attr_language_new (language);
1449 g_value_init (&val, G_TYPE_INT((GType) ((6) << (2))));
1450 }
1451 break;
1452 /* PangoAttrInt */
1453 case PANGO_ATTR_STYLE:
1454 if (ctk_builder_value_from_string_type (builder, PANGO_TYPE_STYLE(pango_style_get_type ()), value, &val, error))
1455 attribute = pango_attr_style_new (g_value_get_enum (&val));
1456 break;
1457 case PANGO_ATTR_WEIGHT:
1458 if (ctk_builder_value_from_string_type (builder, PANGO_TYPE_WEIGHT(pango_weight_get_type ()), value, &val, error))
1459 attribute = pango_attr_weight_new (g_value_get_enum (&val));
1460 break;
1461 case PANGO_ATTR_VARIANT:
1462 if (ctk_builder_value_from_string_type (builder, PANGO_TYPE_VARIANT(pango_variant_get_type ()), value, &val, error))
1463 attribute = pango_attr_variant_new (g_value_get_enum (&val));
1464 break;
1465 case PANGO_ATTR_STRETCH:
1466 if (ctk_builder_value_from_string_type (builder, PANGO_TYPE_STRETCH(pango_stretch_get_type ()), value, &val, error))
1467 attribute = pango_attr_stretch_new (g_value_get_enum (&val));
1468 break;
1469 case PANGO_ATTR_UNDERLINE:
1470 if (ctk_builder_value_from_string_type (builder, PANGO_TYPE_UNDERLINE(pango_underline_get_type ()), value, &val, NULL((void*)0)))
1471 attribute = pango_attr_underline_new (g_value_get_enum (&val));
1472 else
1473 {
1474 /* XXX: allow boolean for backwards compat, so ignore error */
1475 /* Deprecate this somehow */
1476 g_value_unset (&val);
1477 if (ctk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN((GType) ((5) << (2))), value, &val, error))
1478 attribute = pango_attr_underline_new (g_value_get_boolean (&val));
1479 }
1480 break;
1481 case PANGO_ATTR_STRIKETHROUGH:
1482 if (ctk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN((GType) ((5) << (2))), value, &val, error))
1483 attribute = pango_attr_strikethrough_new (g_value_get_boolean (&val));
1484 break;
1485 case PANGO_ATTR_GRAVITY:
1486 if (ctk_builder_value_from_string_type (builder, PANGO_TYPE_GRAVITY(pango_gravity_get_type ()), value, &val, error))
1487 attribute = pango_attr_gravity_new (g_value_get_enum (&val));
1488 break;
1489 case PANGO_ATTR_GRAVITY_HINT:
1490 if (ctk_builder_value_from_string_type (builder, PANGO_TYPE_GRAVITY_HINT(pango_gravity_hint_get_type ()), value, &val, error))
1491 attribute = pango_attr_gravity_hint_new (g_value_get_enum (&val));
1492 break;
1493 /* PangoAttrString */
1494 case PANGO_ATTR_FAMILY:
1495 attribute = pango_attr_family_new (value);
1496 g_value_init (&val, G_TYPE_INT((GType) ((6) << (2))));
1497 break;
1498
1499 /* PangoAttrSize */
1500 case PANGO_ATTR_SIZE:
1501 if (ctk_builder_value_from_string_type (builder, G_TYPE_INT((GType) ((6) << (2))), value, &val, error))
1502 attribute = pango_attr_size_new (g_value_get_int (&val));
1503 break;
1504 case PANGO_ATTR_ABSOLUTE_SIZE:
1505 if (ctk_builder_value_from_string_type (builder, G_TYPE_INT((GType) ((6) << (2))), value, &val, error))
1506 attribute = pango_attr_size_new_absolute (g_value_get_int (&val));
1507 break;
1508
1509 /* PangoAttrFontDesc */
1510 case PANGO_ATTR_FONT_DESC:
1511 if ((font_desc = pango_font_description_from_string (value)))
1512 {
1513 attribute = pango_attr_font_desc_new (font_desc);
1514 pango_font_description_free (font_desc);
1515 g_value_init (&val, G_TYPE_INT((GType) ((6) << (2))));
1516 }
1517 break;
1518
1519 /* PangoAttrColor */
1520 case PANGO_ATTR_FOREGROUND:
1521 if (ctk_builder_value_from_string_type (builder, CDK_TYPE_COLOR(cdk_color_get_type ()), value, &val, error))
1522 {
1523 color = g_value_get_boxed (&val);
1524 attribute = pango_attr_foreground_new (color->red, color->green, color->blue);
1525 }
1526 break;
1527 case PANGO_ATTR_BACKGROUND:
1528 if (ctk_builder_value_from_string_type (builder, CDK_TYPE_COLOR(cdk_color_get_type ()), value, &val, error))
1529 {
1530 color = g_value_get_boxed (&val);
1531 attribute = pango_attr_background_new (color->red, color->green, color->blue);
1532 }
1533 break;
1534 case PANGO_ATTR_UNDERLINE_COLOR:
1535 if (ctk_builder_value_from_string_type (builder, CDK_TYPE_COLOR(cdk_color_get_type ()), value, &val, error))
1536 {
1537 color = g_value_get_boxed (&val);
1538 attribute = pango_attr_underline_color_new (color->red, color->green, color->blue);
1539 }
1540 break;
1541 case PANGO_ATTR_STRIKETHROUGH_COLOR:
1542 if (ctk_builder_value_from_string_type (builder, CDK_TYPE_COLOR(cdk_color_get_type ()), value, &val, error))
1543 {
1544 color = g_value_get_boxed (&val);
1545 attribute = pango_attr_strikethrough_color_new (color->red, color->green, color->blue);
1546 }
1547 break;
1548
1549 /* PangoAttrShape */
1550 case PANGO_ATTR_SHAPE:
1551 /* Unsupported for now */
1552 break;
1553 /* PangoAttrFloat */
1554 case PANGO_ATTR_SCALE:
1555 if (ctk_builder_value_from_string_type (builder, G_TYPE_DOUBLE((GType) ((15) << (2))), value, &val, error))
1556 attribute = pango_attr_scale_new (g_value_get_double (&val));
1557 break;
1558 case PANGO_ATTR_LETTER_SPACING:
1559 if (ctk_builder_value_from_string_type (builder, G_TYPE_INT((GType) ((6) << (2))), value, &val, error))
1560 attribute = pango_attr_letter_spacing_new (g_value_get_int (&val));
1561 break;
1562 case PANGO_ATTR_RISE:
1563 if (ctk_builder_value_from_string_type (builder, G_TYPE_INT((GType) ((6) << (2))), value, &val, error))
1564 attribute = pango_attr_rise_new (g_value_get_int (&val));
1565 break;
1566 case PANGO_ATTR_FALLBACK:
1567 if (ctk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN((GType) ((5) << (2))), value, &val, error))
1568 attribute = pango_attr_fallback_new (g_value_get_boolean (&val));
1569 break;
1570 case PANGO_ATTR_FONT_FEATURES:
1571 attribute = pango_attr_font_features_new (value);
1572 break;
1573 case PANGO_ATTR_FOREGROUND_ALPHA:
1574 if (ctk_builder_value_from_string_type (builder, G_TYPE_INT((GType) ((6) << (2))), value, &val, error))
1575 attribute = pango_attr_foreground_alpha_new ((guint16)g_value_get_int (&val));
1576 break;
1577 case PANGO_ATTR_BACKGROUND_ALPHA:
1578 if (ctk_builder_value_from_string_type (builder, G_TYPE_INT((GType) ((6) << (2))), value, &val, error))
1579 attribute = pango_attr_background_alpha_new ((guint16)g_value_get_int (&val));
1580 break;
1581 case PANGO_ATTR_INVALID:
1582 default:
1583 break;
1584 }
1585
1586 g_value_unset (&val);
1587
1588 return attribute;
1589}
1590
1591
1592static void
1593pango_start_element (GMarkupParseContext *context,
1594 const gchar *element_name,
1595 const gchar **names,
1596 const gchar **values,
1597 gpointer user_data,
1598 GError **error)
1599{
1600 PangoParserData *data = (PangoParserData*)user_data;
1601
1602 if (strcmp (element_name, "attribute") == 0)
1603 {
1604 PangoAttribute *attr = NULL((void*)0);
1605 const gchar *name = NULL((void*)0);
1606 const gchar *value = NULL((void*)0);
1607 const gchar *start = NULL((void*)0);
1608 const gchar *end = NULL((void*)0);
1609 guint start_val = 0;
1610 guint end_val = G_MAXUINT(2147483647 *2U +1U);
1611 GValue val = G_VALUE_INIT{ 0, { { 0 } } };
1612
1613 if (!_ctk_builder_check_parent (data->builder, context, "attributes", error))
1614 return;
1615
1616 if (!g_markup_collect_attributes (element_name, names, values, error,
1617 G_MARKUP_COLLECT_STRING, "name", &name,
1618 G_MARKUP_COLLECT_STRING, "value", &value,
1619 G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "start", &start,
1620 G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "end", &end,
1621 G_MARKUP_COLLECT_INVALID))
1622 {
1623 _ctk_builder_prefix_error (data->builder, context, error);
1624 return;
1625 }
1626
1627 if (start)
1628 {
1629 if (!ctk_builder_value_from_string_type (data->builder, G_TYPE_UINT((GType) ((7) << (2))), start, &val, error))
1630 {
1631 _ctk_builder_prefix_error (data->builder, context, error);
1632 return;
1633 }
1634 start_val = g_value_get_uint (&val);
1635 g_value_unset (&val);
1636 }
1637
1638 if (end)
1639 {
1640 if (!ctk_builder_value_from_string_type (data->builder, G_TYPE_UINT((GType) ((7) << (2))), end, &val, error))
1641 {
1642 _ctk_builder_prefix_error (data->builder, context, error);
1643 return;
1644 }
1645 end_val = g_value_get_uint (&val);
1646 g_value_unset (&val);
1647 }
1648
1649 attr = attribute_from_text (data->builder, name, value, error);
1650 if (!attr)
1651 {
1652 _ctk_builder_prefix_error (data->builder, context, error);
1653 return;
1654 }
1655
1656 attr->start_index = start_val;
1657 attr->end_index = end_val;
1658
1659 if (!data->attrs)
1660 data->attrs = pango_attr_list_new ();
1661
1662 pango_attr_list_insert (data->attrs, attr);
1663 }
1664 else if (strcmp (element_name, "attributes") == 0)
1665 {
1666 if (!_ctk_builder_check_parent (data->builder, context, "object", error))
1667 return;
1668
1669 if (!g_markup_collect_attributes (element_name, names, values, error,
1670 G_MARKUP_COLLECT_INVALID, NULL((void*)0), NULL((void*)0),
1671 G_MARKUP_COLLECT_INVALID))
1672 _ctk_builder_prefix_error (data->builder, context, error);
1673 }
1674 else
1675 {
1676 _ctk_builder_error_unhandled_tag (data->builder, context,
1677 "CtkContainer", element_name,
1678 error);
1679 }
1680}
1681
1682static const GMarkupParser pango_parser =
1683 {
1684 .start_element = pango_start_element,
1685 };
1686
1687static gboolean
1688ctk_label_buildable_custom_tag_start (CtkBuildable *buildable,
1689 CtkBuilder *builder,
1690 GObject *child,
1691 const gchar *tagname,
1692 GMarkupParser *parser,
1693 gpointer *data)
1694{
1695 if (buildable_parent_iface->custom_tag_start (buildable, builder, child,
1696 tagname, parser, data))
1697 return TRUE(!(0));
1698
1699 if (strcmp (tagname, "attributes") == 0)
1700 {
1701 PangoParserData *parser_data;
1702
1703 parser_data = g_slice_new0 (PangoParserData)((PangoParserData*) g_slice_alloc0 (sizeof (PangoParserData))
)
;
1704 parser_data->builder = g_object_ref (builder)((__typeof__ (builder)) (g_object_ref) (builder));
1705 parser_data->object = G_OBJECT (g_object_ref (buildable))((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((((__typeof__ (buildable)) (g_object_ref) (buildable)))),
(((GType) ((20) << (2))))))))
;
1706 *parser = pango_parser;
1707 *data = parser_data;
1708 return TRUE(!(0));
1709 }
1710 return FALSE(0);
1711}
1712
1713static void
1714ctk_label_buildable_custom_finished (CtkBuildable *buildable,
1715 CtkBuilder *builder,
1716 GObject *child,
1717 const gchar *tagname,
1718 gpointer user_data)
1719{
1720 PangoParserData *data;
1721
1722 buildable_parent_iface->custom_finished (buildable, builder, child,
1723 tagname, user_data);
1724
1725 if (strcmp (tagname, "attributes") == 0)
1726 {
1727 data = (PangoParserData*)user_data;
1728
1729 if (data->attrs)
1730 {
1731 ctk_label_set_attributes (CTK_LABEL (buildable)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((buildable)), ((ctk_label_get_type ()))))))
, data->attrs);
1732 pango_attr_list_unref (data->attrs);
1733 }
1734
1735 g_object_unref (data->object);
1736 g_object_unref (data->builder);
1737 g_slice_free (PangoParserData, data)do { if (1) g_slice_free1 (sizeof (PangoParserData), (data));
else (void) ((PangoParserData*) 0 == (data)); } while (0)
;
1738 }
1739}
1740
1741
1742/**
1743 * ctk_label_new:
1744 * @str: (nullable): The text of the label
1745 *
1746 * Creates a new label with the given text inside it. You can
1747 * pass %NULL to get an empty label widget.
1748 *
1749 * Returns: the new #CtkLabel
1750 **/
1751CtkWidget*
1752ctk_label_new (const gchar *str)
1753{
1754 CtkLabel *label;
1755
1756 label = g_object_new (CTK_TYPE_LABEL(ctk_label_get_type ()), NULL((void*)0));
1757
1758 if (str && *str)
1759 ctk_label_set_text (label, str);
1760
1761 return CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
;
1762}
1763
1764/**
1765 * ctk_label_new_with_mnemonic:
1766 * @str: (nullable): The text of the label, with an underscore in front of the
1767 * mnemonic character
1768 *
1769 * Creates a new #CtkLabel, containing the text in @str.
1770 *
1771 * If characters in @str are preceded by an underscore, they are
1772 * underlined. If you need a literal underscore character in a label, use
1773 * '__' (two underscores). The first underlined character represents a
1774 * keyboard accelerator called a mnemonic. The mnemonic key can be used
1775 * to activate another widget, chosen automatically, or explicitly using
1776 * ctk_label_set_mnemonic_widget().
1777 *
1778 * If ctk_label_set_mnemonic_widget() is not called, then the first
1779 * activatable ancestor of the #CtkLabel will be chosen as the mnemonic
1780 * widget. For instance, if the label is inside a button or menu item,
1781 * the button or menu item will automatically become the mnemonic widget
1782 * and be activated by the mnemonic.
1783 *
1784 * Returns: the new #CtkLabel
1785 **/
1786CtkWidget*
1787ctk_label_new_with_mnemonic (const gchar *str)
1788{
1789 CtkLabel *label;
1790
1791 label = g_object_new (CTK_TYPE_LABEL(ctk_label_get_type ()), NULL((void*)0));
1792
1793 if (str && *str)
1794 ctk_label_set_text_with_mnemonic (label, str);
1795
1796 return CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
;
1797}
1798
1799static gboolean
1800ctk_label_mnemonic_activate (CtkWidget *widget,
1801 gboolean group_cycling)
1802{
1803 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
1804 CtkLabelPrivate *priv = label->priv;
1805 CtkWidget *parent;
1806
1807 if (priv->mnemonic_widget)
1808 return ctk_widget_mnemonic_activate (priv->mnemonic_widget, group_cycling);
1809
1810 /* Try to find the widget to activate by traversing the
1811 * widget's ancestry.
1812 */
1813 parent = ctk_widget_get_parent (widget);
1814
1815 if (CTK_IS_NOTEBOOK (parent)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(parent)); GType __t = ((ctk_notebook_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
1816 return FALSE(0);
1817
1818 while (parent)
1819 {
1820 if (ctk_widget_get_can_focus (parent) ||
1821 (!group_cycling && CTK_WIDGET_GET_CLASS (parent)((((CtkWidgetClass*) (((GTypeInstance*) ((parent)))->g_class
))))
->activate_signal) ||
1822 CTK_IS_NOTEBOOK (ctk_widget_get_parent (parent))(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(ctk_widget_get_parent (parent))); GType __t = ((ctk_notebook_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
||
1823 CTK_IS_MENU_ITEM (parent)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(parent)); GType __t = ((ctk_menu_item_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
1824 return ctk_widget_mnemonic_activate (parent, group_cycling);
1825 parent = ctk_widget_get_parent (parent);
1826 }
1827
1828 /* barf if there was nothing to activate */
1829 g_warning ("Couldn't find a target for a mnemonic activation.");
1830 ctk_widget_error_bell (widget);
1831
1832 return FALSE(0);
1833}
1834
1835static void
1836ctk_label_setup_mnemonic (CtkLabel *label,
1837 guint last_key)
1838{
1839 CtkLabelPrivate *priv = label->priv;
1840 CtkWidget *widget = CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
;
1841 CtkWidget *toplevel;
1842 CtkWidget *mnemonic_menu;
1843
1844 mnemonic_menu = g_object_get_qdata (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, quark_mnemonic_menu);
1845
1846 if (last_key != CDK_KEY_VoidSymbol0xffffff)
1847 {
1848 if (priv->mnemonic_window)
1849 {
1850 ctk_window_remove_mnemonic (priv->mnemonic_window,
1851 last_key,
1852 widget);
1853 priv->mnemonic_window = NULL((void*)0);
1854 }
1855 if (mnemonic_menu)
1856 {
1857 _ctk_menu_shell_remove_mnemonic (CTK_MENU_SHELL (mnemonic_menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((mnemonic_menu)), ((ctk_menu_shell_get_type ()))))))
,
1858 last_key,
1859 widget);
1860 mnemonic_menu = NULL((void*)0);
1861 }
1862 }
1863
1864 if (priv->mnemonic_keyval == CDK_KEY_VoidSymbol0xffffff)
1865 goto done;
1866
1867 connect_mnemonics_visible_notify (CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
);
1868
1869 toplevel = ctk_widget_get_toplevel (widget);
1870 if (ctk_widget_is_toplevel (toplevel))
1871 {
1872 CtkWidget *menu_shell;
1873
1874 menu_shell = ctk_widget_get_ancestor (widget,
1875 CTK_TYPE_MENU_SHELL(ctk_menu_shell_get_type ()));
1876
1877 if (menu_shell)
1878 {
1879 _ctk_menu_shell_add_mnemonic (CTK_MENU_SHELL (menu_shell)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu_shell)), ((ctk_menu_shell_get_type ()))))))
,
1880 priv->mnemonic_keyval,
1881 widget);
1882 mnemonic_menu = menu_shell;
1883 }
1884
1885 if (!CTK_IS_MENU (menu_shell)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(menu_shell)); GType __t = ((ctk_menu_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
1886 {
1887 ctk_window_add_mnemonic (CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
,
1888 priv->mnemonic_keyval,
1889 widget);
1890 priv->mnemonic_window = CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
;
1891 }
1892 }
1893
1894 done:
1895 g_object_set_qdata (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, quark_mnemonic_menu, mnemonic_menu);
1896}
1897
1898static void
1899ctk_label_hierarchy_changed (CtkWidget *widget,
1900 CtkWidget *old_toplevel G_GNUC_UNUSED__attribute__ ((__unused__)))
1901{
1902 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
1903 CtkLabelPrivate *priv = label->priv;
1904
1905 ctk_label_setup_mnemonic (label, priv->mnemonic_keyval);
1906}
1907
1908static void
1909label_shortcut_setting_apply (CtkLabel *label)
1910{
1911 ctk_label_recalculate (label);
1912 if (CTK_IS_ACCEL_LABEL (label)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(label)); GType __t = ((ctk_accel_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
1913 ctk_accel_label_refetch (CTK_ACCEL_LABEL (label)((((CtkAccelLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_accel_label_get_type ()))))))
);
1914}
1915
1916static void
1917label_shortcut_setting_traverse_container (CtkWidget *widget,
1918 gpointer data)
1919{
1920 if (CTK_IS_LABEL (widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(widget)); GType __t = ((ctk_label_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
1921 label_shortcut_setting_apply (CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
);
1922 else if (CTK_IS_CONTAINER (widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(widget)); GType __t = ((ctk_container_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
1923 ctk_container_forall (CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
,
1924 label_shortcut_setting_traverse_container, data);
1925}
1926
1927static void
1928label_shortcut_setting_changed (CtkSettings *settings)
1929{
1930 GList *list, *l;
1931
1932 list = ctk_window_list_toplevels ();
1933
1934 for (l = list; l ; l = l->next)
1935 {
1936 CtkWidget *widget = l->data;
1937
1938 if (ctk_widget_get_settings (widget) == settings)
1939 ctk_container_forall (CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
,
1940 label_shortcut_setting_traverse_container, NULL((void*)0));
1941 }
1942
1943 g_list_free (list);
1944}
1945
1946static void
1947mnemonics_visible_apply (CtkWidget *widget,
1948 gboolean mnemonics_visible)
1949{
1950 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
1951 CtkLabelPrivate *priv = label->priv;
1952
1953 mnemonics_visible = mnemonics_visible != FALSE(0);
1954
1955 if (priv->mnemonics_visible != mnemonics_visible)
1956 {
1957 priv->mnemonics_visible = mnemonics_visible;
1958
1959 ctk_label_recalculate (label);
1960 }
1961}
1962
1963static void
1964label_mnemonics_visible_traverse_container (CtkWidget *widget,
1965 gpointer data)
1966{
1967 gboolean mnemonics_visible = GPOINTER_TO_INT (data)((gint) (glong) (data));
1968
1969 _ctk_label_mnemonics_visible_apply_recursively (widget, mnemonics_visible);
1970}
1971
1972void
1973_ctk_label_mnemonics_visible_apply_recursively (CtkWidget *widget,
1974 gboolean mnemonics_visible)
1975{
1976 if (CTK_IS_LABEL (widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(widget)); GType __t = ((ctk_label_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
1977 mnemonics_visible_apply (widget, mnemonics_visible);
1978 else if (CTK_IS_CONTAINER (widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(widget)); GType __t = ((ctk_container_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
1979 ctk_container_forall (CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
,
1980 label_mnemonics_visible_traverse_container,
1981 GINT_TO_POINTER (mnemonics_visible)((gpointer) (glong) (mnemonics_visible)));
1982}
1983
1984static void
1985label_mnemonics_visible_changed (CtkWindow *window,
1986 GParamSpec *pspec G_GNUC_UNUSED__attribute__ ((__unused__)),
1987 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
1988{
1989 gboolean mnemonics_visible;
1990
1991 g_object_get (window, "mnemonics-visible", &mnemonics_visible, NULL((void*)0));
1992
1993 ctk_container_forall (CTK_CONTAINER (window)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((window)), ((ctk_container_get_type ()))))))
,
1994 label_mnemonics_visible_traverse_container,
1995 GINT_TO_POINTER (mnemonics_visible)((gpointer) (glong) (mnemonics_visible)));
1996}
1997
1998static void
1999ctk_label_screen_changed (CtkWidget *widget,
2000 CdkScreen *old_screen G_GNUC_UNUSED__attribute__ ((__unused__)))
2001{
2002 CtkSettings *settings;
2003 gboolean shortcuts_connected;
2004
2005 /* The PangoContext is replaced when the screen changes, so clear the layouts */
2006 ctk_label_clear_layout (CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
);
2007
2008 if (!ctk_widget_has_screen (widget))
2009 return;
2010
2011 settings = ctk_widget_get_settings (widget);
2012
2013 shortcuts_connected =
2014 GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (settings), quark_shortcuts_connected))((gint) (glong) (g_object_get_qdata (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((settings)), (((GType) ((20) << (2)
))))))), quark_shortcuts_connected)))
;
2015
2016 if (! shortcuts_connected)
2017 {
2018 g_signal_connect (settings, "notify::ctk-enable-mnemonics",g_signal_connect_data ((settings), ("notify::ctk-enable-mnemonics"
), (((GCallback) (label_shortcut_setting_changed))), (((void*
)0)), ((void*)0), (GConnectFlags) 0)
2019 G_CALLBACK (label_shortcut_setting_changed),g_signal_connect_data ((settings), ("notify::ctk-enable-mnemonics"
), (((GCallback) (label_shortcut_setting_changed))), (((void*
)0)), ((void*)0), (GConnectFlags) 0)
2020 NULL)g_signal_connect_data ((settings), ("notify::ctk-enable-mnemonics"
), (((GCallback) (label_shortcut_setting_changed))), (((void*
)0)), ((void*)0), (GConnectFlags) 0)
;
2021 g_signal_connect (settings, "notify::ctk-enable-accels",g_signal_connect_data ((settings), ("notify::ctk-enable-accels"
), (((GCallback) (label_shortcut_setting_changed))), (((void*
)0)), ((void*)0), (GConnectFlags) 0)
2022 G_CALLBACK (label_shortcut_setting_changed),g_signal_connect_data ((settings), ("notify::ctk-enable-accels"
), (((GCallback) (label_shortcut_setting_changed))), (((void*
)0)), ((void*)0), (GConnectFlags) 0)
2023 NULL)g_signal_connect_data ((settings), ("notify::ctk-enable-accels"
), (((GCallback) (label_shortcut_setting_changed))), (((void*
)0)), ((void*)0), (GConnectFlags) 0)
;
2024
2025 g_object_set_qdata (G_OBJECT (settings)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((settings)), (((GType) ((20) << (2))))))))
, quark_shortcuts_connected,
2026 GINT_TO_POINTER (TRUE)((gpointer) (glong) ((!(0)))));
2027 }
2028
2029 label_shortcut_setting_apply (CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
);
2030}
2031
2032
2033static void
2034label_mnemonic_widget_weak_notify (gpointer data,
2035 GObject *where_the_object_was G_GNUC_UNUSED__attribute__ ((__unused__)))
2036{
2037 CtkLabel *label = data;
2038 CtkLabelPrivate *priv = label->priv;
2039
2040 priv->mnemonic_widget = NULL((void*)0);
2041 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_MNEMONIC_WIDGET]);
2042}
2043
2044/**
2045 * ctk_label_set_mnemonic_widget:
2046 * @label: a #CtkLabel
2047 * @widget: (nullable): the target #CtkWidget, or %NULL to unset
2048 *
2049 * If the label has been set so that it has an mnemonic key (using
2050 * i.e. ctk_label_set_markup_with_mnemonic(),
2051 * ctk_label_set_text_with_mnemonic(), ctk_label_new_with_mnemonic()
2052 * or the “use_underline” property) the label can be associated with a
2053 * widget that is the target of the mnemonic. When the label is inside
2054 * a widget (like a #CtkButton or a #CtkNotebook tab) it is
2055 * automatically associated with the correct widget, but sometimes
2056 * (i.e. when the target is a #CtkEntry next to the label) you need to
2057 * set it explicitly using this function.
2058 *
2059 * The target widget will be accelerated by emitting the
2060 * CtkWidget::mnemonic-activate signal on it. The default handler for
2061 * this signal will activate the widget if there are no mnemonic collisions
2062 * and toggle focus between the colliding widgets otherwise.
2063 **/
2064void
2065ctk_label_set_mnemonic_widget (CtkLabel *label,
2066 CtkWidget *widget)
2067{
2068 CtkLabelPrivate *priv;
2069
2070 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
2071
2072 priv = label->priv;
2073
2074 if (widget)
2075 g_return_if_fail (CTK_IS_WIDGET (widget))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((widget)); GType __t = ((ctk_widget_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_WIDGET (widget)"); return; } } while (0)
;
2076
2077 if (priv->mnemonic_widget)
2078 {
2079 ctk_widget_remove_mnemonic_label (priv->mnemonic_widget, CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
2080 g_object_weak_unref (G_OBJECT (priv->mnemonic_widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->mnemonic_widget)), (((GType) ((20) << (2)
)))))))
,
2081 label_mnemonic_widget_weak_notify,
2082 label);
2083 }
2084 priv->mnemonic_widget = widget;
2085 if (priv->mnemonic_widget)
2086 {
2087 g_object_weak_ref (G_OBJECT (priv->mnemonic_widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((priv->mnemonic_widget)), (((GType) ((20) << (2)
)))))))
,
2088 label_mnemonic_widget_weak_notify,
2089 label);
2090 ctk_widget_add_mnemonic_label (priv->mnemonic_widget, CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
2091 }
2092
2093 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_MNEMONIC_WIDGET]);
2094}
2095
2096/**
2097 * ctk_label_get_mnemonic_widget:
2098 * @label: a #CtkLabel
2099 *
2100 * Retrieves the target of the mnemonic (keyboard shortcut) of this
2101 * label. See ctk_label_set_mnemonic_widget().
2102 *
2103 * Returns: (nullable) (transfer none): the target of the label’s mnemonic,
2104 * or %NULL if none has been set and the default algorithm will be used.
2105 **/
2106CtkWidget *
2107ctk_label_get_mnemonic_widget (CtkLabel *label)
2108{
2109 g_return_val_if_fail (CTK_IS_LABEL (label), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return (((void*)0)); } } while (
0)
;
2110
2111 return label->priv->mnemonic_widget;
2112}
2113
2114/**
2115 * ctk_label_get_mnemonic_keyval:
2116 * @label: a #CtkLabel
2117 *
2118 * If the label has been set so that it has an mnemonic key this function
2119 * returns the keyval used for the mnemonic accelerator. If there is no
2120 * mnemonic set up it returns #CDK_KEY_VoidSymbol.
2121 *
2122 * Returns: CDK keyval usable for accelerators, or #CDK_KEY_VoidSymbol
2123 **/
2124guint
2125ctk_label_get_mnemonic_keyval (CtkLabel *label)
2126{
2127 g_return_val_if_fail (CTK_IS_LABEL (label), CDK_KEY_VoidSymbol)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return (0xffffff); } } while (0)
;
2128
2129 return label->priv->mnemonic_keyval;
2130}
2131
2132static void
2133ctk_label_set_text_internal (CtkLabel *label,
2134 gchar *str)
2135{
2136 CtkLabelPrivate *priv = label->priv;
2137
2138 if (g_strcmp0 (priv->text, str) == 0)
2139 {
2140 g_free (str);
2141 return;
2142 }
2143
2144 _ctk_label_accessible_text_deleted (label);
2145 g_free (priv->text);
2146 priv->text = str;
2147
2148 _ctk_label_accessible_text_inserted (label);
2149
2150 ctk_label_select_region_index (label, 0, 0);
2151}
2152
2153static void
2154ctk_label_set_label_internal (CtkLabel *label,
2155 gchar *str)
2156{
2157 CtkLabelPrivate *priv = label->priv;
2158
2159 g_free (priv->label);
2160
2161 priv->label = str;
2162
2163 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_LABEL]);
2164}
2165
2166static gboolean
2167ctk_label_set_use_markup_internal (CtkLabel *label,
2168 gboolean val)
2169{
2170 CtkLabelPrivate *priv = label->priv;
2171
2172 val = val != FALSE(0);
2173 if (priv->use_markup != val)
2174 {
2175 priv->use_markup = val;
2176
2177 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_USE_MARKUP]);
2178
2179 return TRUE(!(0));
2180 }
2181
2182 return FALSE(0);
2183}
2184
2185static gboolean
2186ctk_label_set_use_underline_internal (CtkLabel *label,
2187 gboolean val)
2188{
2189 CtkLabelPrivate *priv = label->priv;
2190
2191 val = val != FALSE(0);
2192 if (priv->use_underline != val)
2193 {
2194 priv->use_underline = val;
2195
2196 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_USE_UNDERLINE]);
2197
2198 return TRUE(!(0));
2199 }
2200
2201 return FALSE(0);
2202}
2203
2204/* Calculates text, attrs and mnemonic_keyval from
2205 * label, use_underline and use_markup
2206 */
2207static void
2208ctk_label_recalculate (CtkLabel *label)
2209{
2210 CtkLabelPrivate *priv = label->priv;
2211 guint keyval = priv->mnemonic_keyval;
2212
2213 ctk_label_clear_links (label);
2214
2215 if (priv->use_markup)
2216 ctk_label_set_markup_internal (label, priv->label, priv->use_underline);
2217 else if (priv->use_underline)
2218 ctk_label_set_uline_text_internal (label, priv->label);
2219 else
2220 {
2221 if (!priv->pattern_set)
2222 {
2223 if (priv->markup_attrs)
2224 pango_attr_list_unref (priv->markup_attrs);
2225 priv->markup_attrs = NULL((void*)0);
2226 }
2227 ctk_label_set_text_internal (label, g_strdup (priv->label)g_strdup_inline (priv->label));
2228 }
2229
2230 if (!priv->use_underline)
2231 priv->mnemonic_keyval = CDK_KEY_VoidSymbol0xffffff;
2232
2233 if (keyval != priv->mnemonic_keyval)
2234 {
2235 ctk_label_setup_mnemonic (label, keyval);
2236 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_MNEMONIC_KEYVAL]);
2237 }
2238
2239 ctk_label_clear_layout (label);
2240 ctk_label_clear_select_info (label);
2241 ctk_widget_queue_resize (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
2242}
2243
2244/**
2245 * ctk_label_set_text:
2246 * @label: a #CtkLabel
2247 * @str: The text you want to set
2248 *
2249 * Sets the text within the #CtkLabel widget. It overwrites any text that
2250 * was there before.
2251 *
2252 * This function will clear any previously set mnemonic accelerators, and
2253 * set the #CtkLabel:use-underline property to %FALSE as a side effect.
2254 *
2255 * This function will set the #CtkLabel:use-markup property to %FALSE
2256 * as a side effect.
2257 *
2258 * See also: ctk_label_set_markup()
2259 **/
2260void
2261ctk_label_set_text (CtkLabel *label,
2262 const gchar *str)
2263{
2264 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
2265
2266 g_object_freeze_notify (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
2267
2268 ctk_label_set_label_internal (label, g_strdup (str ? str : "")g_strdup_inline (str ? str : ""));
2269 ctk_label_set_use_markup_internal (label, FALSE(0));
2270 ctk_label_set_use_underline_internal (label, FALSE(0));
2271
2272 ctk_label_recalculate (label);
2273
2274 g_object_thaw_notify (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
2275}
2276
2277/**
2278 * ctk_label_set_attributes:
2279 * @label: a #CtkLabel
2280 * @attrs: (nullable): a #PangoAttrList, or %NULL
2281 *
2282 * Sets a #PangoAttrList; the attributes in the list are applied to the
2283 * label text.
2284 *
2285 * The attributes set with this function will be applied
2286 * and merged with any other attributes previously effected by way
2287 * of the #CtkLabel:use-underline or #CtkLabel:use-markup properties.
2288 * While it is not recommended to mix markup strings with manually set
2289 * attributes, if you must; know that the attributes will be applied
2290 * to the label after the markup string is parsed.
2291 **/
2292void
2293ctk_label_set_attributes (CtkLabel *label,
2294 PangoAttrList *attrs)
2295{
2296 CtkLabelPrivate *priv = label->priv;
2297
2298 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
2299
2300 if (attrs)
2301 pango_attr_list_ref (attrs);
2302
2303 if (priv->attrs)
2304 pango_attr_list_unref (priv->attrs);
2305 priv->attrs = attrs;
2306
2307 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_ATTRIBUTES]);
2308
2309 ctk_label_clear_layout (label);
2310 ctk_widget_queue_resize (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
2311}
2312
2313/**
2314 * ctk_label_get_attributes:
2315 * @label: a #CtkLabel
2316 *
2317 * Gets the attribute list that was set on the label using
2318 * ctk_label_set_attributes(), if any. This function does
2319 * not reflect attributes that come from the labels markup
2320 * (see ctk_label_set_markup()). If you want to get the
2321 * effective attributes for the label, use
2322 * pango_layout_get_attribute (ctk_label_get_layout (label)).
2323 *
2324 * Returns: (nullable) (transfer none): the attribute list, or %NULL
2325 * if none was set.
2326 **/
2327PangoAttrList *
2328ctk_label_get_attributes (CtkLabel *label)
2329{
2330 g_return_val_if_fail (CTK_IS_LABEL (label), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return (((void*)0)); } } while (
0)
;
2331
2332 return label->priv->attrs;
2333}
2334
2335/**
2336 * ctk_label_set_label:
2337 * @label: a #CtkLabel
2338 * @str: the new text to set for the label
2339 *
2340 * Sets the text of the label. The label is interpreted as
2341 * including embedded underlines and/or Pango markup depending
2342 * on the values of the #CtkLabel:use-underline and
2343 * #CtkLabel:use-markup properties.
2344 **/
2345void
2346ctk_label_set_label (CtkLabel *label,
2347 const gchar *str)
2348{
2349 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
2350
2351 g_object_freeze_notify (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
2352
2353 ctk_label_set_label_internal (label, g_strdup (str ? str : "")g_strdup_inline (str ? str : ""));
2354 ctk_label_recalculate (label);
2355
2356 g_object_thaw_notify (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
2357}
2358
2359/**
2360 * ctk_label_get_label:
2361 * @label: a #CtkLabel
2362 *
2363 * Fetches the text from a label widget including any embedded
2364 * underlines indicating mnemonics and Pango markup. (See
2365 * ctk_label_get_text()).
2366 *
2367 * Returns: the text of the label widget. This string is
2368 * owned by the widget and must not be modified or freed.
2369 **/
2370const gchar *
2371ctk_label_get_label (CtkLabel *label)
2372{
2373 g_return_val_if_fail (CTK_IS_LABEL (label), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return (((void*)0)); } } while (
0)
;
2374
2375 return label->priv->label;
2376}
2377
2378typedef struct
2379{
2380 CtkLabel *label;
2381 GList *links;
2382 GString *new_str;
2383 gsize text_len;
2384} UriParserData;
2385
2386static void
2387start_element_handler (GMarkupParseContext *context,
2388 const gchar *element_name,
2389 const gchar **attribute_names,
2390 const gchar **attribute_values,
2391 gpointer user_data,
2392 GError **error)
2393{
2394 CtkLabelPrivate *priv;
2395 UriParserData *pdata = user_data;
2396
2397 if (strcmp (element_name, "a") == 0)
2398 {
2399 CtkLabelLink *link;
2400 const gchar *uri = NULL((void*)0);
2401 const gchar *title = NULL((void*)0);
2402 gboolean visited = FALSE(0);
2403 gint line_number;
2404 gint char_number;
2405 gint i;
2406 CtkCssNode *widget_node;
2407 CtkStateFlags state;
2408
2409 g_markup_parse_context_get_position (context, &line_number, &char_number);
2410
2411 for (i = 0; attribute_names[i] != NULL((void*)0); i++)
2412 {
2413 const gchar *attr = attribute_names[i];
2414
2415 if (strcmp (attr, "href") == 0)
2416 uri = attribute_values[i];
2417 else if (strcmp (attr, "title") == 0)
2418 title = attribute_values[i];
2419 else
2420 {
2421 g_set_error (error,
2422 G_MARKUP_ERRORg_markup_error_quark (),
2423 G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
2424 "Attribute '%s' is not allowed on the <a> tag "
2425 "on line %d char %d",
2426 attr, line_number, char_number);
2427 return;
2428 }
2429 }
2430
2431 if (uri == NULL((void*)0))
2432 {
2433 g_set_error (error,
2434 G_MARKUP_ERRORg_markup_error_quark (),
2435 G_MARKUP_ERROR_INVALID_CONTENT,
2436 "Attribute 'href' was missing on the <a> tag "
2437 "on line %d char %d",
2438 line_number, char_number);
2439 return;
2440 }
2441
2442 visited = FALSE(0);
2443 priv = pdata->label->priv;
2444 if (priv->track_links && priv->select_info)
2445 {
2446 GList *l;
2447 for (l = priv->select_info->links; l; l = l->next)
2448 {
2449 link = l->data;
2450 if (strcmp (uri, link->uri) == 0)
2451 {
2452 visited = link->visited;
2453 break;
2454 }
2455 }
2456 }
2457
2458 link = g_new0 (CtkLabelLink, 1)((CtkLabelLink *) g_malloc0_n ((1), sizeof (CtkLabelLink)));
2459 link->uri = g_strdup (uri)g_strdup_inline (uri);
2460 link->title = g_strdup (title)g_strdup_inline (title);
2461
2462 widget_node = ctk_widget_get_css_node (CTK_WIDGET (pdata->label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((pdata->label)), ((ctk_widget_get_type ()))))))
);
2463 link->cssnode = ctk_css_node_new ();
2464 ctk_css_node_set_name (link->cssnode, I_("link")g_intern_static_string ("link"));
2465 ctk_css_node_set_parent (link->cssnode, widget_node);
2466 state = ctk_css_node_get_state (widget_node);
2467 if (visited)
2468 state |= CTK_STATE_FLAG_VISITED;
2469 else
2470 state |= CTK_STATE_FLAG_LINK;
2471 ctk_css_node_set_state (link->cssnode, state);
2472 g_object_unref (link->cssnode);
2473
2474 link->visited = visited;
2475 link->start = pdata->text_len;
2476 pdata->links = g_list_prepend (pdata->links, link);
2477 }
2478 else
2479 {
2480 gint i;
2481
2482 g_string_append_c (pdata->new_str, '<')g_string_append_c_inline (pdata->new_str, '<');
2483 g_string_append (pdata->new_str, element_name)(__builtin_constant_p (element_name) ? __extension__ ({ const
char * const __val = (element_name); g_string_append_len_inline
(pdata->new_str, __val, (__val != ((void*)0)) ? (gssize) strlen
(((__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(pdata->new_str, element_name, (gssize) -1))
;
2484
2485 for (i = 0; attribute_names[i] != NULL((void*)0); i++)
2486 {
2487 const gchar *attr = attribute_names[i];
2488 const gchar *value = attribute_values[i];
2489 gchar *newvalue;
2490
2491 newvalue = g_markup_escape_text (value, -1);
2492
2493 g_string_append_c (pdata->new_str, ' ')g_string_append_c_inline (pdata->new_str, ' ');
2494 g_string_append (pdata->new_str, attr)(__builtin_constant_p (attr) ? __extension__ ({ const char * const
__val = (attr); g_string_append_len_inline (pdata->new_str
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (pdata
->new_str, attr, (gssize) -1))
;
2495 g_string_append (pdata->new_str, "=\"")(__builtin_constant_p ("=\"") ? __extension__ ({ const char *
const __val = ("=\""); g_string_append_len_inline (pdata->
new_str, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val
) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(pdata->new_str, "=\"", (gssize) -1))
;
2496 g_string_append (pdata->new_str, newvalue)(__builtin_constant_p (newvalue) ? __extension__ ({ const char
* const __val = (newvalue); g_string_append_len_inline (pdata
->new_str, __val, (__val != ((void*)0)) ? (gssize) strlen (
((__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(pdata->new_str, newvalue, (gssize) -1))
;
2497 g_string_append_c (pdata->new_str, '\"')g_string_append_c_inline (pdata->new_str, '\"');
2498
2499 g_free (newvalue);
2500 }
2501 g_string_append_c (pdata->new_str, '>')g_string_append_c_inline (pdata->new_str, '>');
2502 }
2503}
2504
2505static void
2506end_element_handler (GMarkupParseContext *context G_GNUC_UNUSED__attribute__ ((__unused__)),
2507 const gchar *element_name,
2508 gpointer user_data,
2509 GError **error G_GNUC_UNUSED__attribute__ ((__unused__)))
2510{
2511 UriParserData *pdata = user_data;
2512
2513 if (!strcmp (element_name, "a"))
2514 {
2515 CtkLabelLink *link = pdata->links->data;
2516 link->end = pdata->text_len;
2517 }
2518 else
2519 {
2520 g_string_append (pdata->new_str, "</")(__builtin_constant_p ("</") ? __extension__ ({ const char
* const __val = ("</"); g_string_append_len_inline (pdata
->new_str, __val, (__val != ((void*)0)) ? (gssize) strlen (
((__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(pdata->new_str, "</", (gssize) -1))
;
2521 g_string_append (pdata->new_str, element_name)(__builtin_constant_p (element_name) ? __extension__ ({ const
char * const __val = (element_name); g_string_append_len_inline
(pdata->new_str, __val, (__val != ((void*)0)) ? (gssize) strlen
(((__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(pdata->new_str, element_name, (gssize) -1))
;
2522 g_string_append_c (pdata->new_str, '>')g_string_append_c_inline (pdata->new_str, '>');
2523 }
2524}
2525
2526static void
2527text_handler (GMarkupParseContext *context G_GNUC_UNUSED__attribute__ ((__unused__)),
2528 const gchar *text,
2529 gsize text_len,
2530 gpointer user_data,
2531 GError **error G_GNUC_UNUSED__attribute__ ((__unused__)))
2532{
2533 UriParserData *pdata = user_data;
2534 gchar *newtext;
2535
2536 newtext = g_markup_escape_text (text, text_len);
2537 g_string_append (pdata->new_str, newtext)(__builtin_constant_p (newtext) ? __extension__ ({ const char
* const __val = (newtext); g_string_append_len_inline (pdata
->new_str, __val, (__val != ((void*)0)) ? (gssize) strlen (
((__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(pdata->new_str, newtext, (gssize) -1))
;
2538 pdata->text_len += text_len;
2539 g_free (newtext);
2540}
2541
2542static const GMarkupParser markup_parser =
2543{
2544 start_element_handler,
2545 end_element_handler,
2546 text_handler,
2547 NULL((void*)0),
2548 NULL((void*)0)
2549};
2550
2551static gboolean
2552xml_isspace (gchar c)
2553{
2554 return (c == ' ' || c == '\t' || c == '\n' || c == '\r');
2555}
2556
2557static void
2558link_free (CtkLabelLink *link)
2559{
2560 ctk_css_node_set_parent (link->cssnode, NULL((void*)0));
2561 g_free (link->uri);
2562 g_free (link->title);
2563 g_free (link);
2564}
2565
2566
2567static gboolean
2568parse_uri_markup (CtkLabel *label,
2569 const gchar *str,
2570 gchar **new_str,
2571 GList **links,
2572 GError **error)
2573{
2574 GMarkupParseContext *context = NULL((void*)0);
2575 const gchar *p, *end;
2576 gboolean needs_root = TRUE(!(0));
2577 gsize length;
2578 UriParserData pdata;
2579
2580 length = strlen (str);
2581 p = str;
2582 end = str + length;
2583
2584 pdata.label = label;
2585 pdata.links = NULL((void*)0);
2586 pdata.new_str = g_string_sized_new (length);
2587 pdata.text_len = 0;
2588
2589 while (p != end && xml_isspace (*p))
2590 p++;
2591
2592 if (end - p >= 8 && strncmp (p, "<markup>", 8) == 0)
2593 needs_root = FALSE(0);
2594
2595 context = g_markup_parse_context_new (&markup_parser, 0, &pdata, NULL((void*)0));
2596
2597 if (needs_root)
2598 {
2599 if (!g_markup_parse_context_parse (context, "<markup>", -1, error))
2600 goto failed;
2601 }
2602
2603 if (!g_markup_parse_context_parse (context, str, length, error))
2604 goto failed;
2605
2606 if (needs_root)
2607 {
2608 if (!g_markup_parse_context_parse (context, "</markup>", -1, error))
2609 goto failed;
2610 }
2611
2612 if (!g_markup_parse_context_end_parse (context, error))
2613 goto failed;
2614
2615 g_markup_parse_context_free (context);
2616
2617 *new_str = g_string_free (pdata.new_str, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((pdata
.new_str), ((0))) : g_string_free_and_steal (pdata.new_str)) :
(g_string_free) ((pdata.new_str), ((0))))
;
2618 *links = pdata.links;
2619
2620 return TRUE(!(0));
2621
2622failed:
2623 g_markup_parse_context_free (context);
2624 g_string_free (pdata.new_str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(pdata.new_str), ((!(0)))) : g_string_free_and_steal (pdata.new_str
)) : (g_string_free) ((pdata.new_str), ((!(0)))))
;
2625 g_list_free_full (pdata.links, (GDestroyNotify) link_free);
2626
2627 return FALSE(0);
2628}
2629
2630static void
2631ctk_label_ensure_has_tooltip (CtkLabel *label)
2632{
2633 CtkLabelPrivate *priv = label->priv;
2634 GList *l;
2635 gboolean has_tooltip = FALSE(0);
2636
2637 for (l = priv->select_info->links; l; l = l->next)
2638 {
2639 CtkLabelLink *link = l->data;
2640 if (link->title)
2641 {
2642 has_tooltip = TRUE(!(0));
2643 break;
2644 }
2645 }
2646
2647 ctk_widget_set_has_tooltip (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
, has_tooltip);
2648}
2649
2650static void
2651ctk_label_set_markup_internal (CtkLabel *label,
2652 const gchar *str,
2653 gboolean with_uline)
2654{
2655 CtkLabelPrivate *priv = label->priv;
2656 gchar *text = NULL((void*)0);
2657 GError *error = NULL((void*)0);
2658 PangoAttrList *attrs = NULL((void*)0);
2659 gunichar accel_char = 0;
2660 gchar *str_for_display = NULL((void*)0);
2661 gchar *str_for_accel = NULL((void*)0);
2662 GList *links = NULL((void*)0);
2663
2664 if (!parse_uri_markup (label, str, &str_for_display, &links, &error))
2665 {
2666 g_warning ("Failed to set text '%s' from markup due to error parsing markup: %s",
2667 str, error->message);
2668 g_error_free (error);
2669 return;
2670 }
2671
2672 str_for_accel = g_strdup (str_for_display)g_strdup_inline (str_for_display);
2673
2674 if (links)
2675 {
2676 ctk_label_ensure_select_info (label);
2677 priv->select_info->links = g_list_reverse (links);
2678 _ctk_label_accessible_update_links (label);
2679 ctk_label_ensure_has_tooltip (label);
2680 }
2681
2682 if (with_uline)
2683 {
2684 gboolean enable_mnemonics = TRUE(!(0));
2685 gboolean auto_mnemonics = TRUE(!(0));
2686
2687 g_object_get (ctk_widget_get_settings (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
),
2688 "ctk-enable-mnemonics", &enable_mnemonics,
2689 NULL((void*)0));
2690
2691 if (!(enable_mnemonics && priv->mnemonics_visible &&
2692 (!auto_mnemonics ||
2693 (ctk_widget_is_sensitive (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
) &&
2694 (!priv->mnemonic_widget ||
2695 ctk_widget_is_sensitive (priv->mnemonic_widget))))))
2696 {
2697 gchar *tmp;
2698 gchar *pattern;
2699 guint key;
2700
2701 if (separate_uline_pattern (str_for_display, &key, &tmp, &pattern))
2702 {
2703 g_free (str_for_display);
2704 str_for_display = tmp;
2705 g_free (pattern);
2706 }
2707 }
2708 }
2709
2710 /* Extract the text to display */
2711 if (!pango_parse_markup (str_for_display,
2712 -1,
2713 with_uline ? '_' : 0,
2714 &attrs,
2715 &text,
2716 NULL((void*)0),
2717 &error))
2718 {
2719 g_warning ("Failed to set text '%s' from markup due to error parsing markup: %s",
2720 str_for_display, error->message);
2721 g_free (str_for_display);
2722 g_free (str_for_accel);
2723 g_error_free (error);
2724 return;
2725 }
2726
2727 /* Extract the accelerator character */
2728 if (with_uline && !pango_parse_markup (str_for_accel,
2729 -1,
2730 '_',
2731 NULL((void*)0),
2732 NULL((void*)0),
2733 &accel_char,
2734 &error))
2735 {
2736 g_warning ("Failed to set text from markup due to error parsing markup: %s",
2737 error->message);
2738 g_free (str_for_display);
2739 g_free (str_for_accel);
2740 g_error_free (error);
2741 return;
2742 }
2743
2744 g_free (str_for_display);
2745 g_free (str_for_accel);
2746
2747 if (text)
2748 ctk_label_set_text_internal (label, text);
2749
2750 if (attrs)
2751 {
2752 if (priv->markup_attrs)
2753 pango_attr_list_unref (priv->markup_attrs);
2754 priv->markup_attrs = attrs;
2755 }
2756
2757 if (accel_char != 0)
2758 priv->mnemonic_keyval = cdk_keyval_to_lower (cdk_unicode_to_keyval (accel_char));
2759 else
2760 priv->mnemonic_keyval = CDK_KEY_VoidSymbol0xffffff;
2761}
2762
2763/**
2764 * ctk_label_set_markup:
2765 * @label: a #CtkLabel
2766 * @str: a markup string (see [Pango markup format][PangoMarkupFormat])
2767 *
2768 * Parses @str which is marked up with the
2769 * [Pango text markup language][PangoMarkupFormat], setting the
2770 * label’s text and attribute list based on the parse results.
2771 *
2772 * If the @str is external data, you may need to escape it with
2773 * g_markup_escape_text() or g_markup_printf_escaped():
2774 *
2775 * |[<!-- language="C" -->
2776 * CtkWidget *label = ctk_label_new (NULL);
2777 * const char *str = "some text";
2778 * const char *format = "<span style=\"italic\">\%s</span>";
2779 * char *markup;
2780 *
2781 * markup = g_markup_printf_escaped (format, str);
2782 * ctk_label_set_markup (CTK_LABEL (label), markup);
2783 * g_free (markup);
2784 * ]|
2785 *
2786 * This function will set the #CtkLabel:use-markup property to %TRUE as
2787 * a side effect.
2788 *
2789 * If you set the label contents using the #CtkLabel:label property you
2790 * should also ensure that you set the #CtkLabel:use-markup property
2791 * accordingly.
2792 *
2793 * See also: ctk_label_set_text()
2794 **/
2795void
2796ctk_label_set_markup (CtkLabel *label,
2797 const gchar *str)
2798{
2799 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
2800
2801 g_object_freeze_notify (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
2802
2803 ctk_label_set_label_internal (label, g_strdup (str ? str : "")g_strdup_inline (str ? str : ""));
2804 ctk_label_set_use_markup_internal (label, TRUE(!(0)));
2805 ctk_label_set_use_underline_internal (label, FALSE(0));
2806
2807 ctk_label_recalculate (label);
2808
2809 g_object_thaw_notify (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
2810}
2811
2812/**
2813 * ctk_label_set_markup_with_mnemonic:
2814 * @label: a #CtkLabel
2815 * @str: a markup string (see
2816 * [Pango markup format][PangoMarkupFormat])
2817 *
2818 * Parses @str which is marked up with the
2819 * [Pango text markup language][PangoMarkupFormat],
2820 * setting the label’s text and attribute list based on the parse results.
2821 * If characters in @str are preceded by an underscore, they are underlined
2822 * indicating that they represent a keyboard accelerator called a mnemonic.
2823 *
2824 * The mnemonic key can be used to activate another widget, chosen
2825 * automatically, or explicitly using ctk_label_set_mnemonic_widget().
2826 */
2827void
2828ctk_label_set_markup_with_mnemonic (CtkLabel *label,
2829 const gchar *str)
2830{
2831 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
2832
2833 g_object_freeze_notify (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
2834
2835 ctk_label_set_label_internal (label, g_strdup (str ? str : "")g_strdup_inline (str ? str : ""));
2836 ctk_label_set_use_markup_internal (label, TRUE(!(0)));
2837 ctk_label_set_use_underline_internal (label, TRUE(!(0)));
2838
2839 ctk_label_recalculate (label);
2840
2841 g_object_thaw_notify (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
2842}
2843
2844/**
2845 * ctk_label_get_text:
2846 * @label: a #CtkLabel
2847 *
2848 * Fetches the text from a label widget, as displayed on the
2849 * screen. This does not include any embedded underlines
2850 * indicating mnemonics or Pango markup. (See ctk_label_get_label())
2851 *
2852 * Returns: the text in the label widget. This is the internal
2853 * string used by the label, and must not be modified.
2854 **/
2855const gchar *
2856ctk_label_get_text (CtkLabel *label)
2857{
2858 g_return_val_if_fail (CTK_IS_LABEL (label), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return (((void*)0)); } } while (
0)
;
2859
2860 return label->priv->text;
2861}
2862
2863static PangoAttrList *
2864ctk_label_pattern_to_attrs (CtkLabel *label,
2865 const gchar *pattern)
2866{
2867 CtkLabelPrivate *priv = label->priv;
2868 const char *start;
2869 const char *p = priv->text;
2870 const char *q = pattern;
2871 PangoAttrList *attrs;
2872
2873 attrs = pango_attr_list_new ();
2874
2875 while (1)
2876 {
2877 while (*p && *q && *q != '_')
2878 {
2879 p = g_utf8_next_char (p)((p) + g_utf8_skip[*(const guchar *)(p)]);
2880 q++;
2881 }
2882 start = p;
2883 while (*p && *q && *q == '_')
2884 {
2885 p = g_utf8_next_char (p)((p) + g_utf8_skip[*(const guchar *)(p)]);
2886 q++;
2887 }
2888
2889 if (p > start)
2890 {
2891 PangoAttribute *attr = pango_attr_underline_new (PANGO_UNDERLINE_LOW);
2892 attr->start_index = start - priv->text;
2893 attr->end_index = p - priv->text;
2894
2895 pango_attr_list_insert (attrs, attr);
2896 }
2897 else
2898 break;
2899 }
2900
2901 return attrs;
2902}
2903
2904static void
2905ctk_label_set_pattern_internal (CtkLabel *label,
2906 const gchar *pattern,
2907 gboolean is_mnemonic)
2908{
2909 CtkLabelPrivate *priv = label->priv;
2910 PangoAttrList *attrs;
2911 gboolean enable_mnemonics = TRUE(!(0));
2912 gboolean auto_mnemonics = TRUE(!(0));
2913
2914 if (priv->pattern_set)
2915 return;
2916
2917 if (is_mnemonic)
2918 {
2919 g_object_get (ctk_widget_get_settings (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
),
2920 "ctk-enable-mnemonics", &enable_mnemonics,
2921 NULL((void*)0));
2922
2923 if (enable_mnemonics && priv->mnemonics_visible && pattern &&
2924 (!auto_mnemonics ||
2925 (ctk_widget_is_sensitive (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
) &&
2926 (!priv->mnemonic_widget ||
2927 ctk_widget_is_sensitive (priv->mnemonic_widget)))))
2928 attrs = ctk_label_pattern_to_attrs (label, pattern);
2929 else
2930 attrs = NULL((void*)0);
2931 }
2932 else
2933 attrs = ctk_label_pattern_to_attrs (label, pattern);
2934
2935 if (priv->markup_attrs)
2936 pango_attr_list_unref (priv->markup_attrs);
2937 priv->markup_attrs = attrs;
2938}
2939
2940/**
2941 * ctk_label_set_pattern:
2942 * @label: The #CtkLabel you want to set the pattern to.
2943 * @pattern: The pattern as described above.
2944 *
2945 * The pattern of underlines you want under the existing text within the
2946 * #CtkLabel widget. For example if the current text of the label says
2947 * “FooBarBaz” passing a pattern of “___ ___” will underline
2948 * “Foo” and “Baz” but not “Bar”.
2949 */
2950void
2951ctk_label_set_pattern (CtkLabel *label,
2952 const gchar *pattern)
2953{
2954 CtkLabelPrivate *priv;
2955
2956 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
2957
2958 priv = label->priv;
2959
2960 priv->pattern_set = FALSE(0);
2961
2962 if (pattern)
2963 {
2964 ctk_label_set_pattern_internal (label, pattern, FALSE(0));
2965 priv->pattern_set = TRUE(!(0));
2966 }
2967 else
2968 ctk_label_recalculate (label);
2969
2970 ctk_label_clear_layout (label);
2971 ctk_widget_queue_resize (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
2972}
2973
2974
2975/**
2976 * ctk_label_set_justify:
2977 * @label: a #CtkLabel
2978 * @jtype: a #CtkJustification
2979 *
2980 * Sets the alignment of the lines in the text of the label relative to
2981 * each other. %CTK_JUSTIFY_LEFT is the default value when the widget is
2982 * first created with ctk_label_new(). If you instead want to set the
2983 * alignment of the label as a whole, use ctk_widget_set_halign() instead.
2984 * ctk_label_set_justify() has no effect on labels containing only a
2985 * single line.
2986 */
2987void
2988ctk_label_set_justify (CtkLabel *label,
2989 CtkJustification jtype)
2990{
2991 CtkLabelPrivate *priv;
2992
2993 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
2994 g_return_if_fail (jtype >= CTK_JUSTIFY_LEFT && jtype <= CTK_JUSTIFY_FILL)do { if ((jtype >= CTK_JUSTIFY_LEFT && jtype <=
CTK_JUSTIFY_FILL)) { } else { g_return_if_fail_warning ("Ctk"
, ((const char*) (__func__)), "jtype >= CTK_JUSTIFY_LEFT && jtype <= CTK_JUSTIFY_FILL"
); return; } } while (0)
;
2995
2996 priv = label->priv;
2997
2998 if ((CtkJustification) priv->jtype != jtype)
2999 {
3000 priv->jtype = jtype;
3001
3002 /* No real need to be this drastic, but easier than duplicating the code */
3003 ctk_label_clear_layout (label);
3004
3005 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_JUSTIFY]);
3006 ctk_widget_queue_resize (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
3007 }
3008}
3009
3010/**
3011 * ctk_label_get_justify:
3012 * @label: a #CtkLabel
3013 *
3014 * Returns the justification of the label. See ctk_label_set_justify().
3015 *
3016 * Returns: #CtkJustification
3017 **/
3018CtkJustification
3019ctk_label_get_justify (CtkLabel *label)
3020{
3021 g_return_val_if_fail (CTK_IS_LABEL (label), 0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return (0); } } while (0)
;
3022
3023 return label->priv->jtype;
3024}
3025
3026/**
3027 * ctk_label_set_ellipsize:
3028 * @label: a #CtkLabel
3029 * @mode: a #PangoEllipsizeMode
3030 *
3031 * Sets the mode used to ellipsize (add an ellipsis: "...") to the text
3032 * if there is not enough space to render the entire string.
3033 *
3034 * Since: 2.6
3035 **/
3036void
3037ctk_label_set_ellipsize (CtkLabel *label,
3038 PangoEllipsizeMode mode)
3039{
3040 CtkLabelPrivate *priv;
3041
3042 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
3043 g_return_if_fail (mode >= PANGO_ELLIPSIZE_NONE && mode <= PANGO_ELLIPSIZE_END)do { if ((mode >= PANGO_ELLIPSIZE_NONE && mode <=
PANGO_ELLIPSIZE_END)) { } else { g_return_if_fail_warning ("Ctk"
, ((const char*) (__func__)), "mode >= PANGO_ELLIPSIZE_NONE && mode <= PANGO_ELLIPSIZE_END"
); return; } } while (0)
;
3044
3045 priv = label->priv;
3046
3047 if ((PangoEllipsizeMode) priv->ellipsize != mode)
3048 {
3049 priv->ellipsize = mode;
3050
3051 /* No real need to be this drastic, but easier than duplicating the code */
3052 ctk_label_clear_layout (label);
3053
3054 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_ELLIPSIZE]);
3055 ctk_widget_queue_resize (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
3056 }
3057}
3058
3059/**
3060 * ctk_label_get_ellipsize:
3061 * @label: a #CtkLabel
3062 *
3063 * Returns the ellipsizing position of the label. See ctk_label_set_ellipsize().
3064 *
3065 * Returns: #PangoEllipsizeMode
3066 *
3067 * Since: 2.6
3068 **/
3069PangoEllipsizeMode
3070ctk_label_get_ellipsize (CtkLabel *label)
3071{
3072 g_return_val_if_fail (CTK_IS_LABEL (label), PANGO_ELLIPSIZE_NONE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return (PANGO_ELLIPSIZE_NONE); }
} while (0)
;
3073
3074 return label->priv->ellipsize;
3075}
3076
3077/**
3078 * ctk_label_set_width_chars:
3079 * @label: a #CtkLabel
3080 * @n_chars: the new desired width, in characters.
3081 *
3082 * Sets the desired width in characters of @label to @n_chars.
3083 *
3084 * Since: 2.6
3085 **/
3086void
3087ctk_label_set_width_chars (CtkLabel *label,
3088 gint n_chars)
3089{
3090 CtkLabelPrivate *priv;
3091
3092 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
3093
3094 priv = label->priv;
3095
3096 if (priv->width_chars != n_chars)
3097 {
3098 priv->width_chars = n_chars;
3099 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_WIDTH_CHARS]);
3100 ctk_widget_queue_resize (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
3101 }
3102}
3103
3104/**
3105 * ctk_label_get_width_chars:
3106 * @label: a #CtkLabel
3107 *
3108 * Retrieves the desired width of @label, in characters. See
3109 * ctk_label_set_width_chars().
3110 *
3111 * Returns: the width of the label in characters.
3112 *
3113 * Since: 2.6
3114 **/
3115gint
3116ctk_label_get_width_chars (CtkLabel *label)
3117{
3118 g_return_val_if_fail (CTK_IS_LABEL (label), -1)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return (-1); } } while (0)
;
3119
3120 return label->priv->width_chars;
3121}
3122
3123/**
3124 * ctk_label_set_max_width_chars:
3125 * @label: a #CtkLabel
3126 * @n_chars: the new desired maximum width, in characters.
3127 *
3128 * Sets the desired maximum width in characters of @label to @n_chars.
3129 *
3130 * Since: 2.6
3131 **/
3132void
3133ctk_label_set_max_width_chars (CtkLabel *label,
3134 gint n_chars)
3135{
3136 CtkLabelPrivate *priv;
3137
3138 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
3139
3140 priv = label->priv;
3141
3142 if (priv->max_width_chars != n_chars)
3143 {
3144 priv->max_width_chars = n_chars;
3145
3146 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_MAX_WIDTH_CHARS]);
3147 ctk_widget_queue_resize (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
3148 }
3149}
3150
3151/**
3152 * ctk_label_get_max_width_chars:
3153 * @label: a #CtkLabel
3154 *
3155 * Retrieves the desired maximum width of @label, in characters. See
3156 * ctk_label_set_width_chars().
3157 *
3158 * Returns: the maximum width of the label in characters.
3159 *
3160 * Since: 2.6
3161 **/
3162gint
3163ctk_label_get_max_width_chars (CtkLabel *label)
3164{
3165 g_return_val_if_fail (CTK_IS_LABEL (label), -1)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return (-1); } } while (0)
;
3166
3167 return label->priv->max_width_chars;
3168}
3169
3170/**
3171 * ctk_label_set_line_wrap:
3172 * @label: a #CtkLabel
3173 * @wrap: the setting
3174 *
3175 * Toggles line wrapping within the #CtkLabel widget. %TRUE makes it break
3176 * lines if text exceeds the widget’s size. %FALSE lets the text get cut off
3177 * by the edge of the widget if it exceeds the widget size.
3178 *
3179 * Note that setting line wrapping to %TRUE does not make the label
3180 * wrap at its parent container’s width, because CTK+ widgets
3181 * conceptually can’t make their requisition depend on the parent
3182 * container’s size. For a label that wraps at a specific position,
3183 * set the label’s width using ctk_widget_set_size_request().
3184 **/
3185void
3186ctk_label_set_line_wrap (CtkLabel *label,
3187 gboolean wrap)
3188{
3189 CtkLabelPrivate *priv;
3190
3191 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
3192
3193 priv = label->priv;
3194
3195 wrap = wrap != FALSE(0);
3196
3197 if (priv->wrap != wrap)
3198 {
3199 priv->wrap = wrap;
3200
3201 ctk_label_clear_layout (label);
3202 ctk_widget_queue_resize (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
3203 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_WRAP]);
3204 }
3205}
3206
3207/**
3208 * ctk_label_get_line_wrap:
3209 * @label: a #CtkLabel
3210 *
3211 * Returns whether lines in the label are automatically wrapped.
3212 * See ctk_label_set_line_wrap().
3213 *
3214 * Returns: %TRUE if the lines of the label are automatically wrapped.
3215 */
3216gboolean
3217ctk_label_get_line_wrap (CtkLabel *label)
3218{
3219 g_return_val_if_fail (CTK_IS_LABEL (label), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return ((0)); } } while (0)
;
3220
3221 return label->priv->wrap;
3222}
3223
3224/**
3225 * ctk_label_set_line_wrap_mode:
3226 * @label: a #CtkLabel
3227 * @wrap_mode: the line wrapping mode
3228 *
3229 * If line wrapping is on (see ctk_label_set_line_wrap()) this controls how
3230 * the line wrapping is done. The default is %PANGO_WRAP_WORD which means
3231 * wrap on word boundaries.
3232 *
3233 * Since: 2.10
3234 **/
3235void
3236ctk_label_set_line_wrap_mode (CtkLabel *label,
3237 PangoWrapMode wrap_mode)
3238{
3239 CtkLabelPrivate *priv;
3240
3241 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
3242
3243 priv = label->priv;
3244
3245 if (priv->wrap_mode != wrap_mode)
3246 {
3247 priv->wrap_mode = wrap_mode;
3248 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_WRAP_MODE]);
3249
3250 ctk_widget_queue_resize (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
3251 }
3252}
3253
3254/**
3255 * ctk_label_get_line_wrap_mode:
3256 * @label: a #CtkLabel
3257 *
3258 * Returns line wrap mode used by the label. See ctk_label_set_line_wrap_mode().
3259 *
3260 * Returns: %TRUE if the lines of the label are automatically wrapped.
3261 *
3262 * Since: 2.10
3263 */
3264PangoWrapMode
3265ctk_label_get_line_wrap_mode (CtkLabel *label)
3266{
3267 g_return_val_if_fail (CTK_IS_LABEL (label), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return ((0)); } } while (0)
;
3268
3269 return label->priv->wrap_mode;
3270}
3271
3272static void
3273ctk_label_destroy (CtkWidget *widget)
3274{
3275 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
3276
3277 ctk_label_set_mnemonic_widget (label, NULL((void*)0));
3278
3279 CTK_WIDGET_CLASS (ctk_label_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_label_parent_class)), ((ctk_widget_get_type ()))))))
->destroy (widget);
3280}
3281
3282static void
3283ctk_label_finalize (GObject *object)
3284{
3285 CtkLabel *label = CTK_LABEL (object)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_label_get_type ()))))))
;
3286 CtkLabelPrivate *priv = label->priv;
3287
3288 g_free (priv->label);
3289 g_free (priv->text);
3290
3291 g_clear_object (&priv->layout)do { _Static_assert (sizeof *((&priv->layout)) == sizeof
(gpointer), "Expression evaluates to false"); __typeof__ (((
&priv->layout))) _pp = ((&priv->layout)); __typeof__
(*((&priv->layout))) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_object_unref) (_ptr); } while (0)
;
3292 g_clear_pointer (&priv->attrs, pango_attr_list_unref)do { _Static_assert (sizeof *(&priv->attrs) == sizeof (
gpointer), "Expression evaluates to false"); __typeof__ ((&
priv->attrs)) _pp = (&priv->attrs); __typeof__ (*(&
priv->attrs)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (pango_attr_list_unref
) (_ptr); } while (0)
;
3293 g_clear_pointer (&priv->markup_attrs, pango_attr_list_unref)do { _Static_assert (sizeof *(&priv->markup_attrs) == sizeof
(gpointer), "Expression evaluates to false"); __typeof__ ((&
priv->markup_attrs)) _pp = (&priv->markup_attrs); __typeof__
(*(&priv->markup_attrs)) _ptr = *_pp; *_pp = ((void*)
0); if (_ptr) (pango_attr_list_unref) (_ptr); } while (0)
;
3294
3295 if (priv->select_info)
3296 {
3297 g_object_unref (priv->select_info->drag_gesture);
3298 g_object_unref (priv->select_info->multipress_gesture);
3299 }
3300
3301 ctk_label_clear_links (label);
3302 g_free (priv->select_info);
3303
3304 g_clear_object (&priv->gadget)do { _Static_assert (sizeof *((&priv->gadget)) == sizeof
(gpointer), "Expression evaluates to false"); __typeof__ (((
&priv->gadget))) _pp = ((&priv->gadget)); __typeof__
(*((&priv->gadget))) _ptr = *_pp; *_pp = ((void*)0); if
(_ptr) (g_object_unref) (_ptr); } while (0)
;
3305
3306 G_OBJECT_CLASS (ctk_label_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_label_parent_class)), (((GType) ((20) << (2)))
)))))
->finalize (object);
3307}
3308
3309static void
3310ctk_label_clear_layout (CtkLabel *label)
3311{
3312 g_clear_object (&label->priv->layout)do { _Static_assert (sizeof *((&label->priv->layout
)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&label->priv->layout))) _pp = ((&label->
priv->layout)); __typeof__ (*((&label->priv->layout
))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
3313}
3314
3315/**
3316 * ctk_label_get_measuring_layout:
3317 * @label: the label
3318 * @existing_layout: %NULL or an existing layout already in use.
3319 * @width: the width to measure with in pango units, or -1 for infinite
3320 *
3321 * Gets a layout that can be used for measuring sizes. The returned
3322 * layout will be identical to the label’s layout except for the
3323 * layout’s width, which will be set to @width. Do not modify the returned
3324 * layout.
3325 *
3326 * Returns: a new reference to a pango layout
3327 **/
3328static PangoLayout *
3329ctk_label_get_measuring_layout (CtkLabel * label,
3330 PangoLayout *existing_layout,
3331 int width)
3332{
3333 CtkLabelPrivate *priv = label->priv;
3334 PangoRectangle rect;
3335 PangoLayout *copy;
3336
3337 if (existing_layout != NULL((void*)0))
3338 {
3339 if (existing_layout != priv->layout)
3340 {
3341 pango_layout_set_width (existing_layout, width);
3342 return existing_layout;
3343 }
3344
3345 g_object_unref (existing_layout);
3346 }
3347
3348 ctk_label_ensure_layout (label);
3349
3350 if (pango_layout_get_width (priv->layout) == width)
3351 {
3352 g_object_ref (priv->layout)((__typeof__ (priv->layout)) (g_object_ref) (priv->layout
))
;
3353 return priv->layout;
3354 }
3355
3356 /* We can use the label's own layout if we're not allocated a size yet,
3357 * because we don't need it to be properly setup at that point.
3358 * This way we can make use of caching upon the label's creation.
3359 */
3360 if (ctk_widget_get_allocated_width (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
) <= 1)
3361 {
3362 g_object_ref (priv->layout)((__typeof__ (priv->layout)) (g_object_ref) (priv->layout
))
;
3363 pango_layout_set_width (priv->layout, width);
3364 return priv->layout;
3365 }
3366
3367 /* oftentimes we want to measure a width that is far wider than the current width,
3368 * even though the layout would not change if we made it wider. In that case, we
3369 * can just return the current layout, because for measuring purposes, it will be
3370 * identical.
3371 */
3372 pango_layout_get_extents (priv->layout, NULL((void*)0), &rect);
3373 if ((width == -1 || rect.width <= width) &&
3374 !pango_layout_is_wrapped (priv->layout) &&
3375 !pango_layout_is_ellipsized (priv->layout))
3376 {
3377 g_object_ref (priv->layout)((__typeof__ (priv->layout)) (g_object_ref) (priv->layout
))
;
3378 return priv->layout;
3379 }
3380
3381 copy = pango_layout_copy (priv->layout);
3382 pango_layout_set_width (copy, width);
3383 return copy;
3384}
3385
3386static void
3387ctk_label_update_layout_width (CtkLabel *label)
3388{
3389 CtkLabelPrivate *priv = label->priv;
3390 CtkWidget *widget = CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
;
3391
3392 g_assert (priv->layout)do { if (priv->layout) ; else g_assertion_message_expr ("Ctk"
, "ctklabel.c", 3392, ((const char*) (__func__)), "priv->layout"
); } while (0)
;
3393
3394 if (priv->ellipsize || priv->wrap)
3395 {
3396 CtkAllocation allocation;
3397 int xpad, ypad;
3398 PangoRectangle logical;
3399 gint width, height;
3400
3401 ctk_css_gadget_get_content_allocation (priv->gadget, &allocation, NULL((void*)0));
3402G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
3403 ctk_misc_get_padding (CTK_MISC (label)((((CtkMisc*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_misc_get_type ()))))))
, &xpad, &ypad);
3404G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop
3405
3406 width = allocation.width - 2 * xpad;
3407 height = allocation.height - 2 * ypad;
3408
3409 if (priv->have_transform)
3410 {
3411 PangoContext *context = ctk_widget_get_pango_context (widget);
3412 const PangoMatrix *matrix = pango_context_get_matrix (context);
3413 const gdouble dx = matrix->xx; /* cos (M_PI * angle / 180) */
3414 const gdouble dy = matrix->xy; /* sin (M_PI * angle / 180) */
3415
3416 pango_layout_set_width (priv->layout, -1);
3417 pango_layout_get_pixel_extents (priv->layout, NULL((void*)0), &logical);
3418
3419 if (fabs (dy) < 0.01)
3420 {
3421 if (logical.width > width)
3422 pango_layout_set_width (priv->layout, width * PANGO_SCALE1024);
3423 }
3424 else if (fabs (dx) < 0.01)
3425 {
3426 if (logical.width > height)
3427 pango_layout_set_width (priv->layout, height * PANGO_SCALE1024);
3428 }
3429 else
3430 {
3431 gdouble x0, y0, x1, y1, length;
3432 gboolean vertical;
3433 gint cy;
3434
3435 x0 = width / 2;
3436 y0 = dx ? x0 * dy / dx : G_MAXDOUBLE1.7976931348623157e+308;
3437 vertical = fabs (y0) > height / 2;
3438
3439 if (vertical)
3440 {
3441 y0 = height/2;
3442 x0 = dy ? y0 * dx / dy : G_MAXDOUBLE1.7976931348623157e+308;
3443 }
3444
3445 length = 2 * sqrt (x0 * x0 + y0 * y0);
3446 pango_layout_set_width (priv->layout, rint (length * PANGO_SCALE1024));
3447 pango_layout_get_pixel_size (priv->layout, NULL((void*)0), &cy);
3448
3449 x1 = +dy * cy/2;
3450 y1 = -dx * cy/2;
3451
3452 if (vertical)
3453 {
3454 y0 = height/2 + y1 - y0;
3455 x0 = -y0 * dx/dy;
3456 }
3457 else
3458 {
3459 x0 = width/2 + x1 - x0;
3460 y0 = -x0 * dy/dx;
3461 }
3462
3463 length = length - sqrt (x0 * x0 + y0 * y0) * 2;
3464 pango_layout_set_width (priv->layout, rint (length * PANGO_SCALE1024));
3465 }
3466 }
3467 else
3468 {
3469 pango_layout_set_width (priv->layout, width * PANGO_SCALE1024);
3470 }
3471 }
3472 else
3473 {
3474 pango_layout_set_width (priv->layout, -1);
3475 }
3476}
3477
3478static void
3479ctk_label_update_layout_attributes (CtkLabel *label)
3480{
3481 CtkLabelPrivate *priv = label->priv;
3482 CtkWidget *widget = CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
;
3483 CtkStyleContext *context;
3484 PangoAttrList *attrs;
3485 PangoAttrList *style_attrs;
3486
3487 if (priv->layout == NULL((void*)0))
3488 return;
3489
3490 context = ctk_widget_get_style_context (widget);
3491
3492 if (priv->select_info && priv->select_info->links)
3493 {
3494 CdkRGBA link_color;
3495 PangoAttribute *attribute;
3496 GList *list;
3497
3498 attrs = pango_attr_list_new ();
3499
3500 for (list = priv->select_info->links; list; list = list->next)
3501 {
3502 CtkLabelLink *link = list->data;
3503
3504 attribute = pango_attr_underline_new (TRUE(!(0)));
3505 attribute->start_index = link->start;
3506 attribute->end_index = link->end;
3507 pango_attr_list_insert (attrs, attribute);
3508
3509 ctk_style_context_save_to_node (context, link->cssnode);
3510 ctk_style_context_get_color (context, ctk_style_context_get_state (context), &link_color);
3511 ctk_style_context_restore (context);
3512
3513 attribute = pango_attr_foreground_new (link_color.red * 65535,
3514 link_color.green * 65535,
3515 link_color.blue * 65535);
3516 attribute->start_index = link->start;
3517 attribute->end_index = link->end;
3518 pango_attr_list_insert (attrs, attribute);
3519 }
3520 }
3521 else if (priv->markup_attrs && priv->attrs)
3522 attrs = pango_attr_list_new ();
3523 else
3524 attrs = NULL((void*)0);
3525
3526 style_attrs = _ctk_style_context_get_pango_attributes (context);
3527
3528 attrs = _ctk_pango_attr_list_merge (attrs, style_attrs);
3529 attrs = _ctk_pango_attr_list_merge (attrs, priv->markup_attrs);
3530 attrs = _ctk_pango_attr_list_merge (attrs, priv->attrs);
3531
3532 pango_layout_set_attributes (priv->layout, attrs);
3533
3534 if (attrs)
3535 pango_attr_list_unref (attrs);
3536 if (style_attrs)
3537 pango_attr_list_unref (style_attrs);
3538}
3539
3540static void
3541ctk_label_ensure_layout (CtkLabel *label)
3542{
3543 CtkLabelPrivate *priv = label->priv;
3544 CtkWidget *widget;
3545 gboolean rtl;
3546
3547 widget = CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
;
3548
3549 rtl = ctk_widget_get_direction (widget) == CTK_TEXT_DIR_RTL;
3550
3551 if (!priv->layout)
3552 {
3553 PangoAlignment align = PANGO_ALIGN_LEFT; /* Quiet gcc */
3554 gdouble angle = ctk_label_get_angle (label);
3555
3556 if (angle != 0.0 && !priv->select_info)
3557 {
3558 PangoMatrix matrix = PANGO_MATRIX_INIT{ 1., 0., 0., 1., 0., 0. };
3559
3560 /* We rotate the standard singleton PangoContext for the widget,
3561 * depending on the fact that it's meant pretty much exclusively
3562 * for our use.
3563 */
3564 pango_matrix_rotate (&matrix, angle);
3565
3566 pango_context_set_matrix (ctk_widget_get_pango_context (widget), &matrix);
3567
3568 priv->have_transform = TRUE(!(0));
3569 }
3570 else
3571 {
3572 if (priv->have_transform)
3573 pango_context_set_matrix (ctk_widget_get_pango_context (widget), NULL((void*)0));
3574
3575 priv->have_transform = FALSE(0);
3576 }
3577
3578 priv->layout = ctk_widget_create_pango_layout (widget, priv->text);
3579
3580 ctk_label_update_layout_attributes (label);
3581
3582 switch (priv->jtype)
3583 {
3584 case CTK_JUSTIFY_LEFT:
3585 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
3586 break;
3587 case CTK_JUSTIFY_RIGHT:
3588 align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
3589 break;
3590 case CTK_JUSTIFY_CENTER:
3591 align = PANGO_ALIGN_CENTER;
3592 break;
3593 case CTK_JUSTIFY_FILL:
3594 align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
3595 pango_layout_set_justify (priv->layout, TRUE(!(0)));
3596 break;
3597 default:
3598 g_assert_not_reached()do { g_assertion_message_expr ("Ctk", "ctklabel.c", 3598, ((const
char*) (__func__)), ((void*)0)); } while (0)
;
3599 }
3600
3601 pango_layout_set_alignment (priv->layout, align);
3602 pango_layout_set_ellipsize (priv->layout, priv->ellipsize);
3603 pango_layout_set_wrap (priv->layout, priv->wrap_mode);
3604 pango_layout_set_single_paragraph_mode (priv->layout, priv->single_line_mode);
3605 if (priv->lines > 0)
3606 pango_layout_set_height (priv->layout, - priv->lines);
3607
3608 ctk_label_update_layout_width (label);
3609 }
3610}
3611
3612static CtkSizeRequestMode
3613ctk_label_get_request_mode (CtkWidget *widget)
3614{
3615 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
3616 gdouble angle;
3617
3618 angle = ctk_label_get_angle (label);
3619
3620 if (label->priv->wrap)
3621 return (angle == 90 || angle == 270)
3622 ? CTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT
3623 : CTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
3624
3625 return CTK_SIZE_REQUEST_CONSTANT_SIZE;
3626}
3627
3628
3629static void
3630get_size_for_allocation (CtkLabel *label,
3631 gint allocation,
3632 gint *minimum_size,
3633 gint *natural_size,
3634 gint *minimum_baseline,
3635 gint *natural_baseline)
3636{
3637 PangoLayout *layout;
3638 gint text_height, baseline;
3639
3640 layout = ctk_label_get_measuring_layout (label, NULL((void*)0), allocation * PANGO_SCALE1024);
3641
3642 pango_layout_get_pixel_size (layout, NULL((void*)0), &text_height);
3643
3644 *minimum_size = text_height;
3645 *natural_size = text_height;
3646
3647 if (minimum_baseline || natural_baseline)
11
Assuming 'minimum_baseline' is null
12
Assuming 'natural_baseline' is non-null
13
Taking true branch
3648 {
3649 baseline = pango_layout_get_baseline (layout) / PANGO_SCALE1024;
3650 *minimum_baseline = baseline;
14
Dereference of null pointer (loaded from variable 'minimum_baseline')
3651 *natural_baseline = baseline;
3652 }
3653
3654 g_object_unref (layout);
3655}
3656
3657static gint
3658get_char_pixels (CtkWidget *label G_GNUC_UNUSED__attribute__ ((__unused__)),
3659 PangoLayout *layout)
3660{
3661 PangoContext *context;
3662 PangoFontMetrics *metrics;
3663 gint char_width, digit_width;
3664
3665 context = pango_layout_get_context (layout);
3666 metrics = pango_context_get_metrics (context,
3667 pango_context_get_font_description (context),
3668 pango_context_get_language (context));
3669 char_width = pango_font_metrics_get_approximate_char_width (metrics);
3670 digit_width = pango_font_metrics_get_approximate_digit_width (metrics);
3671 pango_font_metrics_unref (metrics);
3672
3673 return MAX (char_width, digit_width)(((char_width) > (digit_width)) ? (char_width) : (digit_width
))
;;
3674}
3675
3676static void
3677ctk_label_get_preferred_layout_size (CtkLabel *label,
3678 PangoRectangle *smallest,
3679 PangoRectangle *widest)
3680{
3681 CtkLabelPrivate *priv = label->priv;
3682 PangoLayout *layout;
3683 gint char_pixels;
3684
3685 /* "width-chars" Hard-coded minimum width:
3686 * - minimum size should be MAX (width-chars, strlen ("..."));
3687 * - natural size should be MAX (width-chars, strlen (priv->text));
3688 *
3689 * "max-width-chars" User specified maximum size requisition
3690 * - minimum size should be MAX (width-chars, 0)
3691 * - natural size should be MIN (max-width-chars, strlen (priv->text))
3692 *
3693 * For ellipsizing labels; if max-width-chars is specified: either it is used as
3694 * a minimum size or the label text as a minimum size (natural size still overflows).
3695 *
3696 * For wrapping labels; A reasonable minimum size is useful to naturally layout
3697 * interfaces automatically. In this case if no "width-chars" is specified, the minimum
3698 * width will default to the wrap guess that ctk_label_ensure_layout() does.
3699 */
3700
3701 /* Start off with the pixel extents of an as-wide-as-possible layout */
3702 layout = ctk_label_get_measuring_layout (label, NULL((void*)0), -1);
3703
3704 if (priv->width_chars > -1 || priv->max_width_chars > -1)
3705 char_pixels = get_char_pixels (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
, layout);
3706 else
3707 char_pixels = 0;
3708
3709 pango_layout_get_extents (layout, NULL((void*)0), widest);
3710 widest->width = MAX (widest->width, char_pixels * priv->width_chars)(((widest->width) > (char_pixels * priv->width_chars
)) ? (widest->width) : (char_pixels * priv->width_chars
))
;
3711 widest->x = widest->y = 0;
3712
3713 if (priv->ellipsize || priv->wrap)
3714 {
3715 /* a layout with width 0 will be as small as humanly possible */
3716 layout = ctk_label_get_measuring_layout (label,
3717 layout,
3718 priv->width_chars > -1 ? char_pixels * priv->width_chars
3719 : 0);
3720
3721 pango_layout_get_extents (layout, NULL((void*)0), smallest);
3722 smallest->width = MAX (smallest->width, char_pixels * priv->width_chars)(((smallest->width) > (char_pixels * priv->width_chars
)) ? (smallest->width) : (char_pixels * priv->width_chars
))
;
3723 smallest->x = smallest->y = 0;
3724
3725 if (priv->max_width_chars > -1 && widest->width > char_pixels * priv->max_width_chars)
3726 {
3727 layout = ctk_label_get_measuring_layout (label,
3728 layout,
3729 MAX (smallest->width, char_pixels * priv->max_width_chars)(((smallest->width) > (char_pixels * priv->max_width_chars
)) ? (smallest->width) : (char_pixels * priv->max_width_chars
))
);
3730 pango_layout_get_extents (layout, NULL((void*)0), widest);
3731 widest->width = MAX (widest->width, char_pixels * priv->width_chars)(((widest->width) > (char_pixels * priv->width_chars
)) ? (widest->width) : (char_pixels * priv->width_chars
))
;
3732 widest->x = widest->y = 0;
3733 }
3734 }
3735 else
3736 {
3737 *smallest = *widest;
3738 }
3739
3740 if (widest->width < smallest->width)
3741 *smallest = *widest;
3742
3743 g_object_unref (layout);
3744}
3745
3746static void
3747ctk_label_get_preferred_size (CtkWidget *widget,
3748 CtkOrientation orientation,
3749 gint *minimum_size,
3750 gint *natural_size,
3751 gint *minimum_baseline,
3752 gint *natural_baseline)
3753{
3754 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
3755 CtkLabelPrivate *priv = label->priv;
3756 gint xpad, ypad;
3757 PangoRectangle widest_rect;
3758 PangoRectangle smallest_rect;
3759
3760G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
3761 ctk_misc_get_padding (CTK_MISC (label)((((CtkMisc*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_misc_get_type ()))))))
, &xpad, &ypad);
3762G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop
3763
3764 ctk_label_get_preferred_layout_size (label, &smallest_rect, &widest_rect);
3765
3766 /* Now that we have minimum and natural sizes in pango extents, apply a possible transform */
3767 if (priv->have_transform)
3768 {
3769 PangoContext *context;
3770 const PangoMatrix *matrix;
3771
3772 context = pango_layout_get_context (priv->layout);
3773 matrix = pango_context_get_matrix (context);
3774
3775 pango_matrix_transform_rectangle (matrix, &widest_rect);
3776 pango_matrix_transform_rectangle (matrix, &smallest_rect);
3777
3778 /* Bump the size in case of ellipsize to ensure pango has
3779 * enough space in the angles (note, we could alternatively set the
3780 * layout to not ellipsize when we know we have been allocated our
3781 * full size, or it may be that pango needs a fix here).
3782 */
3783 if (priv->ellipsize && priv->angle != 0 && priv->angle != 90 &&
3784 priv->angle != 180 && priv->angle != 270 && priv->angle != 360)
3785 {
3786 /* For some reason we only need this at about 110 degrees, and only
3787 * when gaining in height
3788 */
3789 widest_rect.height += ROTATION_ELLIPSIZE_PADDING2 * 2 * PANGO_SCALE1024;
3790 widest_rect.width += ROTATION_ELLIPSIZE_PADDING2 * 2 * PANGO_SCALE1024;
3791 smallest_rect.height += ROTATION_ELLIPSIZE_PADDING2 * 2 * PANGO_SCALE1024;
3792 smallest_rect.width += ROTATION_ELLIPSIZE_PADDING2 * 2 * PANGO_SCALE1024;
3793 }
3794 }
3795
3796 widest_rect.width = PANGO_PIXELS_CEIL (widest_rect.width)(((int)(widest_rect.width) + 1023) >> 10);
3797 widest_rect.height = PANGO_PIXELS_CEIL (widest_rect.height)(((int)(widest_rect.height) + 1023) >> 10);
3798
3799 smallest_rect.width = PANGO_PIXELS_CEIL (smallest_rect.width)(((int)(smallest_rect.width) + 1023) >> 10);
3800 smallest_rect.height = PANGO_PIXELS_CEIL (smallest_rect.height)(((int)(smallest_rect.height) + 1023) >> 10);
3801
3802 if (orientation == CTK_ORIENTATION_HORIZONTAL)
3803 {
3804 /* Note, we cant use get_size_for_allocation() when rotating
3805 * ellipsized labels.
3806 */
3807 if (!(priv->ellipsize && priv->have_transform) &&
3808 (priv->angle == 90 || priv->angle == 270))
3809 {
3810 /* Doing a h4w request on a rotated label here, return the
3811 * required width for the minimum height.
3812 */
3813 get_size_for_allocation (label,
3814 smallest_rect.height,
3815 minimum_size, natural_size,
3816 NULL((void*)0), NULL((void*)0));
3817
3818 }
3819 else
3820 {
3821 /* Normal desired width */
3822 *minimum_size = smallest_rect.width;
3823 *natural_size = widest_rect.width;
3824 }
3825
3826 *minimum_size += xpad * 2;
3827 *natural_size += xpad * 2;
3828
3829 if (minimum_baseline)
3830 *minimum_baseline = -1;
3831
3832 if (natural_baseline)
3833 *natural_baseline = -1;
3834 }
3835 else /* CTK_ORIENTATION_VERTICAL */
3836 {
3837 /* Note, we cant use get_size_for_allocation() when rotating
3838 * ellipsized labels.
3839 */
3840 if (!(priv->ellipsize && priv->have_transform) &&
3841 (priv->angle == 0 || priv->angle == 180 || priv->angle == 360))
3842 {
3843 /* Doing a w4h request on a label here, return the required
3844 * height for the minimum width.
3845 */
3846 get_size_for_allocation (label,
3847 widest_rect.width,
3848 minimum_size, natural_size,
3849 minimum_baseline, natural_baseline);
3850
3851 if (priv->angle == 180)
3852 {
3853 if (minimum_baseline)
3854 *minimum_baseline = *minimum_size - *minimum_baseline;
3855 if (natural_baseline)
3856 *natural_baseline = *natural_size - *natural_baseline;
3857 }
3858 }
3859 else
3860 {
3861 /* A vertically rotated label does w4h, so return the base
3862 * desired height (text length)
3863 */
3864 *minimum_size = MIN (smallest_rect.height, widest_rect.height)(((smallest_rect.height) < (widest_rect.height)) ? (smallest_rect
.height) : (widest_rect.height))
;
3865 *natural_size = MAX (smallest_rect.height, widest_rect.height)(((smallest_rect.height) > (widest_rect.height)) ? (smallest_rect
.height) : (widest_rect.height))
;
3866 }
3867
3868 *minimum_size += ypad * 2;
3869 *natural_size += ypad * 2;
3870 }
3871}
3872
3873static void
3874ctk_label_measure (CtkCssGadget *gadget,
3875 CtkOrientation orientation,
3876 int for_size,
3877 int *minimum,
3878 int *natural,
3879 int *minimum_baseline,
3880 int *natural_baseline,
3881 gpointer unused G_GNUC_UNUSED__attribute__ ((__unused__)))
3882{
3883 CtkWidget *widget;
3884 CtkLabel *label;
3885 CtkLabelPrivate *priv;
3886 gint xpad, ypad;
3887
3888 widget = ctk_css_gadget_get_owner (gadget);
3889 label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
3890 priv = label->priv;
3891
3892G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
3893 ctk_misc_get_padding (CTK_MISC (label)((((CtkMisc*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_misc_get_type ()))))))
, &xpad, &ypad);
3894G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop
3895
3896 if ((orientation == CTK_ORIENTATION_VERTICAL && for_size != -1 && priv->wrap && (priv->angle == 0 || priv->angle == 180 || priv->angle == 360)) ||
1
Assuming 'orientation' is not equal to CTK_ORIENTATION_VERTICAL
3897 (orientation == CTK_ORIENTATION_HORIZONTAL && priv->wrap && (priv->angle == 90 || priv->angle == 270)))
2
Assuming 'orientation' is equal to CTK_ORIENTATION_HORIZONTAL
3
Assuming field 'wrap' is not equal to 0
4
Assuming field 'angle' is equal to 90
3898 {
3899 gint size;
3900
3901 if (priv->wrap
4.1
Field 'wrap' is not equal to 0
)
5
Taking true branch
3902 ctk_label_clear_layout (label);
3903
3904 if (orientation
5.1
'orientation' is equal to CTK_ORIENTATION_HORIZONTAL
== CTK_ORIENTATION_HORIZONTAL)
3905 size = MAX (1, for_size)(((1) > (for_size)) ? (1) : (for_size)) - 2 * ypad;
6
Taking true branch
7
Assuming 'for_size' is < 1
8
'?' condition is true
3906 else
3907 size = MAX (1, for_size)(((1) > (for_size)) ? (1) : (for_size)) - 2 * xpad;
3908
3909 get_size_for_allocation (label, size, minimum, natural, minimum_baseline, natural_baseline);
9
Passing value via 5th parameter 'minimum_baseline'
10
Calling 'get_size_for_allocation'
3910
3911 if (orientation == CTK_ORIENTATION_HORIZONTAL)
3912 {
3913 *minimum += 2 * xpad;
3914 *natural += 2 * xpad;
3915 }
3916 else
3917 {
3918 *minimum += 2 * ypad;
3919 *natural += 2 * ypad;
3920 }
3921 }
3922 else
3923 ctk_label_get_preferred_size (widget, orientation, minimum, natural, minimum_baseline, natural_baseline);
3924}
3925
3926static void
3927ctk_label_get_preferred_width (CtkWidget *widget,
3928 gint *minimum_size,
3929 gint *natural_size)
3930{
3931 ctk_css_gadget_get_preferred_size (CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
->priv->gadget,
3932 CTK_ORIENTATION_HORIZONTAL,
3933 -1,
3934 minimum_size, natural_size,
3935 NULL((void*)0), NULL((void*)0));
3936}
3937
3938static void
3939ctk_label_get_preferred_height (CtkWidget *widget,
3940 gint *minimum_size,
3941 gint *natural_size)
3942{
3943 ctk_css_gadget_get_preferred_size (CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
->priv->gadget,
3944 CTK_ORIENTATION_VERTICAL,
3945 -1,
3946 minimum_size, natural_size,
3947 NULL((void*)0), NULL((void*)0));
3948}
3949
3950static void
3951ctk_label_get_preferred_width_for_height (CtkWidget *widget,
3952 gint height,
3953 gint *minimum_width,
3954 gint *natural_width)
3955{
3956 ctk_css_gadget_get_preferred_size (CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
->priv->gadget,
3957 CTK_ORIENTATION_HORIZONTAL,
3958 height,
3959 minimum_width, natural_width,
3960 NULL((void*)0), NULL((void*)0));
3961}
3962
3963static void
3964ctk_label_get_preferred_height_for_width (CtkWidget *widget,
3965 gint width,
3966 gint *minimum_height,
3967 gint *natural_height)
3968{
3969 ctk_css_gadget_get_preferred_size (CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
->priv->gadget,
3970 CTK_ORIENTATION_VERTICAL,
3971 width,
3972 minimum_height, natural_height,
3973 NULL((void*)0), NULL((void*)0));
3974}
3975
3976static void
3977ctk_label_get_preferred_height_and_baseline_for_width (CtkWidget *widget,
3978 gint width,
3979 gint *minimum_height,
3980 gint *natural_height,
3981 gint *minimum_baseline,
3982 gint *natural_baseline)
3983{
3984 ctk_css_gadget_get_preferred_size (CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
->priv->gadget,
3985 CTK_ORIENTATION_VERTICAL,
3986 width,
3987 minimum_height, natural_height,
3988 minimum_baseline, natural_baseline);
3989}
3990
3991static void
3992get_layout_location (CtkLabel *label,
3993 gint *xp,
3994 gint *yp)
3995{
3996 CtkAllocation allocation;
3997 CtkWidget *widget;
3998 CtkLabelPrivate *priv;
3999 gint xpad, ypad;
4000 gint req_width, x, y;
4001 gint req_height;
4002 gfloat xalign, yalign;
4003 PangoRectangle logical;
4004 gint baseline, layout_baseline, baseline_offset;
4005
4006 widget = CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
;
4007 priv = label->priv;
4008
4009 xalign = priv->xalign;
4010 yalign = priv->yalign;
4011
4012G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push clang diagnostic ignored "-Wdeprecated-declarations"
4013 ctk_misc_get_padding (CTK_MISC (label)((((CtkMisc*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_misc_get_type ()))))))
, &xpad, &ypad);
4014G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop
4015
4016 if (ctk_widget_get_direction (widget) != CTK_TEXT_DIR_LTR)
4017 xalign = 1.0 - xalign;
4018
4019 pango_layout_get_extents (priv->layout, NULL((void*)0), &logical);
4020
4021 if (priv->have_transform)
4022 {
4023 PangoContext *context = ctk_widget_get_pango_context (widget);
4024 const PangoMatrix *matrix = pango_context_get_matrix (context);
4025 pango_matrix_transform_rectangle (matrix, &logical);
4026 }
4027
4028 pango_extents_to_pixels (&logical, NULL((void*)0));
4029
4030 req_width = logical.width;
4031 req_height = logical.height;
4032
4033 req_width += 2 * xpad;
4034 req_height += 2 * ypad;
4035
4036 ctk_css_gadget_get_content_allocation (priv->gadget,
4037 &allocation,
4038 &baseline);
4039
4040 x = floor (allocation.x + xpad + xalign * (allocation.width - req_width) - logical.x);
4041
4042 baseline_offset = 0;
4043 if (baseline != -1 && !priv->have_transform)
4044 {
4045 layout_baseline = pango_layout_get_baseline (priv->layout) / PANGO_SCALE1024;
4046 baseline_offset = baseline - layout_baseline;
4047 yalign = 0.0; /* Can't support yalign while baseline aligning */
4048 }
4049
4050 /* bgo#315462 - For single-line labels, *do* align the requisition with
4051 * respect to the allocation, even if we are under-allocated. For multi-line
4052 * labels, always show the top of the text when they are under-allocated. The
4053 * rationale is this:
4054 *
4055 * - Single-line labels appear in CtkButtons, and it is very easy to get them
4056 * to be smaller than their requisition. The button may clip the label, but
4057 * the label will still be able to show most of itself and the focus
4058 * rectangle. Also, it is fairly easy to read a single line of clipped text.
4059 *
4060 * - Multi-line labels should not be clipped to showing "something in the
4061 * middle". You want to read the first line, at least, to get some context.
4062 */
4063 if (pango_layout_get_line_count (priv->layout) == 1)
4064 y = floor (allocation.y + ypad + (allocation.height - req_height) * yalign) - logical.y + baseline_offset;
4065 else
4066 y = floor (allocation.y + ypad + MAX ((allocation.height - req_height) * yalign, 0)((((allocation.height - req_height) * yalign) > (0)) ? ((allocation
.height - req_height) * yalign) : (0))
) - logical.y + baseline_offset;
4067
4068 if (xp)
4069 *xp = x;
4070
4071 if (yp)
4072 *yp = y;
4073}
4074
4075static void
4076ctk_label_get_ink_rect (CtkLabel *label,
4077 CdkRectangle *rect)
4078{
4079 CtkLabelPrivate *priv = label->priv;
4080 CtkStyleContext *context;
4081 PangoRectangle ink_rect;
4082 CtkBorder extents;
4083 int x, y;
4084
4085 ctk_label_ensure_layout (label);
4086 get_layout_location (label, &x, &y);
4087 pango_layout_get_pixel_extents (priv->layout, &ink_rect, NULL((void*)0));
4088 context = ctk_widget_get_style_context (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
4089 _ctk_css_shadows_value_get_extents (_ctk_style_context_peek_property (context, CTK_CSS_PROPERTY_TEXT_SHADOW), &extents);
4090
4091 rect->x = x + ink_rect.x - extents.left;
4092 rect->width = ink_rect.width + extents.left + extents.right;
4093 rect->y = y + ink_rect.y - extents.top;
4094 rect->height = ink_rect.height + extents.top + extents.bottom;
4095}
4096
4097static void
4098ctk_label_size_allocate (CtkWidget *widget,
4099 CtkAllocation *allocation)
4100{
4101 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
4102 CtkLabelPrivate *priv = label->priv;
4103 CdkRectangle clip_rect, clip;
4104
4105 CTK_WIDGET_CLASS (ctk_label_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_label_parent_class)), ((ctk_widget_get_type ()))))))
->size_allocate (widget, allocation);
4106
4107 ctk_css_gadget_allocate (priv->gadget,
4108 allocation,
4109 ctk_widget_get_allocated_baseline (widget),
4110 &clip);
4111
4112 if (priv->layout)
4113 ctk_label_update_layout_width (label);
4114
4115 if (priv->select_info && priv->select_info->window)
4116 cdk_window_move_resize (priv->select_info->window,
4117 allocation->x,
4118 allocation->y,
4119 allocation->width,
4120 allocation->height);
4121
4122 ctk_label_get_ink_rect (label, &clip_rect);
4123 cdk_rectangle_union (&clip_rect, &clip, &clip_rect);
4124 _ctk_widget_set_simple_clip (widget, &clip_rect);
4125}
4126
4127static void
4128ctk_label_update_cursor (CtkLabel *label)
4129{
4130 CtkLabelPrivate *priv = label->priv;
4131 CtkWidget *widget;
4132
4133 if (!priv->select_info)
4134 return;
4135
4136 widget = CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
;
4137
4138 if (ctk_widget_get_realized (widget))
4139 {
4140 CdkDisplay *display;
4141 CdkCursor *cursor;
4142
4143 if (ctk_widget_is_sensitive (widget))
4144 {
4145 display = ctk_widget_get_display (widget);
4146
4147 if (priv->select_info->active_link)
4148 cursor = cdk_cursor_new_from_name (display, "pointer");
4149 else if (priv->select_info->selectable)
4150 cursor = cdk_cursor_new_from_name (display, "text");
4151 else
4152 cursor = NULL((void*)0);
4153 }
4154 else
4155 cursor = NULL((void*)0);
4156
4157 cdk_window_set_cursor (priv->select_info->window, cursor);
4158
4159 if (cursor)
4160 g_object_unref (cursor);
4161 }
4162}
4163
4164static void
4165update_link_state (CtkLabel *label)
4166{
4167 CtkLabelPrivate *priv = label->priv;
4168 GList *l;
4169 CtkStateFlags state;
4170
4171 if (!priv->select_info)
4172 return;
4173
4174 for (l = priv->select_info->links; l; l = l->next)
4175 {
4176 CtkLabelLink *link = l->data;
4177
4178 state = ctk_widget_get_state_flags (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
4179 if (link->visited)
4180 state |= CTK_STATE_FLAG_VISITED;
4181 else
4182 state |= CTK_STATE_FLAG_LINK;
4183 if (link == priv->select_info->active_link)
4184 {
4185 if (priv->select_info->link_clicked)
4186 state |= CTK_STATE_FLAG_ACTIVE;
4187 else
4188 state |= CTK_STATE_FLAG_PRELIGHT;
4189 }
4190 ctk_css_node_set_state (link->cssnode, state);
4191 }
4192}
4193
4194static void
4195ctk_label_state_flags_changed (CtkWidget *widget,
4196 CtkStateFlags prev_state)
4197{
4198 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
4199 CtkLabelPrivate *priv = label->priv;
4200
4201 if (priv->select_info)
4202 {
4203 if (!ctk_widget_is_sensitive (widget))
4204 ctk_label_select_region (label, 0, 0);
4205
4206 ctk_label_update_cursor (label);
4207 update_link_state (label);
4208 }
4209
4210 if (CTK_WIDGET_CLASS (ctk_label_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_label_parent_class)), ((ctk_widget_get_type ()))))))
->state_flags_changed)
4211 CTK_WIDGET_CLASS (ctk_label_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_label_parent_class)), ((ctk_widget_get_type ()))))))
->state_flags_changed (widget, prev_state);
4212}
4213
4214static void
4215ctk_label_style_updated (CtkWidget *widget)
4216{
4217 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
4218 CtkLabelPrivate *priv = label->priv;
4219 CtkStyleContext *context;
4220 CtkCssStyleChange *change;
4221
4222 CTK_WIDGET_CLASS (ctk_label_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_label_parent_class)), ((ctk_widget_get_type ()))))))
->style_updated (widget);
4223
4224 context = ctk_widget_get_style_context (widget);
4225 change = ctk_style_context_get_change (context);
4226
4227 if (change == NULL((void*)0) || ctk_css_style_change_affects (change, CTK_CSS_AFFECTS_TEXT_ATTRS) ||
4228 (priv->select_info && priv->select_info->links))
4229 ctk_label_update_layout_attributes (label);
4230}
4231
4232static PangoDirection
4233get_cursor_direction (CtkLabel *label)
4234{
4235 CtkLabelPrivate *priv = label->priv;
4236 GSList *l;
4237
4238 g_assert (priv->select_info)do { if (priv->select_info) ; else g_assertion_message_expr
("Ctk", "ctklabel.c", 4238, ((const char*) (__func__)), "priv->select_info"
); } while (0)
;
4239
4240 ctk_label_ensure_layout (label);
4241
4242 for (l = pango_layout_get_lines_readonly (priv->layout); l; l = l->next)
4243 {
4244 PangoLayoutLine *line = l->data;
4245
4246 /* If priv->select_info->selection_end is at the very end of
4247 * the line, we don't know if the cursor is on this line or
4248 * the next without looking ahead at the next line. (End
4249 * of paragraph is different from line break.) But it's
4250 * definitely in this paragraph, which is good enough
4251 * to figure out the resolved direction.
4252 */
4253 if (line->start_index + line->length >= priv->select_info->selection_end)
4254 return line->resolved_dir;
4255 }
4256
4257 return PANGO_DIRECTION_LTR;
4258}
4259
4260static CtkLabelLink *
4261ctk_label_get_focus_link (CtkLabel *label)
4262{
4263 CtkLabelPrivate *priv = label->priv;
4264 CtkLabelSelectionInfo *info = priv->select_info;
4265 GList *l;
4266
4267 if (!info)
4268 return NULL((void*)0);
4269
4270 if (info->selection_anchor != info->selection_end)
4271 return NULL((void*)0);
4272
4273 for (l = info->links; l; l = l->next)
4274 {
4275 CtkLabelLink *link = l->data;
4276 if (link->start <= info->selection_anchor &&
4277 info->selection_anchor <= link->end)
4278 return link;
4279 }
4280
4281 return NULL((void*)0);
4282}
4283
4284static gboolean
4285ctk_label_draw (CtkWidget *widget,
4286 cairo_t *cr)
4287{
4288 ctk_css_gadget_draw (CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
->priv->gadget, cr);
4289
4290 return FALSE(0);
4291}
4292
4293static void layout_to_window_coords (CtkLabel *label,
4294 gint *x,
4295 gint *y);
4296
4297static gboolean
4298ctk_label_render (CtkCssGadget *gadget,
4299 cairo_t *cr,
4300 int x,
4301 int y,
4302 int width,
4303 int height,
4304 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
4305{
4306 CtkWidget *widget;
4307 CtkLabel *label;
4308 CtkLabelPrivate *priv;
4309 CtkLabelSelectionInfo *info;
4310 CtkStyleContext *context;
4311 gint lx, ly;
4312
4313 widget = ctk_css_gadget_get_owner (gadget);
4314 label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
4315 priv = label->priv;
4316 info = priv->select_info;
4317
4318 ctk_label_ensure_layout (label);
4319
4320 context = ctk_widget_get_style_context (widget);
4321
4322 if (CTK_IS_ACCEL_LABEL (widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(widget)); GType __t = ((ctk_accel_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
4323 {
4324 guint ac_width = ctk_accel_label_get_accel_width (CTK_ACCEL_LABEL (widget)((((CtkAccelLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_accel_label_get_type ()))))))
);
4325 width -= ac_width;
4326 if (ctk_widget_get_direction (widget) == CTK_TEXT_DIR_RTL)
4327 x += ac_width;
4328 }
4329
4330 if (priv->text && (*priv->text != '\0'))
4331 {
4332 lx = ly = 0;
4333 layout_to_window_coords (label, &lx, &ly);
4334
4335 ctk_render_layout (context, cr, lx, ly, priv->layout);
4336
4337 if (info && (info->selection_anchor != info->selection_end))
4338 {
4339 gint range[2];
4340 cairo_region_t *clip;
4341
4342 range[0] = info->selection_anchor;
4343 range[1] = info->selection_end;
4344
4345 if (range[0] > range[1])
4346 {
4347 gint tmp = range[0];
4348 range[0] = range[1];
4349 range[1] = tmp;
4350 }
4351
4352 clip = cdk_pango_layout_get_clip_region (priv->layout, lx, ly, range, 1);
4353
4354 cairo_save (cr);
4355 ctk_style_context_save_to_node (context, info->selection_node);
4356
4357 cdk_cairo_region (cr, clip);
4358 cairo_clip (cr);
4359
4360 ctk_render_background (context, cr, x, y, width, height);
4361 ctk_render_layout (context, cr, lx, ly, priv->layout);
4362
4363 ctk_style_context_restore (context);
4364 cairo_restore (cr);
4365 cairo_region_destroy (clip);
4366 }
4367 else if (info)
4368 {
4369 CtkLabelLink *focus_link;
4370 CtkLabelLink *active_link;
4371 gint range[2];
4372 cairo_region_t *clip;
4373 CdkRectangle rect;
4374
4375 if (info->selectable &&
4376 ctk_widget_has_focus (widget) &&
4377 ctk_widget_is_drawable (widget))
4378 {
4379 PangoDirection cursor_direction;
4380
4381 cursor_direction = get_cursor_direction (label);
4382 ctk_render_insertion_cursor (context, cr,
4383 lx, ly,
4384 priv->layout, priv->select_info->selection_end,
4385 cursor_direction);
4386 }
4387
4388 focus_link = ctk_label_get_focus_link (label);
4389 active_link = info->active_link;
4390
4391 if (active_link)
4392 {
4393 range[0] = active_link->start;
4394 range[1] = active_link->end;
4395
4396 cairo_save (cr);
4397 ctk_style_context_save_to_node (context, active_link->cssnode);
4398
4399 clip = cdk_pango_layout_get_clip_region (priv->layout, lx, ly, range, 1);
4400
4401 cdk_cairo_region (cr, clip);
4402 cairo_clip (cr);
4403 cairo_region_destroy (clip);
4404
4405 ctk_render_background (context, cr, x, y, width, height);
4406 ctk_render_layout (context, cr, lx, ly, priv->layout);
4407
4408 ctk_style_context_restore (context);
4409 cairo_restore (cr);
4410 }
4411
4412 if (focus_link && ctk_widget_has_visible_focus (widget))
4413 {
4414 range[0] = focus_link->start;
4415 range[1] = focus_link->end;
4416
4417 clip = cdk_pango_layout_get_clip_region (priv->layout, lx, ly, range, 1);
4418 cairo_region_get_extents (clip, &rect);
4419
4420 ctk_render_focus (context, cr, rect.x, rect.y, rect.width, rect.height);
4421
4422 cairo_region_destroy (clip);
4423 }
4424 }
4425 }
4426
4427 return FALSE(0);
4428}
4429
4430static gboolean
4431separate_uline_pattern (const gchar *str,
4432 guint *accel_key,
4433 gchar **new_str,
4434 gchar **pattern)
4435{
4436 gboolean underscore;
4437 const gchar *src;
4438 gchar *dest;
4439 gchar *pattern_dest;
4440
4441 *accel_key = CDK_KEY_VoidSymbol0xffffff;
4442 *new_str = g_new (gchar, strlen (str) + 1)((gchar *) g_malloc_n ((strlen (str) + 1), sizeof (gchar)));
4443 *pattern = g_new (gchar, g_utf8_strlen (str, -1) + 1)((gchar *) g_malloc_n ((g_utf8_strlen (str, -1) + 1), sizeof (
gchar)))
;
4444
4445 underscore = FALSE(0);
4446
4447 src = str;
4448 dest = *new_str;
4449 pattern_dest = *pattern;
4450
4451 while (*src)
4452 {
4453 gunichar c;
4454 const gchar *next_src;
4455
4456 c = g_utf8_get_char (src);
4457 if (c == (gunichar)-1)
4458 {
4459 g_warning ("Invalid input string");
4460 g_free (*new_str);
4461 g_free (*pattern);
4462
4463 return FALSE(0);
4464 }
4465 next_src = g_utf8_next_char (src)((src) + g_utf8_skip[*(const guchar *)(src)]);
4466
4467 if (underscore)
4468 {
4469 if (c == '_')
4470 *pattern_dest++ = ' ';
4471 else
4472 {
4473 *pattern_dest++ = '_';
4474 if (*accel_key == CDK_KEY_VoidSymbol0xffffff)
4475 *accel_key = cdk_keyval_to_lower (cdk_unicode_to_keyval (c));
4476 }
4477
4478 while (src < next_src)
4479 *dest++ = *src++;
4480
4481 underscore = FALSE(0);
4482 }
4483 else
4484 {
4485 if (c == '_')
4486 {
4487 underscore = TRUE(!(0));
4488 src = next_src;
4489 }
4490 else
4491 {
4492 while (src < next_src)
4493 *dest++ = *src++;
4494
4495 *pattern_dest++ = ' ';
4496 }
4497 }
4498 }
4499
4500 *dest = 0;
4501 *pattern_dest = 0;
4502
4503 return TRUE(!(0));
4504}
4505
4506static void
4507ctk_label_set_uline_text_internal (CtkLabel *label,
4508 const gchar *str)
4509{
4510 CtkLabelPrivate *priv = label->priv;
4511 guint accel_key = CDK_KEY_VoidSymbol0xffffff;
4512 gchar *new_str;
4513 gchar *pattern;
4514
4515 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
4516 g_return_if_fail (str != NULL)do { if ((str != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "str != NULL"); return; }
} while (0)
;
4517
4518 /* Split text into the base text and a separate pattern
4519 * of underscores.
4520 */
4521 if (!separate_uline_pattern (str, &accel_key, &new_str, &pattern))
4522 return;
4523
4524 ctk_label_set_text_internal (label, new_str);
4525 ctk_label_set_pattern_internal (label, pattern, TRUE(!(0)));
4526 priv->mnemonic_keyval = accel_key;
4527
4528 g_free (pattern);
4529}
4530
4531/**
4532 * ctk_label_set_text_with_mnemonic:
4533 * @label: a #CtkLabel
4534 * @str: a string
4535 *
4536 * Sets the label’s text from the string @str.
4537 * If characters in @str are preceded by an underscore, they are underlined
4538 * indicating that they represent a keyboard accelerator called a mnemonic.
4539 * The mnemonic key can be used to activate another widget, chosen
4540 * automatically, or explicitly using ctk_label_set_mnemonic_widget().
4541 **/
4542void
4543ctk_label_set_text_with_mnemonic (CtkLabel *label,
4544 const gchar *str)
4545{
4546 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
4547 g_return_if_fail (str != NULL)do { if ((str != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "str != NULL"); return; }
} while (0)
;
4548
4549 g_object_freeze_notify (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
4550
4551 ctk_label_set_label_internal (label, g_strdup (str)g_strdup_inline (str));
4552 ctk_label_set_use_markup_internal (label, FALSE(0));
4553 ctk_label_set_use_underline_internal (label, TRUE(!(0)));
4554
4555 ctk_label_recalculate (label);
4556
4557 g_object_thaw_notify (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
4558}
4559
4560static void
4561ctk_label_realize (CtkWidget *widget)
4562{
4563 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
4564 CtkLabelPrivate *priv = label->priv;
4565
4566 CTK_WIDGET_CLASS (ctk_label_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_label_parent_class)), ((ctk_widget_get_type ()))))))
->realize (widget);
4567
4568 if (priv->select_info)
4569 ctk_label_create_window (label);
4570}
4571
4572static void
4573ctk_label_unrealize (CtkWidget *widget)
4574{
4575 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
4576 CtkLabelPrivate *priv = label->priv;
4577
4578 if (priv->select_info)
4579 ctk_label_destroy_window (label);
4580
4581 CTK_WIDGET_CLASS (ctk_label_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_label_parent_class)), ((ctk_widget_get_type ()))))))
->unrealize (widget);
4582}
4583
4584static void
4585ctk_label_map (CtkWidget *widget)
4586{
4587 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
4588 CtkLabelPrivate *priv = label->priv;
4589
4590 CTK_WIDGET_CLASS (ctk_label_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_label_parent_class)), ((ctk_widget_get_type ()))))))
->map (widget);
4591
4592 if (priv->select_info)
4593 cdk_window_show (priv->select_info->window);
4594}
4595
4596static void
4597ctk_label_unmap (CtkWidget *widget)
4598{
4599 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
4600 CtkLabelPrivate *priv = label->priv;
4601
4602 if (priv->select_info)
4603 {
4604 cdk_window_hide (priv->select_info->window);
4605
4606 if (priv->select_info->popup_menu)
4607 {
4608 ctk_widget_destroy (priv->select_info->popup_menu);
4609 priv->select_info->popup_menu = NULL((void*)0);
4610 }
4611 }
4612
4613 CTK_WIDGET_CLASS (ctk_label_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_label_parent_class)), ((ctk_widget_get_type ()))))))
->unmap (widget);
4614}
4615
4616static void
4617window_to_layout_coords (CtkLabel *label,
4618 gint *x,
4619 gint *y)
4620{
4621 CtkAllocation allocation;
4622 gint lx, ly;
4623
4624 /* get layout location in widget->window coords */
4625 get_layout_location (label, &lx, &ly);
4626 ctk_widget_get_allocation (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
, &allocation);
4627
4628 *x += allocation.x; /* go to widget->window */
4629 *x -= lx; /* go to layout */
4630
4631 *y += allocation.y; /* go to widget->window */
4632 *y -= ly; /* go to layout */
4633}
4634
4635static void
4636layout_to_window_coords (CtkLabel *label,
4637 gint *x,
4638 gint *y)
4639{
4640 gint lx, ly;
4641 CtkAllocation allocation;
4642
4643 /* get layout location in widget->window coords */
4644 get_layout_location (label, &lx, &ly);
4645 ctk_widget_get_allocation (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
, &allocation);
4646
4647 *x += lx; /* go to widget->window */
4648 *x -= allocation.x; /* go to selection window */
4649
4650 *y += ly; /* go to widget->window */
4651 *y -= allocation.y; /* go to selection window */
4652}
4653
4654static gboolean
4655get_layout_index (CtkLabel *label,
4656 gint x,
4657 gint y,
4658 gint *index)
4659{
4660 CtkLabelPrivate *priv = label->priv;
4661 gint trailing = 0;
4662 const gchar *cluster;
4663 const gchar *cluster_end;
4664 gboolean inside;
4665
4666 *index = 0;
4667
4668 ctk_label_ensure_layout (label);
4669
4670 window_to_layout_coords (label, &x, &y);
4671
4672 x *= PANGO_SCALE1024;
4673 y *= PANGO_SCALE1024;
4674
4675 inside = pango_layout_xy_to_index (priv->layout,
4676 x, y,
4677 index, &trailing);
4678
4679 cluster = priv->text + *index;
4680 cluster_end = cluster;
4681 while (trailing)
4682 {
4683 cluster_end = g_utf8_next_char (cluster_end)((cluster_end) + g_utf8_skip[*(const guchar *)(cluster_end)]);
4684 --trailing;
4685 }
4686
4687 *index += (cluster_end - cluster);
4688
4689 return inside;
4690}
4691
4692static gboolean
4693range_is_in_ellipsis_full (CtkLabel *label,
4694 gint range_start,
4695 gint range_end,
4696 gint *ellipsis_start,
4697 gint *ellipsis_end)
4698{
4699 CtkLabelPrivate *priv = label->priv;
4700 PangoLayoutIter *iter;
4701 gboolean in_ellipsis;
4702
4703 if (!priv->ellipsize)
4704 return FALSE(0);
4705
4706 ctk_label_ensure_layout (label);
4707
4708 if (!pango_layout_is_ellipsized (priv->layout))
4709 return FALSE(0);
4710
4711 iter = pango_layout_get_iter (priv->layout);
4712
4713 in_ellipsis = FALSE(0);
4714
4715 do {
4716 PangoLayoutRun *run;
4717
4718 run = pango_layout_iter_get_run_readonly (iter);
4719 if (run)
4720 {
4721 PangoItem *item;
4722
4723 item = ((PangoGlyphItem*)run)->item;
4724
4725 if (item->offset <= range_start && range_end <= item->offset + item->length)
4726 {
4727 if (item->analysis.flags & PANGO_ANALYSIS_FLAG_IS_ELLIPSIS(1 << 1))
4728 {
4729 if (ellipsis_start)
4730 *ellipsis_start = item->offset;
4731 if (ellipsis_end)
4732 *ellipsis_end = item->offset + item->length;
4733 in_ellipsis = TRUE(!(0));
4734 }
4735 break;
4736 }
4737 else if (item->offset + item->length >= range_end)
4738 break;
4739 }
4740 } while (pango_layout_iter_next_run (iter));
4741
4742 pango_layout_iter_free (iter);
4743
4744 return in_ellipsis;
4745}
4746
4747static gboolean
4748range_is_in_ellipsis (CtkLabel *label,
4749 gint range_start,
4750 gint range_end)
4751{
4752 return range_is_in_ellipsis_full (label, range_start, range_end, NULL((void*)0), NULL((void*)0));
4753}
4754
4755static void
4756ctk_label_select_word (CtkLabel *label)
4757{
4758 CtkLabelPrivate *priv = label->priv;
4759 gint min, max;
4760
4761 gint start_index = ctk_label_move_backward_word (label, priv->select_info->selection_end);
4762 gint end_index = ctk_label_move_forward_word (label, priv->select_info->selection_end);
4763
4764 min = MIN (priv->select_info->selection_anchor,(((priv->select_info->selection_anchor) < (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
4765 priv->select_info->selection_end)(((priv->select_info->selection_anchor) < (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
;
4766 max = MAX (priv->select_info->selection_anchor,(((priv->select_info->selection_anchor) > (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
4767 priv->select_info->selection_end)(((priv->select_info->selection_anchor) > (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
;
4768
4769 min = MIN (min, start_index)(((min) < (start_index)) ? (min) : (start_index));
4770 max = MAX (max, end_index)(((max) > (end_index)) ? (max) : (end_index));
4771
4772 ctk_label_select_region_index (label, min, max);
4773}
4774
4775static void
4776ctk_label_grab_focus (CtkWidget *widget)
4777{
4778 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
4779 CtkLabelPrivate *priv = label->priv;
4780 gboolean select_on_focus;
4781 CtkLabelLink *link;
4782 GList *l;
4783
4784 if (priv->select_info == NULL((void*)0))
4785 return;
4786
4787 CTK_WIDGET_CLASS (ctk_label_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_label_parent_class)), ((ctk_widget_get_type ()))))))
->grab_focus (widget);
4788
4789 if (priv->select_info->selectable)
4790 {
4791 g_object_get (ctk_widget_get_settings (widget),
4792 "ctk-label-select-on-focus",
4793 &select_on_focus,
4794 NULL((void*)0));
4795
4796 if (select_on_focus && !priv->in_click)
4797 ctk_label_select_region (label, 0, -1);
4798 }
4799 else
4800 {
4801 if (priv->select_info->links && !priv->in_click)
4802 {
4803 for (l = priv->select_info->links; l; l = l->next)
4804 {
4805 link = l->data;
4806 if (!range_is_in_ellipsis (label, link->start, link->end))
4807 {
4808 priv->select_info->selection_anchor = link->start;
4809 priv->select_info->selection_end = link->start;
4810 _ctk_label_accessible_focus_link_changed (label);
4811 break;
4812 }
4813 }
4814 }
4815 }
4816}
4817
4818static gboolean
4819ctk_label_focus (CtkWidget *widget,
4820 CtkDirectionType direction)
4821{
4822 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
4823 CtkLabelPrivate *priv = label->priv;
4824 CtkLabelSelectionInfo *info = priv->select_info;
4825 CtkLabelLink *focus_link;
4826 GList *l;
4827
4828 if (!ctk_widget_is_focus (widget))
4829 {
4830 ctk_widget_grab_focus (widget);
4831 if (info)
4832 {
4833 focus_link = ctk_label_get_focus_link (label);
4834 if (focus_link && direction == CTK_DIR_TAB_BACKWARD)
4835 {
4836 for (l = g_list_last (info->links); l; l = l->prev)
4837 {
4838 focus_link = l->data;
4839 if (!range_is_in_ellipsis (label, focus_link->start, focus_link->end))
4840 {
4841 info->selection_anchor = focus_link->start;
4842 info->selection_end = focus_link->start;
4843 _ctk_label_accessible_focus_link_changed (label);
4844 }
4845 }
4846 }
4847 }
4848
4849 return TRUE(!(0));
4850 }
4851
4852 if (!info)
4853 return FALSE(0);
4854
4855 if (info->selectable)
4856 {
4857 gint index;
4858
4859 if (info->selection_anchor != info->selection_end)
4860 goto out;
4861
4862 index = info->selection_anchor;
4863
4864 if (direction == CTK_DIR_TAB_FORWARD)
4865 for (l = info->links; l; l = l->next)
4866 {
4867 CtkLabelLink *link = l->data;
4868
4869 if (link->start > index)
4870 {
4871 if (!range_is_in_ellipsis (label, link->start, link->end))
4872 {
4873 ctk_label_select_region_index (label, link->start, link->start);
4874 _ctk_label_accessible_focus_link_changed (label);
4875 return TRUE(!(0));
4876 }
4877 }
4878 }
4879 else if (direction == CTK_DIR_TAB_BACKWARD)
4880 for (l = g_list_last (info->links); l; l = l->prev)
4881 {
4882 CtkLabelLink *link = l->data;
4883
4884 if (link->end < index)
4885 {
4886 if (!range_is_in_ellipsis (label, link->start, link->end))
4887 {
4888 ctk_label_select_region_index (label, link->start, link->start);
4889 _ctk_label_accessible_focus_link_changed (label);
4890 return TRUE(!(0));
4891 }
4892 }
4893 }
4894
4895 goto out;
4896 }
4897 else
4898 {
4899 focus_link = ctk_label_get_focus_link (label);
4900 switch (direction)
4901 {
4902 case CTK_DIR_TAB_FORWARD:
4903 if (focus_link)
4904 {
4905 l = g_list_find (info->links, focus_link);
4906 l = l->next;
4907 }
4908 else
4909 l = info->links;
4910 for (; l; l = l->next)
4911 {
4912 CtkLabelLink *link = l->data;
4913 if (!range_is_in_ellipsis (label, link->start, link->end))
4914 break;
4915 }
4916 break;
4917
4918 case CTK_DIR_TAB_BACKWARD:
4919 if (focus_link)
4920 {
4921 l = g_list_find (info->links, focus_link);
4922 l = l->prev;
4923 }
4924 else
4925 l = g_list_last (info->links);
4926 for (; l; l = l->prev)
4927 {
4928 CtkLabelLink *link = l->data;
4929 if (!range_is_in_ellipsis (label, link->start, link->end))
4930 break;
4931 }
4932 break;
4933
4934 default:
4935 goto out;
4936 }
4937
4938 if (l)
4939 {
4940 focus_link = l->data;
4941 info->selection_anchor = focus_link->start;
4942 info->selection_end = focus_link->start;
4943 _ctk_label_accessible_focus_link_changed (label);
4944 ctk_widget_queue_draw (widget);
4945
4946 return TRUE(!(0));
4947 }
4948 }
4949
4950out:
4951
4952 return FALSE(0);
4953}
4954
4955static void
4956ctk_label_multipress_gesture_pressed (CtkGestureMultiPress *gesture,
4957 gint n_press,
4958 gdouble widget_x,
4959 gdouble widget_y,
4960 CtkLabel *label)
4961{
4962 CtkLabelPrivate *priv = label->priv;
4963 CtkLabelSelectionInfo *info = priv->select_info;
4964 CtkWidget *widget = CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
;
4965 CdkEventSequence *sequence;
4966 const CdkEvent *event;
4967 guint button;
4968
4969 if (info == NULL((void*)0))
4970 {
4971 ctk_gesture_set_state (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, CTK_EVENT_SEQUENCE_DENIED);
4972 return;
4973 }
4974
4975 button = ctk_gesture_single_get_current_button (CTK_GESTURE_SINGLE (gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((gesture)), ((ctk_gesture_single_get_type ()
))))))
);
4976 sequence = ctk_gesture_single_get_current_sequence (CTK_GESTURE_SINGLE (gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((gesture)), ((ctk_gesture_single_get_type ()
))))))
);
4977 event = ctk_gesture_get_last_event (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, sequence);
4978 ctk_label_update_active_link (widget, widget_x, widget_y);
4979
4980 ctk_gesture_set_state (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, CTK_EVENT_SEQUENCE_CLAIMED);
4981
4982 if (info->active_link)
4983 {
4984 if (cdk_event_triggers_context_menu (event))
4985 {
4986 info->link_clicked = 1;
4987 update_link_state (label);
4988 ctk_label_do_popup (label, event);
4989 return;
4990 }
4991 else if (button == CDK_BUTTON_PRIMARY(1))
4992 {
4993 info->link_clicked = 1;
4994 update_link_state (label);
4995 ctk_widget_queue_draw (widget);
4996 if (!info->selectable)
4997 return;
4998 }
4999 }
5000
5001 if (!info->selectable)
5002 {
5003 ctk_gesture_set_state (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, CTK_EVENT_SEQUENCE_DENIED);
5004 return;
5005 }
5006
5007 info->in_drag = FALSE(0);
5008 info->select_words = FALSE(0);
5009
5010 if (cdk_event_triggers_context_menu (event))
5011 ctk_label_do_popup (label, event);
5012 else if (button == CDK_BUTTON_PRIMARY(1))
5013 {
5014 if (!ctk_widget_has_focus (widget))
5015 {
5016 priv->in_click = TRUE(!(0));
5017 ctk_widget_grab_focus (widget);
5018 priv->in_click = FALSE(0);
5019 }
5020
5021 if (n_press == 3)
5022 ctk_label_select_region_index (label, 0, strlen (priv->text));
5023 else if (n_press == 2)
5024 {
5025 info->select_words = TRUE(!(0));
5026 ctk_label_select_word (label);
5027 }
5028 }
5029 else
5030 {
5031 ctk_gesture_set_state (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, CTK_EVENT_SEQUENCE_DENIED);
5032 return;
5033 }
5034
5035 if (n_press >= 3)
5036 ctk_event_controller_reset (CTK_EVENT_CONTROLLER (gesture)((((CtkEventController*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((gesture)), ((ctk_event_controller_get_type
()))))))
);
5037}
5038
5039static void
5040ctk_label_multipress_gesture_released (CtkGestureMultiPress *gesture,
5041 gint n_press,
5042 gdouble x,
5043 gdouble y,
5044 CtkLabel *label)
5045{
5046 CtkLabelPrivate *priv = label->priv;
5047 CtkLabelSelectionInfo *info = priv->select_info;
5048 CdkEventSequence *sequence;
5049 gint index;
5050
5051 if (info == NULL((void*)0))
5052 return;
5053
5054 sequence = ctk_gesture_single_get_current_sequence (CTK_GESTURE_SINGLE (gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((gesture)), ((ctk_gesture_single_get_type ()
))))))
);
5055
5056 if (!ctk_gesture_handles_sequence (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, sequence))
5057 return;
5058
5059 if (n_press != 1)
5060 return;
5061
5062 if (info->in_drag)
5063 {
5064 info->in_drag = 0;
5065 get_layout_index (label, x, y, &index);
5066 ctk_label_select_region_index (label, index, index);
5067 }
5068 else if (info->active_link &&
5069 info->selection_anchor == info->selection_end &&
5070 info->link_clicked)
5071 {
5072 emit_activate_link (label, info->active_link);
5073 info->link_clicked = 0;
5074 }
5075}
5076
5077static void
5078connect_mnemonics_visible_notify (CtkLabel *label)
5079{
5080 CtkLabelPrivate *priv = label->priv;
5081 CtkWidget *toplevel;
5082 gboolean connected;
5083
5084 toplevel = ctk_widget_get_toplevel (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
5085
5086 if (!CTK_IS_WINDOW (toplevel)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(toplevel)); GType __t = ((ctk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
5087 return;
5088
5089 /* always set up this widgets initial value */
5090 priv->mnemonics_visible =
5091 ctk_window_get_mnemonics_visible (CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
);
5092
5093 connected =
5094 GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (toplevel), quark_mnemonics_visible_connected))((gint) (glong) (g_object_get_qdata (((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((toplevel)), (((GType) ((20) << (2)
))))))), quark_mnemonics_visible_connected)))
;
5095
5096 if (!connected)
5097 {
5098 g_signal_connect (toplevel,g_signal_connect_data ((toplevel), ("notify::mnemonics-visible"
), (((GCallback) (label_mnemonics_visible_changed))), (label)
, ((void*)0), (GConnectFlags) 0)
5099 "notify::mnemonics-visible",g_signal_connect_data ((toplevel), ("notify::mnemonics-visible"
), (((GCallback) (label_mnemonics_visible_changed))), (label)
, ((void*)0), (GConnectFlags) 0)
5100 G_CALLBACK (label_mnemonics_visible_changed),g_signal_connect_data ((toplevel), ("notify::mnemonics-visible"
), (((GCallback) (label_mnemonics_visible_changed))), (label)
, ((void*)0), (GConnectFlags) 0)
5101 label)g_signal_connect_data ((toplevel), ("notify::mnemonics-visible"
), (((GCallback) (label_mnemonics_visible_changed))), (label)
, ((void*)0), (GConnectFlags) 0)
;
5102 g_object_set_qdata (G_OBJECT (toplevel)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), (((GType) ((20) << (2))))))))
,
5103 quark_mnemonics_visible_connected,
5104 GINT_TO_POINTER (1)((gpointer) (glong) (1)));
5105 }
5106}
5107
5108static void
5109drag_begin_cb (CtkWidget *widget,
5110 CdkDragContext *context,
5111 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
5112{
5113 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
5114 CtkLabelPrivate *priv = label->priv;
5115 cairo_surface_t *surface = NULL((void*)0);
5116
5117 g_signal_handlers_disconnect_by_func (widget, drag_begin_cb, NULL)g_signal_handlers_disconnect_matched ((widget), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (drag_begin_cb), (((void*)0)))
;
5118
5119 if ((priv->select_info->selection_anchor !=
5120 priv->select_info->selection_end) &&
5121 priv->text)
5122 {
5123 gint start, end;
5124 gint len;
5125
5126 start = MIN (priv->select_info->selection_anchor,(((priv->select_info->selection_anchor) < (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
5127 priv->select_info->selection_end)(((priv->select_info->selection_anchor) < (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
;
5128 end = MAX (priv->select_info->selection_anchor,(((priv->select_info->selection_anchor) > (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
5129 priv->select_info->selection_end)(((priv->select_info->selection_anchor) > (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
;
5130
5131 len = strlen (priv->text);
5132
5133 if (end > len)
5134 end = len;
5135
5136 if (start > len)
5137 start = len;
5138
5139 surface = _ctk_text_util_create_drag_icon (widget,
5140 priv->text + start,
5141 end - start);
5142 }
5143
5144 if (surface)
5145 {
5146 ctk_drag_set_icon_surface (context, surface);
5147 cairo_surface_destroy (surface);
5148 }
5149 else
5150 {
5151 ctk_drag_set_icon_default (context);
5152 }
5153}
5154
5155static void
5156ctk_label_drag_gesture_begin (CtkGestureDrag *gesture,
5157 gdouble start_x,
5158 gdouble start_y,
5159 CtkLabel *label)
5160{
5161 CtkLabelPrivate *priv = label->priv;
5162 CtkLabelSelectionInfo *info = priv->select_info;
5163 CdkModifierType state_mask;
5164 CdkEventSequence *sequence;
5165 const CdkEvent *event;
5166 gint min, max, index;
5167
5168 if (!info || !info->selectable)
5169 {
5170 ctk_gesture_set_state (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, CTK_EVENT_SEQUENCE_DENIED);
5171 return;
5172 }
5173
5174 get_layout_index (label, start_x, start_y, &index);
5175 min = MIN (info->selection_anchor, info->selection_end)(((info->selection_anchor) < (info->selection_end)) ?
(info->selection_anchor) : (info->selection_end))
;
5176 max = MAX (info->selection_anchor, info->selection_end)(((info->selection_anchor) > (info->selection_end)) ?
(info->selection_anchor) : (info->selection_end))
;
5177
5178 sequence = ctk_gesture_single_get_current_sequence (CTK_GESTURE_SINGLE (gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((gesture)), ((ctk_gesture_single_get_type ()
))))))
);
5179 event = ctk_gesture_get_last_event (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, sequence);
5180 cdk_event_get_state (event, &state_mask);
5181
5182 if ((info->selection_anchor != info->selection_end) &&
5183 (state_mask & CDK_SHIFT_MASK))
5184 {
5185 if (index > min && index < max)
5186 {
5187 /* truncate selection, but keep it as big as possible */
5188 if (index - min > max - index)
5189 max = index;
5190 else
5191 min = index;
5192 }
5193 else
5194 {
5195 /* extend (same as motion) */
5196 min = MIN (min, index)(((min) < (index)) ? (min) : (index));
5197 max = MAX (max, index)(((max) > (index)) ? (max) : (index));
5198 }
5199
5200 /* ensure the anchor is opposite index */
5201 if (index == min)
5202 {
5203 gint tmp = min;
5204 min = max;
5205 max = tmp;
5206 }
5207
5208 ctk_label_select_region_index (label, min, max);
5209 }
5210 else
5211 {
5212 if (min < max && min <= index && index <= max)
5213 {
5214 info->in_drag = TRUE(!(0));
5215 info->drag_start_x = start_x;
5216 info->drag_start_y = start_y;
5217 }
5218 else
5219 /* start a replacement */
5220 ctk_label_select_region_index (label, index, index);
5221 }
5222}
5223
5224static void
5225ctk_label_drag_gesture_update (CtkGestureDrag *gesture,
5226 gdouble offset_x G_GNUC_UNUSED__attribute__ ((__unused__)),
5227 gdouble offset_y G_GNUC_UNUSED__attribute__ ((__unused__)),
5228 CtkLabel *label)
5229{
5230 CtkLabelPrivate *priv = label->priv;
5231 CtkLabelSelectionInfo *info = priv->select_info;
5232 CtkWidget *widget = CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
;
5233 CdkEventSequence *sequence;
5234 gdouble x, y;
5235 gint index;
5236
5237 if (info == NULL((void*)0) || !info->selectable)
5238 return;
5239
5240 sequence = ctk_gesture_single_get_current_sequence (CTK_GESTURE_SINGLE (gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((gesture)), ((ctk_gesture_single_get_type ()
))))))
);
5241 ctk_gesture_get_point (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, sequence, &x, &y);
5242
5243 if (info->in_drag)
5244 {
5245 if (ctk_drag_check_threshold (widget,
5246 info->drag_start_x,
5247 info->drag_start_y,
5248 x, y))
5249 {
5250 CtkTargetList *target_list = ctk_target_list_new (NULL((void*)0), 0);
5251 const CdkEvent *event;
5252
5253 event = ctk_gesture_get_last_event (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, sequence);
5254 ctk_target_list_add_text_targets (target_list, 0);
5255
5256 g_signal_connect (widget, "drag-begin",g_signal_connect_data ((widget), ("drag-begin"), (((GCallback
) (drag_begin_cb))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
5257 G_CALLBACK (drag_begin_cb), NULL)g_signal_connect_data ((widget), ("drag-begin"), (((GCallback
) (drag_begin_cb))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
5258 ctk_drag_begin_with_coordinates (widget, target_list,
5259 CDK_ACTION_COPY,
5260 1, (CdkEvent*) event,
5261 info->drag_start_x,
5262 info->drag_start_y);
5263
5264 info->in_drag = FALSE(0);
5265
5266 ctk_target_list_unref (target_list);
5267 }
5268 }
5269 else
5270 {
5271 get_layout_index (label, x, y, &index);
5272
5273 if (index != info->selection_anchor)
5274 ctk_gesture_set_state (CTK_GESTURE (gesture)((((CtkGesture*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((gesture)), ((ctk_gesture_get_type ()))))))
, CTK_EVENT_SEQUENCE_CLAIMED);
5275
5276 if (info->select_words)
5277 {
5278 gint min, max;
5279 gint old_min, old_max;
5280 gint anchor, end;
5281
5282 min = ctk_label_move_backward_word (label, index);
5283 max = ctk_label_move_forward_word (label, index);
5284
5285 anchor = info->selection_anchor;
5286 end = info->selection_end;
5287
5288 old_min = MIN (anchor, end)(((anchor) < (end)) ? (anchor) : (end));
5289 old_max = MAX (anchor, end)(((anchor) > (end)) ? (anchor) : (end));
5290
5291 if (min < old_min)
5292 {
5293 anchor = min;
5294 end = old_max;
5295 }
5296 else if (old_max < max)
5297 {
5298 anchor = max;
5299 end = old_min;
5300 }
5301 else if (anchor == old_min)
5302 {
5303 if (anchor != min)
5304 anchor = max;
5305 }
5306 else
5307 {
5308 if (anchor != max)
5309 anchor = min;
5310 }
5311
5312 ctk_label_select_region_index (label, anchor, end);
5313 }
5314 else
5315 ctk_label_select_region_index (label, info->selection_anchor, index);
5316 }
5317}
5318
5319static void
5320ctk_label_update_active_link (CtkWidget *widget,
5321 gdouble x,
5322 gdouble y)
5323{
5324 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
5325 CtkLabelPrivate *priv = label->priv;
5326 CtkLabelSelectionInfo *info = priv->select_info;
5327 gint index;
5328
5329 if (info == NULL((void*)0))
5330 return;
5331
5332 if (info->links && !info->in_drag)
5333 {
5334 GList *l;
5335 CtkLabelLink *link;
5336 gboolean found = FALSE(0);
5337
5338 if (info->selection_anchor == info->selection_end)
5339 {
5340 if (get_layout_index (label, x, y, &index))
5341 {
5342 for (l = info->links; l != NULL((void*)0); l = l->next)
5343 {
5344 link = l->data;
5345 if (index >= link->start && index <= link->end)
5346 {
5347 if (!range_is_in_ellipsis (label, link->start, link->end))
5348 found = TRUE(!(0));
5349 break;
5350 }
5351 }
5352 }
5353 }
5354
5355 if (found)
5356 {
5357 if (info->active_link != link)
5358 {
5359 info->link_clicked = 0;
5360 info->active_link = link;
5361 update_link_state (label);
5362 ctk_label_update_cursor (label);
5363 ctk_widget_queue_draw (widget);
5364 }
5365 }
5366 else
5367 {
5368 if (info->active_link != NULL((void*)0))
5369 {
5370 info->link_clicked = 0;
5371 info->active_link = NULL((void*)0);
5372 update_link_state (label);
5373 ctk_label_update_cursor (label);
5374 ctk_widget_queue_draw (widget);
5375 }
5376 }
5377 }
5378}
5379
5380static gboolean
5381ctk_label_motion (CtkWidget *widget,
5382 CdkEventMotion *event)
5383{
5384 gdouble x, y;
5385
5386 cdk_event_get_coords ((CdkEvent *) event, &x, &y);
5387 ctk_label_update_active_link (widget, x, y);
5388
5389 return CTK_WIDGET_CLASS (ctk_label_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_label_parent_class)), ((ctk_widget_get_type ()))))))
->motion_notify_event (widget, event);
5390}
5391
5392static gboolean
5393ctk_label_leave_notify (CtkWidget *widget,
5394 CdkEventCrossing *event)
5395{
5396 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
5397 CtkLabelPrivate *priv = label->priv;
5398
5399 if (priv->select_info)
5400 {
5401 priv->select_info->active_link = NULL((void*)0);
5402 ctk_label_update_cursor (label);
5403 ctk_widget_queue_draw (widget);
5404 }
5405
5406 if (CTK_WIDGET_CLASS (ctk_label_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_label_parent_class)), ((ctk_widget_get_type ()))))))
->leave_notify_event)
5407 return CTK_WIDGET_CLASS (ctk_label_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_label_parent_class)), ((ctk_widget_get_type ()))))))
->leave_notify_event (widget, event);
5408
5409 return FALSE(0);
5410}
5411
5412static void
5413ctk_label_create_window (CtkLabel *label)
5414{
5415 CtkLabelPrivate *priv = label->priv;
5416 CtkAllocation allocation;
5417 CtkWidget *widget;
5418 CdkWindowAttr attributes;
5419 gint attributes_mask;
5420
5421 g_assert (priv->select_info)do { if (priv->select_info) ; else g_assertion_message_expr
("Ctk", "ctklabel.c", 5421, ((const char*) (__func__)), "priv->select_info"
); } while (0)
;
5422 widget = CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
;
5423 g_assert (ctk_widget_get_realized (widget))do { if (ctk_widget_get_realized (widget)) ; else g_assertion_message_expr
("Ctk", "ctklabel.c", 5423, ((const char*) (__func__)), "ctk_widget_get_realized (widget)"
); } while (0)
;
5424
5425 if (priv->select_info->window)
5426 return;
5427
5428 ctk_widget_get_allocation (widget, &allocation);
5429
5430 attributes.x = allocation.x;
5431 attributes.y = allocation.y;
5432 attributes.width = allocation.width;
5433 attributes.height = allocation.height;
5434 attributes.window_type = CDK_WINDOW_CHILD;
5435 attributes.wclass = CDK_INPUT_ONLY;
5436 attributes.override_redirect = TRUE(!(0));
5437 attributes.event_mask = ctk_widget_get_events (widget) |
5438 CDK_BUTTON_PRESS_MASK |
5439 CDK_BUTTON_RELEASE_MASK |
5440 CDK_LEAVE_NOTIFY_MASK |
5441 CDK_BUTTON_MOTION_MASK |
5442 CDK_POINTER_MOTION_MASK;
5443 attributes_mask = CDK_WA_X | CDK_WA_Y | CDK_WA_NOREDIR;
5444 if (ctk_widget_is_sensitive (widget) && priv->select_info->selectable)
5445 {
5446 attributes.cursor = cdk_cursor_new_for_display (ctk_widget_get_display (widget),
5447 CDK_XTERM);
5448 attributes_mask |= CDK_WA_CURSOR;
5449 }
5450
5451
5452 priv->select_info->window = cdk_window_new (ctk_widget_get_window (widget),
5453 &attributes, attributes_mask);
5454 ctk_widget_register_window (widget, priv->select_info->window);
5455
5456 if (attributes_mask & CDK_WA_CURSOR)
5457 g_object_unref (attributes.cursor);
5458}
5459
5460static void
5461ctk_label_destroy_window (CtkLabel *label)
5462{
5463 CtkLabelPrivate *priv = label->priv;
5464
5465 g_assert (priv->select_info)do { if (priv->select_info) ; else g_assertion_message_expr
("Ctk", "ctklabel.c", 5465, ((const char*) (__func__)), "priv->select_info"
); } while (0)
;
5466
5467 if (priv->select_info->window == NULL((void*)0))
5468 return;
5469
5470 ctk_widget_unregister_window (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
, priv->select_info->window);
5471 cdk_window_destroy (priv->select_info->window);
5472 priv->select_info->window = NULL((void*)0);
5473}
5474
5475static void
5476ctk_label_ensure_select_info (CtkLabel *label)
5477{
5478 CtkLabelPrivate *priv = label->priv;
5479
5480 if (priv->select_info == NULL((void*)0))
5481 {
5482 priv->select_info = g_new0 (CtkLabelSelectionInfo, 1)((CtkLabelSelectionInfo *) g_malloc0_n ((1), sizeof (CtkLabelSelectionInfo
)))
;
5483
5484 ctk_widget_set_can_focus (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
, TRUE(!(0)));
5485
5486 if (ctk_widget_get_realized (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
))
5487 ctk_label_create_window (label);
5488
5489 if (ctk_widget_get_mapped (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
))
5490 cdk_window_show (priv->select_info->window);
5491
5492 priv->select_info->drag_gesture = ctk_gesture_drag_new (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
5493 g_signal_connect (priv->select_info->drag_gesture, "drag-begin",g_signal_connect_data ((priv->select_info->drag_gesture
), ("drag-begin"), (((GCallback) (ctk_label_drag_gesture_begin
))), (label), ((void*)0), (GConnectFlags) 0)
5494 G_CALLBACK (ctk_label_drag_gesture_begin), label)g_signal_connect_data ((priv->select_info->drag_gesture
), ("drag-begin"), (((GCallback) (ctk_label_drag_gesture_begin
))), (label), ((void*)0), (GConnectFlags) 0)
;
5495 g_signal_connect (priv->select_info->drag_gesture, "drag-update",g_signal_connect_data ((priv->select_info->drag_gesture
), ("drag-update"), (((GCallback) (ctk_label_drag_gesture_update
))), (label), ((void*)0), (GConnectFlags) 0)
5496 G_CALLBACK (ctk_label_drag_gesture_update), label)g_signal_connect_data ((priv->select_info->drag_gesture
), ("drag-update"), (((GCallback) (ctk_label_drag_gesture_update
))), (label), ((void*)0), (GConnectFlags) 0)
;
5497 ctk_gesture_single_set_exclusive (CTK_GESTURE_SINGLE (priv->select_info->drag_gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((priv->select_info->drag_gesture)), ((
ctk_gesture_single_get_type ()))))))
, TRUE(!(0)));
5498
5499 priv->select_info->multipress_gesture = ctk_gesture_multi_press_new (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
5500 g_signal_connect (priv->select_info->multipress_gesture, "pressed",g_signal_connect_data ((priv->select_info->multipress_gesture
), ("pressed"), (((GCallback) (ctk_label_multipress_gesture_pressed
))), (label), ((void*)0), (GConnectFlags) 0)
5501 G_CALLBACK (ctk_label_multipress_gesture_pressed), label)g_signal_connect_data ((priv->select_info->multipress_gesture
), ("pressed"), (((GCallback) (ctk_label_multipress_gesture_pressed
))), (label), ((void*)0), (GConnectFlags) 0)
;
5502 g_signal_connect (priv->select_info->multipress_gesture, "released",g_signal_connect_data ((priv->select_info->multipress_gesture
), ("released"), (((GCallback) (ctk_label_multipress_gesture_released
))), (label), ((void*)0), (GConnectFlags) 0)
5503 G_CALLBACK (ctk_label_multipress_gesture_released), label)g_signal_connect_data ((priv->select_info->multipress_gesture
), ("released"), (((GCallback) (ctk_label_multipress_gesture_released
))), (label), ((void*)0), (GConnectFlags) 0)
;
5504 ctk_gesture_single_set_button (CTK_GESTURE_SINGLE (priv->select_info->multipress_gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((priv->select_info->multipress_gesture
)), ((ctk_gesture_single_get_type ()))))))
, 0);
5505 ctk_gesture_single_set_exclusive (CTK_GESTURE_SINGLE (priv->select_info->multipress_gesture)((((CtkGestureSingle*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((priv->select_info->multipress_gesture
)), ((ctk_gesture_single_get_type ()))))))
, TRUE(!(0)));
5506 }
5507}
5508
5509static void
5510ctk_label_clear_select_info (CtkLabel *label)
5511{
5512 CtkLabelPrivate *priv = label->priv;
5513
5514 if (priv->select_info == NULL((void*)0))
5515 return;
5516
5517 if (!priv->select_info->selectable && !priv->select_info->links)
5518 {
5519 ctk_label_destroy_window (label);
5520
5521 g_object_unref (priv->select_info->drag_gesture);
5522 g_object_unref (priv->select_info->multipress_gesture);
5523
5524 g_free (priv->select_info);
5525 priv->select_info = NULL((void*)0);
5526
5527 ctk_widget_set_can_focus (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
, FALSE(0));
5528 }
5529}
5530
5531/**
5532 * ctk_label_set_selectable:
5533 * @label: a #CtkLabel
5534 * @setting: %TRUE to allow selecting text in the label
5535 *
5536 * Selectable labels allow the user to select text from the label, for
5537 * copy-and-paste.
5538 **/
5539void
5540ctk_label_set_selectable (CtkLabel *label,
5541 gboolean setting)
5542{
5543 CtkLabelPrivate *priv;
5544 gboolean old_setting;
5545
5546 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
5547
5548 priv = label->priv;
5549
5550 setting = setting != FALSE(0);
5551 old_setting = priv->select_info && priv->select_info->selectable;
5552
5553 if (setting)
5554 {
5555 ctk_label_ensure_select_info (label);
5556 priv->select_info->selectable = TRUE(!(0));
5557 ctk_label_update_cursor (label);
5558 }
5559 else
5560 {
5561 if (old_setting)
5562 {
5563 /* unselect, to give up the selection */
5564 ctk_label_select_region (label, 0, 0);
5565
5566 priv->select_info->selectable = FALSE(0);
5567 ctk_label_clear_select_info (label);
5568 ctk_label_update_cursor (label);
5569 }
5570 }
5571 if (setting != old_setting)
5572 {
5573 g_object_freeze_notify (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
5574 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_SELECTABLE]);
5575 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_CURSOR_POSITION]);
5576 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_SELECTION_BOUND]);
5577 g_object_thaw_notify (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
5578 ctk_widget_queue_draw (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
5579 }
5580}
5581
5582/**
5583 * ctk_label_get_selectable:
5584 * @label: a #CtkLabel
5585 *
5586 * Gets the value set by ctk_label_set_selectable().
5587 *
5588 * Returns: %TRUE if the user can copy text from the label
5589 **/
5590gboolean
5591ctk_label_get_selectable (CtkLabel *label)
5592{
5593 CtkLabelPrivate *priv;
5594
5595 g_return_val_if_fail (CTK_IS_LABEL (label), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return ((0)); } } while (0)
;
5596
5597 priv = label->priv;
5598
5599 return priv->select_info && priv->select_info->selectable;
5600}
5601
5602/**
5603 * ctk_label_set_angle:
5604 * @label: a #CtkLabel
5605 * @angle: the angle that the baseline of the label makes with
5606 * the horizontal, in degrees, measured counterclockwise
5607 *
5608 * Sets the angle of rotation for the label. An angle of 90 reads from
5609 * from bottom to top, an angle of 270, from top to bottom. The angle
5610 * setting for the label is ignored if the label is selectable,
5611 * wrapped, or ellipsized.
5612 *
5613 * Since: 2.6
5614 **/
5615void
5616ctk_label_set_angle (CtkLabel *label,
5617 gdouble angle)
5618{
5619 CtkLabelPrivate *priv;
5620
5621 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
5622
5623 priv = label->priv;
5624
5625 /* Canonicalize to [0,360]. We don't canonicalize 360 to 0, because
5626 * double property ranges are inclusive, and changing 360 to 0 would
5627 * make a property editor behave strangely.
5628 */
5629 if (angle < 0 || angle > 360.0)
5630 angle = angle - 360. * floor (angle / 360.);
5631
5632 if (priv->angle != angle)
5633 {
5634 priv->angle = angle;
5635
5636 ctk_label_clear_layout (label);
5637 ctk_widget_queue_resize (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
5638
5639 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_ANGLE]);
5640 }
5641}
5642
5643/**
5644 * ctk_label_get_angle:
5645 * @label: a #CtkLabel
5646 *
5647 * Gets the angle of rotation for the label. See
5648 * ctk_label_set_angle().
5649 *
5650 * Returns: the angle of rotation for the label
5651 *
5652 * Since: 2.6
5653 **/
5654gdouble
5655ctk_label_get_angle (CtkLabel *label)
5656{
5657 g_return_val_if_fail (CTK_IS_LABEL (label), 0.0)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return (0.0); } } while (0)
;
5658
5659 return label->priv->angle;
5660}
5661
5662static void
5663ctk_label_set_selection_text (CtkLabel *label,
5664 CtkSelectionData *selection_data)
5665{
5666 CtkLabelPrivate *priv = label->priv;
5667
5668 if (priv->select_info &&
5669 (priv->select_info->selection_anchor !=
5670 priv->select_info->selection_end) &&
5671 priv->text)
5672 {
5673 gint start, end;
5674 gint len;
5675
5676 start = MIN (priv->select_info->selection_anchor,(((priv->select_info->selection_anchor) < (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
5677 priv->select_info->selection_end)(((priv->select_info->selection_anchor) < (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
;
5678 end = MAX (priv->select_info->selection_anchor,(((priv->select_info->selection_anchor) > (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
5679 priv->select_info->selection_end)(((priv->select_info->selection_anchor) > (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
;
5680
5681 len = strlen (priv->text);
5682
5683 if (end > len)
5684 end = len;
5685
5686 if (start > len)
5687 start = len;
5688
5689 ctk_selection_data_set_text (selection_data,
5690 priv->text + start,
5691 end - start);
5692 }
5693}
5694
5695static void
5696ctk_label_drag_data_get (CtkWidget *widget,
5697 CdkDragContext *context G_GNUC_UNUSED__attribute__ ((__unused__)),
5698 CtkSelectionData *selection_data,
5699 guint info G_GNUC_UNUSED__attribute__ ((__unused__)),
5700 guint time G_GNUC_UNUSED__attribute__ ((__unused__)))
5701{
5702 ctk_label_set_selection_text (CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
, selection_data);
5703}
5704
5705static void
5706get_text_callback (CtkClipboard *clipboard G_GNUC_UNUSED__attribute__ ((__unused__)),
5707 CtkSelectionData *selection_data,
5708 guint info G_GNUC_UNUSED__attribute__ ((__unused__)),
5709 gpointer user_data_or_owner)
5710{
5711 ctk_label_set_selection_text (CTK_LABEL (user_data_or_owner)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data_or_owner)), ((ctk_label_get_type ()))))))
, selection_data);
5712}
5713
5714static void
5715clear_text_callback (CtkClipboard *clipboard G_GNUC_UNUSED__attribute__ ((__unused__)),
5716 gpointer user_data_or_owner)
5717{
5718 CtkLabel *label;
5719 CtkLabelPrivate *priv;
5720
5721 label = CTK_LABEL (user_data_or_owner)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data_or_owner)), ((ctk_label_get_type ()))))))
;
5722 priv = label->priv;
5723
5724 if (priv->select_info)
5725 {
5726 priv->select_info->selection_anchor = priv->select_info->selection_end;
5727
5728 ctk_widget_queue_draw (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
5729 }
5730}
5731
5732static void
5733ctk_label_select_region_index (CtkLabel *label,
5734 gint anchor_index,
5735 gint end_index)
5736{
5737 CtkLabelPrivate *priv;
5738
5739 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
5740
5741 priv = label->priv;
5742
5743 if (priv->select_info && priv->select_info->selectable)
5744 {
5745 CtkClipboard *clipboard;
5746 gint s, e;
5747
5748 /* Ensure that we treat an ellipsized region like a single
5749 * character with respect to selection.
5750 */
5751 if (anchor_index < end_index)
5752 {
5753 if (range_is_in_ellipsis_full (label, anchor_index, anchor_index + 1, &s, &e))
5754 {
5755 if (priv->select_info->selection_anchor == s)
5756 anchor_index = e;
5757 else
5758 anchor_index = s;
5759 }
5760 if (range_is_in_ellipsis_full (label, end_index - 1, end_index, &s, &e))
5761 {
5762 if (priv->select_info->selection_end == e)
5763 end_index = s;
5764 else
5765 end_index = e;
5766 }
5767 }
5768 else if (end_index < anchor_index)
5769 {
5770 if (range_is_in_ellipsis_full (label, end_index, end_index + 1, &s, &e))
5771 {
5772 if (priv->select_info->selection_end == s)
5773 end_index = e;
5774 else
5775 end_index = s;
5776 }
5777 if (range_is_in_ellipsis_full (label, anchor_index - 1, anchor_index, &s, &e))
5778 {
5779 if (priv->select_info->selection_anchor == e)
5780 anchor_index = s;
5781 else
5782 anchor_index = e;
5783 }
5784 }
5785 else
5786 {
5787 if (range_is_in_ellipsis_full (label, anchor_index, anchor_index, &s, &e))
5788 {
5789 if (priv->select_info->selection_anchor == s)
5790 anchor_index = e;
5791 else if (priv->select_info->selection_anchor == e)
5792 anchor_index = s;
5793 else if (anchor_index - s < e - anchor_index)
5794 anchor_index = s;
5795 else
5796 anchor_index = e;
5797 end_index = anchor_index;
5798 }
5799 }
5800
5801 if (priv->select_info->selection_anchor == anchor_index &&
5802 priv->select_info->selection_end == end_index)
5803 return;
5804
5805 g_object_freeze_notify (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
5806
5807 if (priv->select_info->selection_anchor != anchor_index)
5808 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_SELECTION_BOUND]);
5809 if (priv->select_info->selection_end != end_index)
5810 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_CURSOR_POSITION]);
5811
5812 priv->select_info->selection_anchor = anchor_index;
5813 priv->select_info->selection_end = end_index;
5814
5815 if (ctk_widget_has_screen (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
))
5816 clipboard = ctk_widget_get_clipboard (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
,
5817 CDK_SELECTION_PRIMARY((CdkAtom)((gpointer) (gulong) (1))));
5818 else
5819 clipboard = NULL((void*)0);
5820
5821 if (anchor_index != end_index)
5822 {
5823 CtkTargetList *list;
5824 CtkTargetEntry *targets;
5825 gint n_targets;
5826
5827 list = ctk_target_list_new (NULL((void*)0), 0);
5828 ctk_target_list_add_text_targets (list, 0);
5829 targets = ctk_target_table_new_from_list (list, &n_targets);
5830
5831 if (clipboard)
5832 ctk_clipboard_set_with_owner (clipboard,
5833 targets, n_targets,
5834 get_text_callback,
5835 clear_text_callback,
5836 G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
5837
5838 ctk_target_table_free (targets, n_targets);
5839 ctk_target_list_unref (list);
5840
5841 if (!priv->select_info->selection_node)
5842 {
5843 CtkCssNode *widget_node;
5844
5845 widget_node = ctk_widget_get_css_node (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
5846 priv->select_info->selection_node = ctk_css_node_new ();
5847 ctk_css_node_set_name (priv->select_info->selection_node, I_("selection")g_intern_static_string ("selection"));
5848 ctk_css_node_set_parent (priv->select_info->selection_node, widget_node);
5849 ctk_css_node_set_state (priv->select_info->selection_node, ctk_css_node_get_state (widget_node));
5850 g_object_unref (priv->select_info->selection_node);
5851 }
5852 }
5853 else
5854 {
5855 if (clipboard &&
5856 ctk_clipboard_get_owner (clipboard) == G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
)
5857 ctk_clipboard_clear (clipboard);
5858
5859 if (priv->select_info->selection_node)
5860 {
5861 ctk_css_node_set_parent (priv->select_info->selection_node, NULL((void*)0));
5862 priv->select_info->selection_node = NULL((void*)0);
5863 }
5864 }
5865
5866 ctk_widget_queue_draw (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
5867
5868 g_object_thaw_notify (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
5869 }
5870}
5871
5872/**
5873 * ctk_label_select_region:
5874 * @label: a #CtkLabel
5875 * @start_offset: start offset (in characters not bytes)
5876 * @end_offset: end offset (in characters not bytes)
5877 *
5878 * Selects a range of characters in the label, if the label is selectable.
5879 * See ctk_label_set_selectable(). If the label is not selectable,
5880 * this function has no effect. If @start_offset or
5881 * @end_offset are -1, then the end of the label will be substituted.
5882 **/
5883void
5884ctk_label_select_region (CtkLabel *label,
5885 gint start_offset,
5886 gint end_offset)
5887{
5888 CtkLabelPrivate *priv;
5889
5890 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
5891
5892 priv = label->priv;
5893
5894 if (priv->text && priv->select_info)
5895 {
5896 if (start_offset < 0)
5897 start_offset = g_utf8_strlen (priv->text, -1);
5898
5899 if (end_offset < 0)
5900 end_offset = g_utf8_strlen (priv->text, -1);
5901
5902 ctk_label_select_region_index (label,
5903 g_utf8_offset_to_pointer (priv->text, start_offset) - priv->text,
5904 g_utf8_offset_to_pointer (priv->text, end_offset) - priv->text);
5905 }
5906}
5907
5908/**
5909 * ctk_label_get_selection_bounds:
5910 * @label: a #CtkLabel
5911 * @start: (out): return location for start of selection, as a character offset
5912 * @end: (out): return location for end of selection, as a character offset
5913 *
5914 * Gets the selected range of characters in the label, returning %TRUE
5915 * if there’s a selection.
5916 *
5917 * Returns: %TRUE if selection is non-empty
5918 **/
5919gboolean
5920ctk_label_get_selection_bounds (CtkLabel *label,
5921 gint *start,
5922 gint *end)
5923{
5924 CtkLabelPrivate *priv;
5925
5926 g_return_val_if_fail (CTK_IS_LABEL (label), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return ((0)); } } while (0)
;
5927
5928 priv = label->priv;
5929
5930 if (priv->select_info == NULL((void*)0))
5931 {
5932 /* not a selectable label */
5933 if (start)
5934 *start = 0;
5935 if (end)
5936 *end = 0;
5937
5938 return FALSE(0);
5939 }
5940 else
5941 {
5942 gint start_index, end_index;
5943 gint start_offset, end_offset;
5944 gint len;
5945
5946 start_index = MIN (priv->select_info->selection_anchor,(((priv->select_info->selection_anchor) < (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
5947 priv->select_info->selection_end)(((priv->select_info->selection_anchor) < (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
;
5948 end_index = MAX (priv->select_info->selection_anchor,(((priv->select_info->selection_anchor) > (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
5949 priv->select_info->selection_end)(((priv->select_info->selection_anchor) > (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
;
5950
5951 len = strlen (priv->text);
5952
5953 if (end_index > len)
5954 end_index = len;
5955
5956 if (start_index > len)
5957 start_index = len;
5958
5959 start_offset = g_utf8_strlen (priv->text, start_index);
5960 end_offset = g_utf8_strlen (priv->text, end_index);
5961
5962 if (start_offset > end_offset)
5963 {
5964 gint tmp = start_offset;
5965 start_offset = end_offset;
5966 end_offset = tmp;
5967 }
5968
5969 if (start)
5970 *start = start_offset;
5971
5972 if (end)
5973 *end = end_offset;
5974
5975 return start_offset != end_offset;
5976 }
5977}
5978
5979
5980/**
5981 * ctk_label_get_layout:
5982 * @label: a #CtkLabel
5983 *
5984 * Gets the #PangoLayout used to display the label.
5985 * The layout is useful to e.g. convert text positions to
5986 * pixel positions, in combination with ctk_label_get_layout_offsets().
5987 * The returned layout is owned by the @label so need not be
5988 * freed by the caller. The @label is free to recreate its layout at
5989 * any time, so it should be considered read-only.
5990 *
5991 * Returns: (transfer none): the #PangoLayout for this label
5992 **/
5993PangoLayout*
5994ctk_label_get_layout (CtkLabel *label)
5995{
5996 CtkLabelPrivate *priv;
5997
5998 g_return_val_if_fail (CTK_IS_LABEL (label), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return (((void*)0)); } } while (
0)
;
5999
6000 priv = label->priv;
6001
6002 ctk_label_ensure_layout (label);
6003
6004 return priv->layout;
6005}
6006
6007/**
6008 * ctk_label_get_layout_offsets:
6009 * @label: a #CtkLabel
6010 * @x: (out) (optional): location to store X offset of layout, or %NULL
6011 * @y: (out) (optional): location to store Y offset of layout, or %NULL
6012 *
6013 * Obtains the coordinates where the label will draw the #PangoLayout
6014 * representing the text in the label; useful to convert mouse events
6015 * into coordinates inside the #PangoLayout, e.g. to take some action
6016 * if some part of the label is clicked. Of course you will need to
6017 * create a #CtkEventBox to receive the events, and pack the label
6018 * inside it, since labels are windowless (they return %FALSE from
6019 * ctk_widget_get_has_window()). Remember
6020 * when using the #PangoLayout functions you need to convert to
6021 * and from pixels using PANGO_PIXELS() or #PANGO_SCALE.
6022 **/
6023void
6024ctk_label_get_layout_offsets (CtkLabel *label,
6025 gint *x,
6026 gint *y)
6027{
6028 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
6029
6030 ctk_label_ensure_layout (label);
6031
6032 get_layout_location (label, x, y);
6033}
6034
6035/**
6036 * ctk_label_set_use_markup:
6037 * @label: a #CtkLabel
6038 * @setting: %TRUE if the label’s text should be parsed for markup.
6039 *
6040 * Sets whether the text of the label contains markup in
6041 * [Pango’s text markup language][PangoMarkupFormat].
6042 * See ctk_label_set_markup().
6043 **/
6044void
6045ctk_label_set_use_markup (CtkLabel *label,
6046 gboolean setting)
6047{
6048 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
6049
6050 g_object_freeze_notify (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
6051
6052 if (ctk_label_set_use_markup_internal (label, setting))
6053 ctk_label_recalculate (label);
6054
6055 g_object_thaw_notify (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
6056}
6057
6058/**
6059 * ctk_label_get_use_markup:
6060 * @label: a #CtkLabel
6061 *
6062 * Returns whether the label’s text is interpreted as marked up with
6063 * the [Pango text markup language][PangoMarkupFormat].
6064 * See ctk_label_set_use_markup ().
6065 *
6066 * Returns: %TRUE if the label’s text will be parsed for markup.
6067 **/
6068gboolean
6069ctk_label_get_use_markup (CtkLabel *label)
6070{
6071 g_return_val_if_fail (CTK_IS_LABEL (label), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return ((0)); } } while (0)
;
6072
6073 return label->priv->use_markup;
6074}
6075
6076/**
6077 * ctk_label_set_use_underline:
6078 * @label: a #CtkLabel
6079 * @setting: %TRUE if underlines in the text indicate mnemonics
6080 *
6081 * If true, an underline in the text indicates the next character should be
6082 * used for the mnemonic accelerator key.
6083 */
6084void
6085ctk_label_set_use_underline (CtkLabel *label,
6086 gboolean setting)
6087{
6088 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
6089
6090 g_object_freeze_notify (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
6091
6092 if (ctk_label_set_use_underline_internal (label, setting))
6093 ctk_label_recalculate (label);
6094
6095 g_object_thaw_notify (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
);
6096}
6097
6098/**
6099 * ctk_label_get_use_underline:
6100 * @label: a #CtkLabel
6101 *
6102 * Returns whether an embedded underline in the label indicates a
6103 * mnemonic. See ctk_label_set_use_underline().
6104 *
6105 * Returns: %TRUE whether an embedded underline in the label indicates
6106 * the mnemonic accelerator keys.
6107 **/
6108gboolean
6109ctk_label_get_use_underline (CtkLabel *label)
6110{
6111 g_return_val_if_fail (CTK_IS_LABEL (label), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return ((0)); } } while (0)
;
6112
6113 return label->priv->use_underline;
6114}
6115
6116/**
6117 * ctk_label_set_single_line_mode:
6118 * @label: a #CtkLabel
6119 * @single_line_mode: %TRUE if the label should be in single line mode
6120 *
6121 * Sets whether the label is in single line mode.
6122 *
6123 * Since: 2.6
6124 */
6125void
6126ctk_label_set_single_line_mode (CtkLabel *label,
6127 gboolean single_line_mode)
6128{
6129 CtkLabelPrivate *priv;
6130
6131 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
6132
6133 priv = label->priv;
6134
6135 single_line_mode = single_line_mode != FALSE(0);
6136
6137 if (priv->single_line_mode != single_line_mode)
6138 {
6139 priv->single_line_mode = single_line_mode;
6140
6141 ctk_label_clear_layout (label);
6142 ctk_widget_queue_resize (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
6143
6144 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_SINGLE_LINE_MODE]);
6145 }
6146}
6147
6148/**
6149 * ctk_label_get_single_line_mode:
6150 * @label: a #CtkLabel
6151 *
6152 * Returns whether the label is in single line mode.
6153 *
6154 * Returns: %TRUE when the label is in single line mode.
6155 *
6156 * Since: 2.6
6157 **/
6158gboolean
6159ctk_label_get_single_line_mode (CtkLabel *label)
6160{
6161 g_return_val_if_fail (CTK_IS_LABEL (label), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return ((0)); } } while (0)
;
6162
6163 return label->priv->single_line_mode;
6164}
6165
6166/* Compute the X position for an offset that corresponds to the "more important
6167 * cursor position for that offset. We use this when trying to guess to which
6168 * end of the selection we should go to when the user hits the left or
6169 * right arrow key.
6170 */
6171static void
6172get_better_cursor (CtkLabel *label,
6173 gint index,
6174 gint *x,
6175 gint *y)
6176{
6177 CtkLabelPrivate *priv = label->priv;
6178 CdkKeymap *keymap = cdk_keymap_get_for_display (ctk_widget_get_display (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
));
6179 PangoDirection keymap_direction = cdk_keymap_get_direction (keymap);
6180 PangoDirection cursor_direction = get_cursor_direction (label);
6181 gboolean split_cursor;
6182 PangoRectangle strong_pos, weak_pos;
6183
6184 g_object_get (ctk_widget_get_settings (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
),
6185 "ctk-split-cursor", &split_cursor,
6186 NULL((void*)0));
6187
6188 ctk_label_ensure_layout (label);
6189
6190 pango_layout_get_cursor_pos (priv->layout, index,
6191 &strong_pos, &weak_pos);
6192
6193 if (split_cursor)
6194 {
6195 *x = strong_pos.x / PANGO_SCALE1024;
6196 *y = strong_pos.y / PANGO_SCALE1024;
6197 }
6198 else
6199 {
6200 if (keymap_direction == cursor_direction)
6201 {
6202 *x = strong_pos.x / PANGO_SCALE1024;
6203 *y = strong_pos.y / PANGO_SCALE1024;
6204 }
6205 else
6206 {
6207 *x = weak_pos.x / PANGO_SCALE1024;
6208 *y = weak_pos.y / PANGO_SCALE1024;
6209 }
6210 }
6211}
6212
6213
6214static gint
6215ctk_label_move_logically (CtkLabel *label,
6216 gint start,
6217 gint count)
6218{
6219 CtkLabelPrivate *priv = label->priv;
6220 gint offset = g_utf8_pointer_to_offset (priv->text,
6221 priv->text + start);
6222
6223 if (priv->text)
6224 {
6225 PangoLogAttr *log_attrs;
6226 gint n_attrs;
6227 gint length;
6228
6229 ctk_label_ensure_layout (label);
6230
6231 length = g_utf8_strlen (priv->text, -1);
6232
6233 pango_layout_get_log_attrs (priv->layout, &log_attrs, &n_attrs);
6234
6235 while (count > 0 && offset < length)
6236 {
6237 do
6238 offset++;
6239 while (offset < length && !log_attrs[offset].is_cursor_position);
6240
6241 count--;
6242 }
6243 while (count < 0 && offset > 0)
6244 {
6245 do
6246 offset--;
6247 while (offset > 0 && !log_attrs[offset].is_cursor_position);
6248
6249 count++;
6250 }
6251
6252 g_free (log_attrs);
6253 }
6254
6255 return g_utf8_offset_to_pointer (priv->text, offset) - priv->text;
6256}
6257
6258static gint
6259ctk_label_move_visually (CtkLabel *label,
6260 gint start,
6261 gint count)
6262{
6263 CtkLabelPrivate *priv = label->priv;
6264 gint index;
6265
6266 index = start;
6267
6268 while (count != 0)
6269 {
6270 int new_index, new_trailing;
6271 gboolean split_cursor;
6272 gboolean strong;
6273
6274 ctk_label_ensure_layout (label);
6275
6276 g_object_get (ctk_widget_get_settings (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
),
6277 "ctk-split-cursor", &split_cursor,
6278 NULL((void*)0));
6279
6280 if (split_cursor)
6281 strong = TRUE(!(0));
6282 else
6283 {
6284 CdkKeymap *keymap = cdk_keymap_get_for_display (ctk_widget_get_display (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
));
6285 PangoDirection keymap_direction = cdk_keymap_get_direction (keymap);
6286
6287 strong = keymap_direction == get_cursor_direction (label);
6288 }
6289
6290 if (count > 0)
6291 {
6292 pango_layout_move_cursor_visually (priv->layout, strong, index, 0, 1, &new_index, &new_trailing);
6293 count--;
6294 }
6295 else
6296 {
6297 pango_layout_move_cursor_visually (priv->layout, strong, index, 0, -1, &new_index, &new_trailing);
6298 count++;
6299 }
6300
6301 if (new_index < 0 || new_index == G_MAXINT2147483647)
6302 break;
6303
6304 index = new_index;
6305
6306 while (new_trailing--)
6307 index = g_utf8_next_char (priv->text + new_index)((priv->text + new_index) + g_utf8_skip[*(const guchar *)(
priv->text + new_index)])
- priv->text;
6308 }
6309
6310 return index;
6311}
6312
6313static gint
6314ctk_label_move_forward_word (CtkLabel *label,
6315 gint start)
6316{
6317 CtkLabelPrivate *priv = label->priv;
6318 gint new_pos = g_utf8_pointer_to_offset (priv->text,
6319 priv->text + start);
6320 gint length;
6321
6322 length = g_utf8_strlen (priv->text, -1);
6323 if (new_pos < length)
6324 {
6325 PangoLogAttr *log_attrs;
6326 gint n_attrs;
6327
6328 ctk_label_ensure_layout (label);
6329
6330 pango_layout_get_log_attrs (priv->layout, &log_attrs, &n_attrs);
6331
6332 /* Find the next word end */
6333 new_pos++;
6334 while (new_pos < n_attrs && !log_attrs[new_pos].is_word_end)
6335 new_pos++;
6336
6337 g_free (log_attrs);
6338 }
6339
6340 return g_utf8_offset_to_pointer (priv->text, new_pos) - priv->text;
6341}
6342
6343
6344static gint
6345ctk_label_move_backward_word (CtkLabel *label,
6346 gint start)
6347{
6348 CtkLabelPrivate *priv = label->priv;
6349 gint new_pos = g_utf8_pointer_to_offset (priv->text,
6350 priv->text + start);
6351
6352 if (new_pos > 0)
6353 {
6354 PangoLogAttr *log_attrs;
6355 gint n_attrs;
6356
6357 ctk_label_ensure_layout (label);
6358
6359 pango_layout_get_log_attrs (priv->layout, &log_attrs, &n_attrs);
6360
6361 new_pos -= 1;
6362
6363 /* Find the previous word beginning */
6364 while (new_pos > 0 && !log_attrs[new_pos].is_word_start)
6365 new_pos--;
6366
6367 g_free (log_attrs);
6368 }
6369
6370 return g_utf8_offset_to_pointer (priv->text, new_pos) - priv->text;
6371}
6372
6373static void
6374ctk_label_move_cursor (CtkLabel *label,
6375 CtkMovementStep step,
6376 gint count,
6377 gboolean extend_selection)
6378{
6379 CtkLabelPrivate *priv = label->priv;
6380 gint old_pos;
6381 gint new_pos;
6382
6383 if (priv->select_info == NULL((void*)0))
6384 return;
6385
6386 old_pos = new_pos = priv->select_info->selection_end;
6387
6388 if (priv->select_info->selection_end != priv->select_info->selection_anchor &&
6389 !extend_selection)
6390 {
6391 /* If we have a current selection and aren't extending it, move to the
6392 * start/or end of the selection as appropriate
6393 */
6394 switch (step)
6395 {
6396 case CTK_MOVEMENT_VISUAL_POSITIONS:
6397 {
6398 gint end_x, end_y;
6399 gint anchor_x, anchor_y;
6400 gboolean end_is_left;
6401
6402 get_better_cursor (label, priv->select_info->selection_end, &end_x, &end_y);
6403 get_better_cursor (label, priv->select_info->selection_anchor, &anchor_x, &anchor_y);
6404
6405 end_is_left = (end_y < anchor_y) || (end_y == anchor_y && end_x < anchor_x);
6406
6407 if (count < 0)
6408 new_pos = end_is_left ? priv->select_info->selection_end : priv->select_info->selection_anchor;
6409 else
6410 new_pos = !end_is_left ? priv->select_info->selection_end : priv->select_info->selection_anchor;
6411 break;
6412 }
6413 case CTK_MOVEMENT_LOGICAL_POSITIONS:
6414 case CTK_MOVEMENT_WORDS:
6415 if (count < 0)
6416 new_pos = MIN (priv->select_info->selection_end, priv->select_info->selection_anchor)(((priv->select_info->selection_end) < (priv->select_info
->selection_anchor)) ? (priv->select_info->selection_end
) : (priv->select_info->selection_anchor))
;
6417 else
6418 new_pos = MAX (priv->select_info->selection_end, priv->select_info->selection_anchor)(((priv->select_info->selection_end) > (priv->select_info
->selection_anchor)) ? (priv->select_info->selection_end
) : (priv->select_info->selection_anchor))
;
6419 break;
6420 case CTK_MOVEMENT_DISPLAY_LINE_ENDS:
6421 case CTK_MOVEMENT_PARAGRAPH_ENDS:
6422 case CTK_MOVEMENT_BUFFER_ENDS:
6423 /* FIXME: Can do better here */
6424 new_pos = count < 0 ? 0 : strlen (priv->text);
6425 break;
6426 case CTK_MOVEMENT_DISPLAY_LINES:
6427 case CTK_MOVEMENT_PARAGRAPHS:
6428 case CTK_MOVEMENT_PAGES:
6429 case CTK_MOVEMENT_HORIZONTAL_PAGES:
6430 break;
6431 }
6432 }
6433 else
6434 {
6435 switch (step)
6436 {
6437 case CTK_MOVEMENT_LOGICAL_POSITIONS:
6438 new_pos = ctk_label_move_logically (label, new_pos, count);
6439 break;
6440 case CTK_MOVEMENT_VISUAL_POSITIONS:
6441 new_pos = ctk_label_move_visually (label, new_pos, count);
6442 if (new_pos == old_pos)
6443 {
6444 if (!extend_selection)
6445 {
6446 if (!ctk_widget_keynav_failed (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
,
6447 count > 0 ?
6448 CTK_DIR_RIGHT : CTK_DIR_LEFT))
6449 {
6450 CtkWidget *toplevel = ctk_widget_get_toplevel (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
6451
6452 if (toplevel)
6453 ctk_widget_child_focus (toplevel,
6454 count > 0 ?
6455 CTK_DIR_RIGHT : CTK_DIR_LEFT);
6456 }
6457 }
6458 else
6459 {
6460 ctk_widget_error_bell (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
6461 }
6462 }
6463 break;
6464 case CTK_MOVEMENT_WORDS:
6465 while (count > 0)
6466 {
6467 new_pos = ctk_label_move_forward_word (label, new_pos);
6468 count--;
6469 }
6470 while (count < 0)
6471 {
6472 new_pos = ctk_label_move_backward_word (label, new_pos);
6473 count++;
6474 }
6475 if (new_pos == old_pos)
6476 ctk_widget_error_bell (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
6477 break;
6478 case CTK_MOVEMENT_DISPLAY_LINE_ENDS:
6479 case CTK_MOVEMENT_PARAGRAPH_ENDS:
6480 case CTK_MOVEMENT_BUFFER_ENDS:
6481 /* FIXME: Can do better here */
6482 new_pos = count < 0 ? 0 : strlen (priv->text);
6483 if (new_pos == old_pos)
6484 ctk_widget_error_bell (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
6485 break;
6486 case CTK_MOVEMENT_DISPLAY_LINES:
6487 case CTK_MOVEMENT_PARAGRAPHS:
6488 case CTK_MOVEMENT_PAGES:
6489 case CTK_MOVEMENT_HORIZONTAL_PAGES:
6490 break;
6491 }
6492 }
6493
6494 if (extend_selection)
6495 ctk_label_select_region_index (label,
6496 priv->select_info->selection_anchor,
6497 new_pos);
6498 else
6499 ctk_label_select_region_index (label, new_pos, new_pos);
6500}
6501
6502static void
6503ctk_label_copy_clipboard (CtkLabel *label)
6504{
6505 CtkLabelPrivate *priv = label->priv;
6506
6507 if (priv->text && priv->select_info)
6508 {
6509 gint start, end;
6510 gint len;
6511 CtkClipboard *clipboard;
6512
6513 start = MIN (priv->select_info->selection_anchor,(((priv->select_info->selection_anchor) < (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
6514 priv->select_info->selection_end)(((priv->select_info->selection_anchor) < (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
;
6515 end = MAX (priv->select_info->selection_anchor,(((priv->select_info->selection_anchor) > (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
6516 priv->select_info->selection_end)(((priv->select_info->selection_anchor) > (priv->
select_info->selection_end)) ? (priv->select_info->selection_anchor
) : (priv->select_info->selection_end))
;
6517
6518 len = strlen (priv->text);
6519
6520 if (end > len)
6521 end = len;
6522
6523 if (start > len)
6524 start = len;
6525
6526 clipboard = ctk_widget_get_clipboard (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
, CDK_SELECTION_CLIPBOARD((CdkAtom)((gpointer) (gulong) (69))));
6527
6528 if (start != end)
6529 ctk_clipboard_set_text (clipboard, priv->text + start, end - start);
6530 else
6531 {
6532 CtkLabelLink *link;
6533
6534 link = ctk_label_get_focus_link (label);
6535 if (link)
6536 ctk_clipboard_set_text (clipboard, link->uri, -1);
6537 }
6538 }
6539}
6540
6541static void
6542ctk_label_select_all (CtkLabel *label)
6543{
6544 CtkLabelPrivate *priv = label->priv;
6545
6546 ctk_label_select_region_index (label, 0, strlen (priv->text));
6547}
6548
6549/* Quick hack of a popup menu
6550 */
6551static void
6552activate_cb (CtkWidget *menuitem,
6553 CtkLabel *label)
6554{
6555 const gchar *signal = g_object_get_qdata (G_OBJECT (menuitem)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menuitem)), (((GType) ((20) << (2))))))))
, quark_ctk_signal);
6556 g_signal_emit_by_name (label, signal);
6557}
6558
6559static void
6560append_action_signal (CtkLabel *label,
6561 CtkWidget *menu,
6562 const gchar *text,
6563 const gchar *signal,
6564 gboolean sensitive)
6565{
6566 CtkWidget *menuitem = ctk_menu_item_new_with_mnemonic (text);
6567
6568 g_object_set_qdata (G_OBJECT (menuitem)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menuitem)), (((GType) ((20) << (2))))))))
, quark_ctk_signal, (char *)signal);
6569 g_signal_connect (menuitem, "activate",g_signal_connect_data ((menuitem), ("activate"), (((GCallback
) (activate_cb))), (label), ((void*)0), (GConnectFlags) 0)
6570 G_CALLBACK (activate_cb), label)g_signal_connect_data ((menuitem), ("activate"), (((GCallback
) (activate_cb))), (label), ((void*)0), (GConnectFlags) 0)
;
6571
6572 ctk_widget_set_sensitive (menuitem, sensitive);
6573
6574 ctk_widget_show (menuitem);
6575 ctk_menu_shell_append (CTK_MENU_SHELL (menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_shell_get_type ()))))))
, menuitem);
6576}
6577
6578static void
6579popup_menu_detach (CtkWidget *attach_widget,
6580 CtkMenu *menu G_GNUC_UNUSED__attribute__ ((__unused__)))
6581{
6582 CtkLabel *label = CTK_LABEL (attach_widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((attach_widget)), ((ctk_label_get_type ()))))))
;
6583 CtkLabelPrivate *priv = label->priv;
6584
6585 if (priv->select_info)
6586 priv->select_info->popup_menu = NULL((void*)0);
6587}
6588
6589static void
6590open_link_activate_cb (CtkMenuItem *menuitem,
6591 CtkLabel *label)
6592{
6593 CtkLabelLink *link;
6594
6595 link = g_object_get_qdata (G_OBJECT (menuitem)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menuitem)), (((GType) ((20) << (2))))))))
, quark_link);
6596 emit_activate_link (label, link);
6597}
6598
6599static void
6600copy_link_activate_cb (CtkMenuItem *menuitem,
6601 CtkLabel *label)
6602{
6603 CtkLabelLink *link;
6604 CtkClipboard *clipboard;
6605
6606 link = g_object_get_qdata (G_OBJECT (menuitem)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menuitem)), (((GType) ((20) << (2))))))))
, quark_link);
6607 clipboard = ctk_widget_get_clipboard (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
, CDK_SELECTION_CLIPBOARD((CdkAtom)((gpointer) (gulong) (69))));
6608 ctk_clipboard_set_text (clipboard, link->uri, -1);
6609}
6610
6611static gboolean
6612ctk_label_popup_menu (CtkWidget *widget)
6613{
6614 ctk_label_do_popup (CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
, NULL((void*)0));
6615
6616 return TRUE(!(0));
6617}
6618
6619static void
6620ctk_label_do_popup (CtkLabel *label,
6621 const CdkEvent *event)
6622{
6623 CtkLabelPrivate *priv = label->priv;
6624 CtkWidget *menuitem;
6625 CtkWidget *menu;
6626 gboolean have_selection;
6627 CtkLabelLink *link;
6628
6629 if (!priv->select_info)
6630 return;
6631
6632 if (priv->select_info->popup_menu)
6633 ctk_widget_destroy (priv->select_info->popup_menu);
6634
6635 priv->select_info->popup_menu = menu = ctk_menu_new ();
6636 ctk_style_context_add_class (ctk_widget_get_style_context (menu),
6637 CTK_STYLE_CLASS_CONTEXT_MENU"context-menu");
6638
6639 ctk_menu_attach_to_widget (CTK_MENU (menu)((((CtkMenu*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_get_type ()))))))
, CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
, popup_menu_detach);
6640
6641 have_selection =
6642 priv->select_info->selection_anchor != priv->select_info->selection_end;
6643
6644 if (event)
6645 {
6646 if (priv->select_info->link_clicked)
6647 link = priv->select_info->active_link;
6648 else
6649 link = NULL((void*)0);
6650 }
6651 else
6652 link = ctk_label_get_focus_link (label);
6653
6654 if (!have_selection && link)
6655 {
6656 /* Open Link */
6657 menuitem = ctk_menu_item_new_with_mnemonic (_("_Open Link")((char *) g_dgettext ("ctk30", "_Open Link")));
6658 g_object_set_qdata (G_OBJECT (menuitem)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menuitem)), (((GType) ((20) << (2))))))))
, quark_link, link);
6659 ctk_widget_show (menuitem);
6660 ctk_menu_shell_append (CTK_MENU_SHELL (menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_shell_get_type ()))))))
, menuitem);
6661
6662 g_signal_connect (G_OBJECT (menuitem), "activate",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((menuitem)), (((GType) ((20) << (2)
)))))))), ("activate"), (((GCallback) (open_link_activate_cb)
)), (label), ((void*)0), (GConnectFlags) 0)
6663 G_CALLBACK (open_link_activate_cb), label)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((menuitem)), (((GType) ((20) << (2)
)))))))), ("activate"), (((GCallback) (open_link_activate_cb)
)), (label), ((void*)0), (GConnectFlags) 0)
;
6664
6665 /* Copy Link Address */
6666 menuitem = ctk_menu_item_new_with_mnemonic (_("Copy _Link Address")((char *) g_dgettext ("ctk30", "Copy _Link Address")));
6667 g_object_set_qdata (G_OBJECT (menuitem)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menuitem)), (((GType) ((20) << (2))))))))
, quark_link, link);
6668 ctk_widget_show (menuitem);
6669 ctk_menu_shell_append (CTK_MENU_SHELL (menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_shell_get_type ()))))))
, menuitem);
6670
6671 g_signal_connect (G_OBJECT (menuitem), "activate",g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((menuitem)), (((GType) ((20) << (2)
)))))))), ("activate"), (((GCallback) (copy_link_activate_cb)
)), (label), ((void*)0), (GConnectFlags) 0)
6672 G_CALLBACK (copy_link_activate_cb), label)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((menuitem)), (((GType) ((20) << (2)
)))))))), ("activate"), (((GCallback) (copy_link_activate_cb)
)), (label), ((void*)0), (GConnectFlags) 0)
;
6673 }
6674 else
6675 {
6676 append_action_signal (label, menu, _("Cu_t")((char *) g_dgettext ("ctk30", "Cu_t")), "cut-clipboard", FALSE(0));
6677 append_action_signal (label, menu, _("_Copy")((char *) g_dgettext ("ctk30", "_Copy")), "copy-clipboard", have_selection);
6678 append_action_signal (label, menu, _("_Paste")((char *) g_dgettext ("ctk30", "_Paste")), "paste-clipboard", FALSE(0));
6679
6680 menuitem = ctk_menu_item_new_with_mnemonic (_("_Delete")((char *) g_dgettext ("ctk30", "_Delete")));
6681 ctk_widget_set_sensitive (menuitem, FALSE(0));
6682 ctk_widget_show (menuitem);
6683 ctk_menu_shell_append (CTK_MENU_SHELL (menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_shell_get_type ()))))))
, menuitem);
6684
6685 menuitem = ctk_separator_menu_item_new ();
6686 ctk_widget_show (menuitem);
6687 ctk_menu_shell_append (CTK_MENU_SHELL (menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_shell_get_type ()))))))
, menuitem);
6688
6689 menuitem = ctk_menu_item_new_with_mnemonic (_("Select _All")((char *) g_dgettext ("ctk30", "Select _All")));
6690 g_signal_connect_swapped (menuitem, "activate",g_signal_connect_data ((menuitem), ("activate"), (((GCallback
) (ctk_label_select_all))), (label), ((void*)0), G_CONNECT_SWAPPED
)
6691 G_CALLBACK (ctk_label_select_all), label)g_signal_connect_data ((menuitem), ("activate"), (((GCallback
) (ctk_label_select_all))), (label), ((void*)0), G_CONNECT_SWAPPED
)
;
6692 ctk_widget_show (menuitem);
6693 ctk_menu_shell_append (CTK_MENU_SHELL (menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_shell_get_type ()))))))
, menuitem);
6694 }
6695
6696 g_signal_emit (label, signals[POPULATE_POPUP], 0, menu);
6697
6698 if (event && cdk_event_triggers_context_menu (event))
6699 ctk_menu_popup_at_pointer (CTK_MENU (menu)((((CtkMenu*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_get_type ()))))))
, event);
6700 else
6701 {
6702 ctk_menu_popup_at_widget (CTK_MENU (menu)((((CtkMenu*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_get_type ()))))))
,
6703 CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
,
6704 CDK_GRAVITY_SOUTH,
6705 CDK_GRAVITY_NORTH_WEST,
6706 event);
6707
6708 ctk_menu_shell_select_first (CTK_MENU_SHELL (menu)((((CtkMenuShell*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((menu)), ((ctk_menu_shell_get_type ()))))))
, FALSE(0));
6709 }
6710}
6711
6712static void
6713ctk_label_clear_links (CtkLabel *label)
6714{
6715 CtkLabelPrivate *priv = label->priv;
6716
6717 if (!priv->select_info)
6718 return;
6719
6720 g_list_free_full (priv->select_info->links, (GDestroyNotify) link_free);
6721 priv->select_info->links = NULL((void*)0);
6722 priv->select_info->active_link = NULL((void*)0);
6723
6724 _ctk_label_accessible_update_links (label);
6725}
6726
6727static gboolean
6728ctk_label_activate_link (CtkLabel *label,
6729 const gchar *uri)
6730{
6731 CtkWidget *widget = CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
;
6732 CtkWidget *top_level = ctk_widget_get_toplevel (widget);
6733 guint32 timestamp = ctk_get_current_event_time ();
6734 GError *error = NULL((void*)0);
6735
6736 if (!ctk_show_uri_on_window (CTK_WINDOW (top_level)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((top_level)), ((ctk_window_get_type ()))))))
, uri, timestamp, &error))
6737 {
6738 g_warning ("Unable to show '%s': %s", uri, error->message);
6739 g_error_free (error);
6740 }
6741
6742 return TRUE(!(0));
6743}
6744
6745static void
6746emit_activate_link (CtkLabel *label,
6747 CtkLabelLink *link)
6748{
6749 CtkLabelPrivate *priv = label->priv;
6750 gboolean handled;
6751 CtkStateFlags state;
6752
6753 g_signal_emit (label, signals[ACTIVATE_LINK], 0, link->uri, &handled);
6754
6755 /* signal handler might have invalidated the layout */
6756 if (!priv->layout)
6757 return;
6758
6759 if (handled && priv->track_links && !link->visited &&
6760 priv->select_info && priv->select_info->links)
6761 {
6762 link->visited = TRUE(!(0));
6763 state = ctk_css_node_get_state (link->cssnode);
6764 ctk_css_node_set_state (link->cssnode, (state & ~CTK_STATE_FLAG_LINK) | CTK_STATE_FLAG_VISITED);
6765 /* FIXME: shouldn't have to redo everything here */
6766 ctk_label_clear_layout (label);
6767 }
6768}
6769
6770static void
6771ctk_label_activate_current_link (CtkLabel *label)
6772{
6773 CtkLabelLink *link;
6774 CtkWidget *widget = CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
;
6775
6776 link = ctk_label_get_focus_link (label);
6777
6778 if (link)
6779 {
6780 emit_activate_link (label, link);
6781 }
6782 else
6783 {
6784 CtkWidget *toplevel;
6785 CtkWindow *window;
6786 CtkWidget *default_widget, *focus_widget;
6787
6788 toplevel = ctk_widget_get_toplevel (widget);
6789 if (CTK_IS_WINDOW (toplevel)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(toplevel)); GType __t = ((ctk_window_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
6790 {
6791 window = CTK_WINDOW (toplevel)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((toplevel)), ((ctk_window_get_type ()))))))
;
6792
6793 if (window)
6794 {
6795 default_widget = ctk_window_get_default_widget (window);
6796 focus_widget = ctk_window_get_focus (window);
6797
6798 if (default_widget != widget &&
6799 !(widget == focus_widget && (!default_widget || !ctk_widget_is_sensitive (default_widget))))
6800 ctk_window_activate_default (window);
6801 }
6802 }
6803 }
6804}
6805
6806static CtkLabelLink *
6807ctk_label_get_current_link (CtkLabel *label)
6808{
6809 CtkLabelPrivate *priv = label->priv;
6810 CtkLabelLink *link;
6811
6812 if (!priv->select_info)
6813 return NULL((void*)0);
6814
6815 if (priv->select_info->link_clicked)
6816 link = priv->select_info->active_link;
6817 else
6818 link = ctk_label_get_focus_link (label);
6819
6820 return link;
6821}
6822
6823/**
6824 * ctk_label_get_current_uri:
6825 * @label: a #CtkLabel
6826 *
6827 * Returns the URI for the currently active link in the label.
6828 * The active link is the one under the mouse pointer or, in a
6829 * selectable label, the link in which the text cursor is currently
6830 * positioned.
6831 *
6832 * This function is intended for use in a #CtkLabel::activate-link handler
6833 * or for use in a #CtkWidget::query-tooltip handler.
6834 *
6835 * Returns: the currently active URI. The string is owned by CTK+ and must
6836 * not be freed or modified.
6837 *
6838 * Since: 2.18
6839 */
6840const gchar *
6841ctk_label_get_current_uri (CtkLabel *label)
6842{
6843 CtkLabelLink *link;
6844
6845 g_return_val_if_fail (CTK_IS_LABEL (label), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return (((void*)0)); } } while (
0)
;
6846
6847 link = ctk_label_get_current_link (label);
6848
6849 if (link)
6850 return link->uri;
6851
6852 return NULL((void*)0);
6853}
6854
6855/**
6856 * ctk_label_set_track_visited_links:
6857 * @label: a #CtkLabel
6858 * @track_links: %TRUE to track visited links
6859 *
6860 * Sets whether the label should keep track of clicked
6861 * links (and use a different color for them).
6862 *
6863 * Since: 2.18
6864 */
6865void
6866ctk_label_set_track_visited_links (CtkLabel *label,
6867 gboolean track_links)
6868{
6869 CtkLabelPrivate *priv;
6870
6871 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
6872
6873 priv = label->priv;
6874
6875 track_links = track_links != FALSE(0);
6876
6877 if (priv->track_links != track_links)
6878 {
6879 priv->track_links = track_links;
6880
6881 /* FIXME: shouldn't have to redo everything here */
6882 ctk_label_recalculate (label);
6883
6884 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_TRACK_VISITED_LINKS]);
6885 }
6886}
6887
6888/**
6889 * ctk_label_get_track_visited_links:
6890 * @label: a #CtkLabel
6891 *
6892 * Returns whether the label is currently keeping track
6893 * of clicked links.
6894 *
6895 * Returns: %TRUE if clicked links are remembered
6896 *
6897 * Since: 2.18
6898 */
6899gboolean
6900ctk_label_get_track_visited_links (CtkLabel *label)
6901{
6902 g_return_val_if_fail (CTK_IS_LABEL (label), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return ((0)); } } while (0)
;
6903
6904 return label->priv->track_links;
6905}
6906
6907static gboolean
6908ctk_label_query_tooltip (CtkWidget *widget,
6909 gint x,
6910 gint y,
6911 gboolean keyboard_tip,
6912 CtkTooltip *tooltip)
6913{
6914 CtkLabel *label = CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
;
6915 CtkLabelPrivate *priv = label->priv;
6916 CtkLabelSelectionInfo *info = priv->select_info;
6917 gint index = -1;
6918 GList *l;
6919
6920 if (info && info->links)
6921 {
6922 if (keyboard_tip)
6923 {
6924 if (info->selection_anchor == info->selection_end)
6925 index = info->selection_anchor;
6926 }
6927 else
6928 {
6929 if (!get_layout_index (label, x, y, &index))
6930 index = -1;
6931 }
6932
6933 if (index != -1)
6934 {
6935 for (l = info->links; l != NULL((void*)0); l = l->next)
6936 {
6937 CtkLabelLink *link = l->data;
6938 if (index >= link->start && index <= link->end)
6939 {
6940 if (link->title)
6941 {
6942 ctk_tooltip_set_markup (tooltip, link->title);
6943 return TRUE(!(0));
6944 }
6945 break;
6946 }
6947 }
6948 }
6949 }
6950
6951 return CTK_WIDGET_CLASS (ctk_label_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_label_parent_class)), ((ctk_widget_get_type ()))))))
->query_tooltip (widget,
6952 x, y,
6953 keyboard_tip,
6954 tooltip);
6955}
6956
6957gint
6958_ctk_label_get_cursor_position (CtkLabel *label)
6959{
6960 CtkLabelPrivate *priv = label->priv;
6961
6962 if (priv->select_info && priv->select_info->selectable)
6963 return g_utf8_pointer_to_offset (priv->text,
6964 priv->text + priv->select_info->selection_end);
6965
6966 return 0;
6967}
6968
6969gint
6970_ctk_label_get_selection_bound (CtkLabel *label)
6971{
6972 CtkLabelPrivate *priv = label->priv;
6973
6974 if (priv->select_info && priv->select_info->selectable)
6975 return g_utf8_pointer_to_offset (priv->text,
6976 priv->text + priv->select_info->selection_anchor);
6977
6978 return 0;
6979}
6980
6981/**
6982 * ctk_label_set_lines:
6983 * @label: a #CtkLabel
6984 * @lines: the desired number of lines, or -1
6985 *
6986 * Sets the number of lines to which an ellipsized, wrapping label
6987 * should be limited. This has no effect if the label is not wrapping
6988 * or ellipsized. Set this to -1 if you don’t want to limit the
6989 * number of lines.
6990 *
6991 * Since: 3.10
6992 */
6993void
6994ctk_label_set_lines (CtkLabel *label,
6995 gint lines)
6996{
6997 CtkLabelPrivate *priv;
6998
6999 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
7000
7001 priv = label->priv;
7002
7003 if (priv->lines != lines)
7004 {
7005 priv->lines = lines;
7006 ctk_label_clear_layout (label);
7007 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_LINES]);
7008 ctk_widget_queue_resize (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
7009 }
7010}
7011
7012/**
7013 * ctk_label_get_lines:
7014 * @label: a #CtkLabel
7015 *
7016 * Gets the number of lines to which an ellipsized, wrapping
7017 * label should be limited. See ctk_label_set_lines().
7018 *
7019 * Returns: The number of lines
7020 *
7021 * Since: 3.10
7022 */
7023gint
7024ctk_label_get_lines (CtkLabel *label)
7025{
7026 g_return_val_if_fail (CTK_IS_LABEL (label), -1)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return (-1); } } while (0)
;
7027
7028 return label->priv->lines;
7029}
7030
7031gint
7032_ctk_label_get_n_links (CtkLabel *label)
7033{
7034 CtkLabelPrivate *priv = label->priv;
7035
7036 if (priv->select_info)
7037 return g_list_length (priv->select_info->links);
7038
7039 return 0;
7040}
7041
7042const gchar *
7043_ctk_label_get_link_uri (CtkLabel *label,
7044 gint idx)
7045{
7046 CtkLabelPrivate *priv = label->priv;
7047
7048 if (priv->select_info)
7049 {
7050 CtkLabelLink *link = g_list_nth_data (priv->select_info->links, idx);
7051 if (link)
7052 return link->uri;
7053 }
7054
7055 return NULL((void*)0);
7056}
7057
7058void
7059_ctk_label_get_link_extent (CtkLabel *label,
7060 gint idx,
7061 gint *start,
7062 gint *end)
7063{
7064 CtkLabelPrivate *priv = label->priv;
7065 gint i;
7066 GList *l;
7067 CtkLabelLink *link;
7068
7069 if (priv->select_info)
7070 for (l = priv->select_info->links, i = 0; l; l = l->next, i++)
7071 {
7072 if (i == idx)
7073 {
7074 link = l->data;
7075 *start = link->start;
7076 *end = link->end;
7077 return;
7078 }
7079 }
7080
7081 *start = -1;
7082 *end = -1;
7083}
7084
7085gint
7086_ctk_label_get_link_at (CtkLabel *label,
7087 gint pos)
7088{
7089 CtkLabelPrivate *priv = label->priv;
7090 gint i;
7091 GList *l;
7092 CtkLabelLink *link;
7093
7094 if (priv->select_info)
7095 for (l = priv->select_info->links, i = 0; l; l = l->next, i++)
7096 {
7097 link = l->data;
7098 if (link->start <= pos && pos < link->end)
7099 return i;
7100 }
7101
7102 return -1;
7103}
7104
7105void
7106_ctk_label_activate_link (CtkLabel *label,
7107 gint idx)
7108{
7109 CtkLabelPrivate *priv = label->priv;
7110
7111 if (priv->select_info)
7112 {
7113 CtkLabelLink *link = g_list_nth_data (priv->select_info->links, idx);
7114
7115 if (link)
7116 emit_activate_link (label, link);
7117 }
7118}
7119
7120gboolean
7121_ctk_label_get_link_visited (CtkLabel *label,
7122 gint idx)
7123{
7124 CtkLabelPrivate *priv = label->priv;
7125
7126 if (priv->select_info)
7127 {
7128 CtkLabelLink *link = g_list_nth_data (priv->select_info->links, idx);
7129 return link ? link->visited : FALSE(0);
7130 }
7131
7132 return FALSE(0);
7133}
7134
7135gboolean
7136_ctk_label_get_link_focused (CtkLabel *label,
7137 gint idx)
7138{
7139 CtkLabelPrivate *priv = label->priv;
7140 gint i;
7141 GList *l;
7142 CtkLabelLink *link;
7143 CtkLabelSelectionInfo *info = priv->select_info;
7144
7145 if (!info)
7146 return FALSE(0);
7147
7148 if (info->selection_anchor != info->selection_end)
7149 return FALSE(0);
7150
7151 for (l = info->links, i = 0; l; l = l->next, i++)
7152 {
7153 if (i == idx)
7154 {
7155 link = l->data;
7156 if (link->start <= info->selection_anchor &&
7157 info->selection_anchor <= link->end)
7158 return TRUE(!(0));
7159 }
7160 }
7161
7162 return FALSE(0);
7163}
7164
7165/**
7166 * ctk_label_set_xalign:
7167 * @label: a #CtkLabel
7168 * @xalign: the new xalign value, between 0 and 1
7169 *
7170 * Sets the #CtkLabel:xalign property for @label.
7171 *
7172 * Since: 3.16
7173 */
7174void
7175ctk_label_set_xalign (CtkLabel *label,
7176 gfloat xalign)
7177{
7178 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
7179
7180 xalign = CLAMP (xalign, 0.0, 1.0)(((xalign) > (1.0)) ? (1.0) : (((xalign) < (0.0)) ? (0.0
) : (xalign)))
;
7181
7182 if (label->priv->xalign == xalign)
7183 return;
7184
7185 label->priv->xalign = xalign;
7186
7187 ctk_widget_queue_draw (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
7188 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_XALIGN]);
7189}
7190
7191/**
7192 * ctk_label_get_xalign:
7193 * @label: a #CtkLabel
7194 *
7195 * Gets the #CtkLabel:xalign property for @label.
7196 *
7197 * Returns: the xalign property
7198 *
7199 * Since: 3.16
7200 */
7201gfloat
7202ctk_label_get_xalign (CtkLabel *label)
7203{
7204 g_return_val_if_fail (CTK_IS_LABEL (label), 0.5)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return (0.5); } } while (0)
;
7205
7206 return label->priv->xalign;
7207}
7208
7209/**
7210 * ctk_label_set_yalign:
7211 * @label: a #CtkLabel
7212 * @yalign: the new yalign value, between 0 and 1
7213 *
7214 * Sets the #CtkLabel:yalign property for @label.
7215 *
7216 * Since: 3.16
7217 */
7218void
7219ctk_label_set_yalign (CtkLabel *label,
7220 gfloat yalign)
7221{
7222 g_return_if_fail (CTK_IS_LABEL (label))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return; } } while (0)
;
7223
7224 yalign = CLAMP (yalign, 0.0, 1.0)(((yalign) > (1.0)) ? (1.0) : (((yalign) < (0.0)) ? (0.0
) : (yalign)))
;
7225
7226 if (label->priv->yalign == yalign)
7227 return;
7228
7229 label->priv->yalign = yalign;
7230
7231 ctk_widget_queue_draw (CTK_WIDGET (label)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), ((ctk_widget_get_type ()))))))
);
7232 g_object_notify_by_pspec (G_OBJECT (label)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((label)), (((GType) ((20) << (2))))))))
, label_props[PROP_YALIGN]);
7233}
7234
7235/**
7236 * ctk_label_get_yalign:
7237 * @label: a #CtkLabel
7238 *
7239 * Gets the #CtkLabel:yalign property for @label.
7240 *
7241 * Returns: the yalign property
7242 *
7243 * Since: 3.16
7244 */
7245gfloat
7246ctk_label_get_yalign (CtkLabel *label)
7247{
7248 g_return_val_if_fail (CTK_IS_LABEL (label), 0.5)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((label)); GType __t = ((ctk_label_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))))) { }
else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__
)), "CTK_IS_LABEL (label)"); return (0.5); } } while (0)
;
7249
7250 return label->priv->yalign;
7251}