File: | ctk/ctklabel.c |
Warning: | line 3650, column 25 Dereference of null pointer (loaded from variable 'minimum_baseline') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 <, >, and &. | |||
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=\"<i>Our</i> 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 | ||||
251 | struct _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 | */ | |||
315 | typedef 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 | ||||
329 | struct _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 | ||||
352 | enum { | |||
353 | MOVE_CURSOR, | |||
354 | COPY_CLIPBOARD, | |||
355 | POPULATE_POPUP, | |||
356 | ACTIVATE_LINK, | |||
357 | ACTIVATE_CURRENT_LINK, | |||
358 | LAST_SIGNAL | |||
359 | }; | |||
360 | ||||
361 | enum { | |||
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 | ||||
388 | static 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 | ||||
395 | static guint signals[LAST_SIGNAL] = { 0 }; | |||
396 | ||||
397 | static GQuark quark_shortcuts_connected; | |||
398 | static GQuark quark_mnemonic_menu; | |||
399 | static GQuark quark_mnemonics_visible_connected; | |||
400 | static GQuark quark_ctk_signal; | |||
401 | static GQuark quark_link; | |||
402 | ||||
403 | static void ctk_label_set_property (GObject *object, | |||
404 | guint prop_id, | |||
405 | const GValue *value, | |||
406 | GParamSpec *pspec); | |||
407 | static void ctk_label_get_property (GObject *object, | |||
408 | guint prop_id, | |||
409 | GValue *value, | |||
410 | GParamSpec *pspec); | |||
411 | static void ctk_label_finalize (GObject *object); | |||
412 | static void ctk_label_destroy (CtkWidget *widget); | |||
413 | static void ctk_label_size_allocate (CtkWidget *widget, | |||
414 | CtkAllocation *allocation); | |||
415 | static void ctk_label_state_flags_changed (CtkWidget *widget, | |||
416 | CtkStateFlags prev_state); | |||
417 | static void ctk_label_style_updated (CtkWidget *widget); | |||
418 | static gboolean ctk_label_draw (CtkWidget *widget, | |||
419 | cairo_t *cr); | |||
420 | static gboolean ctk_label_focus (CtkWidget *widget, | |||
421 | CtkDirectionType direction); | |||
422 | ||||
423 | static void ctk_label_realize (CtkWidget *widget); | |||
424 | static void ctk_label_unrealize (CtkWidget *widget); | |||
425 | static void ctk_label_map (CtkWidget *widget); | |||
426 | static void ctk_label_unmap (CtkWidget *widget); | |||
427 | ||||
428 | static gboolean ctk_label_motion (CtkWidget *widget, | |||
429 | CdkEventMotion *event); | |||
430 | static gboolean ctk_label_leave_notify (CtkWidget *widget, | |||
431 | CdkEventCrossing *event); | |||
432 | ||||
433 | static void ctk_label_grab_focus (CtkWidget *widget); | |||
434 | ||||
435 | static gboolean ctk_label_query_tooltip (CtkWidget *widget, | |||
436 | gint x, | |||
437 | gint y, | |||
438 | gboolean keyboard_tip, | |||
439 | CtkTooltip *tooltip); | |||
440 | ||||
441 | static void ctk_label_set_text_internal (CtkLabel *label, | |||
442 | gchar *str); | |||
443 | static void ctk_label_set_label_internal (CtkLabel *label, | |||
444 | gchar *str); | |||
445 | static gboolean ctk_label_set_use_markup_internal (CtkLabel *label, | |||
446 | gboolean val); | |||
447 | static gboolean ctk_label_set_use_underline_internal (CtkLabel *label, | |||
448 | gboolean val); | |||
449 | static void ctk_label_set_uline_text_internal (CtkLabel *label, | |||
450 | const gchar *str); | |||
451 | static void ctk_label_set_pattern_internal (CtkLabel *label, | |||
452 | const gchar *pattern, | |||
453 | gboolean is_mnemonic); | |||
454 | static void ctk_label_set_markup_internal (CtkLabel *label, | |||
455 | const gchar *str, | |||
456 | gboolean with_uline); | |||
457 | static void ctk_label_recalculate (CtkLabel *label); | |||
458 | static void ctk_label_hierarchy_changed (CtkWidget *widget, | |||
459 | CtkWidget *old_toplevel); | |||
460 | static void ctk_label_screen_changed (CtkWidget *widget, | |||
461 | CdkScreen *old_screen); | |||
462 | static gboolean ctk_label_popup_menu (CtkWidget *widget); | |||
463 | ||||
464 | static void ctk_label_create_window (CtkLabel *label); | |||
465 | static void ctk_label_destroy_window (CtkLabel *label); | |||
466 | static void ctk_label_ensure_select_info (CtkLabel *label); | |||
467 | static void ctk_label_clear_select_info (CtkLabel *label); | |||
468 | static void ctk_label_update_cursor (CtkLabel *label); | |||
469 | static void ctk_label_clear_layout (CtkLabel *label); | |||
470 | static void ctk_label_ensure_layout (CtkLabel *label); | |||
471 | static void ctk_label_select_region_index (CtkLabel *label, | |||
472 | gint anchor_index, | |||
473 | gint end_index); | |||
474 | ||||
475 | static void ctk_label_update_active_link (CtkWidget *widget, | |||
476 | gdouble x, | |||
477 | gdouble y); | |||
478 | ||||
479 | static gboolean ctk_label_mnemonic_activate (CtkWidget *widget, | |||
480 | gboolean group_cycling); | |||
481 | static void ctk_label_setup_mnemonic (CtkLabel *label, | |||
482 | guint last_key); | |||
483 | static void ctk_label_drag_data_get (CtkWidget *widget, | |||
484 | CdkDragContext *context, | |||
485 | CtkSelectionData *selection_data, | |||
486 | guint info, | |||
487 | guint time); | |||
488 | ||||
489 | static void ctk_label_buildable_interface_init (CtkBuildableIface *iface); | |||
490 | static 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 | ||||
497 | static void ctk_label_buildable_custom_finished (CtkBuildable *buildable, | |||
498 | CtkBuilder *builder, | |||
499 | GObject *child, | |||
500 | const gchar *tagname, | |||
501 | gpointer user_data); | |||
502 | ||||
503 | ||||
504 | static void connect_mnemonics_visible_notify (CtkLabel *label); | |||
505 | static gboolean separate_uline_pattern (const gchar *str, | |||
506 | guint *accel_key, | |||
507 | gchar **new_str, | |||
508 | gchar **pattern); | |||
509 | ||||
510 | ||||
511 | /* For selectable labels: */ | |||
512 | static void ctk_label_move_cursor (CtkLabel *label, | |||
513 | CtkMovementStep step, | |||
514 | gint count, | |||
515 | gboolean extend_selection); | |||
516 | static void ctk_label_copy_clipboard (CtkLabel *label); | |||
517 | static void ctk_label_select_all (CtkLabel *label); | |||
518 | static void ctk_label_do_popup (CtkLabel *label, | |||
519 | const CdkEvent *event); | |||
520 | static gint ctk_label_move_forward_word (CtkLabel *label, | |||
521 | gint start); | |||
522 | static gint ctk_label_move_backward_word (CtkLabel *label, | |||
523 | gint start); | |||
524 | ||||
525 | /* For links: */ | |||
526 | static void ctk_label_clear_links (CtkLabel *label); | |||
527 | static gboolean ctk_label_activate_link (CtkLabel *label, | |||
528 | const gchar *uri); | |||
529 | static void ctk_label_activate_current_link (CtkLabel *label); | |||
530 | static CtkLabelLink *ctk_label_get_current_link (CtkLabel *label); | |||
531 | static void emit_activate_link (CtkLabel *label, | |||
532 | CtkLabelLink *link); | |||
533 | ||||
534 | /* Event controller callbacks */ | |||
535 | static void ctk_label_multipress_gesture_pressed (CtkGestureMultiPress *gesture, | |||
536 | gint n_press, | |||
537 | gdouble x, | |||
538 | gdouble y, | |||
539 | CtkLabel *label); | |||
540 | static void ctk_label_multipress_gesture_released (CtkGestureMultiPress *gesture, | |||
541 | gint n_press, | |||
542 | gdouble x, | |||
543 | gdouble y, | |||
544 | CtkLabel *label); | |||
545 | static void ctk_label_drag_gesture_begin (CtkGestureDrag *gesture, | |||
546 | gdouble start_x, | |||
547 | gdouble start_y, | |||
548 | CtkLabel *label); | |||
549 | static void ctk_label_drag_gesture_update (CtkGestureDrag *gesture, | |||
550 | gdouble offset_x, | |||
551 | gdouble offset_y, | |||
552 | CtkLabel *label); | |||
553 | ||||
554 | static CtkSizeRequestMode ctk_label_get_request_mode (CtkWidget *widget); | |||
555 | static void ctk_label_get_preferred_width (CtkWidget *widget, | |||
556 | gint *minimum_size, | |||
557 | gint *natural_size); | |||
558 | static void ctk_label_get_preferred_height (CtkWidget *widget, | |||
559 | gint *minimum_size, | |||
560 | gint *natural_size); | |||
561 | static void ctk_label_get_preferred_width_for_height (CtkWidget *widget, | |||
562 | gint height, | |||
563 | gint *minimum_width, | |||
564 | gint *natural_width); | |||
565 | static void ctk_label_get_preferred_height_for_width (CtkWidget *widget, | |||
566 | gint width, | |||
567 | gint *minimum_height, | |||
568 | gint *natural_height); | |||
569 | static 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 | ||||
576 | static 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); | |||
584 | static 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 | ||||
592 | static CtkBuildableIface *buildable_parent_iface = NULL((void*)0); | |||
593 | ||||
594 | G_GNUC_BEGIN_IGNORE_DEPRECATIONSclang diagnostic push
clang diagnostic ignored "-Wdeprecated-declarations" | |||
595 | G_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 ; } | |||
599 | G_GNUC_END_IGNORE_DEPRECATIONSclang diagnostic pop | |||
600 | ||||
601 | static void | |||
602 | add_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 | ||||
624 | static void | |||
625 | ctk_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 | ||||
1207 | static void | |||
1208 | ctk_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 | ||||
1280 | static void | |||
1281 | ctk_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 | ||||
1360 | static void | |||
1361 | ctk_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 | ||||
1408 | static void | |||
1409 | ctk_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 | ||||
1417 | typedef struct { | |||
1418 | CtkBuilder *builder; | |||
1419 | GObject *object; | |||
1420 | PangoAttrList *attrs; | |||
1421 | } PangoParserData; | |||
1422 | ||||
1423 | static PangoAttribute * | |||
1424 | attribute_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 | ||||
1592 | static void | |||
1593 | pango_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 | ||||
1682 | static const GMarkupParser pango_parser = | |||
1683 | { | |||
1684 | .start_element = pango_start_element, | |||
1685 | }; | |||
1686 | ||||
1687 | static gboolean | |||
1688 | ctk_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 | ||||
1713 | static void | |||
1714 | ctk_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 | **/ | |||
1751 | CtkWidget* | |||
1752 | ctk_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 | **/ | |||
1786 | CtkWidget* | |||
1787 | ctk_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 | ||||
1799 | static gboolean | |||
1800 | ctk_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 | ||||
1835 | static void | |||
1836 | ctk_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 | ||||
1898 | static void | |||
1899 | ctk_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 | ||||
1908 | static void | |||
1909 | label_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 | ||||
1916 | static void | |||
1917 | label_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 | ||||
1927 | static void | |||
1928 | label_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 | ||||
1946 | static void | |||
1947 | mnemonics_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 | ||||
1963 | static void | |||
1964 | label_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 | ||||
1972 | void | |||
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 | ||||
1984 | static void | |||
1985 | label_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 | ||||
1998 | static void | |||
1999 | ctk_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 | ||||
2033 | static void | |||
2034 | label_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 | **/ | |||
2064 | void | |||
2065 | ctk_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 | **/ | |||
2106 | CtkWidget * | |||
2107 | ctk_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 | **/ | |||
2124 | guint | |||
2125 | ctk_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 | ||||
2132 | static void | |||
2133 | ctk_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 | ||||
2153 | static void | |||
2154 | ctk_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 | ||||
2166 | static gboolean | |||
2167 | ctk_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 | ||||
2185 | static gboolean | |||
2186 | ctk_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 | */ | |||
2207 | static void | |||
2208 | ctk_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 | **/ | |||
2260 | void | |||
2261 | ctk_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 | **/ | |||
2292 | void | |||
2293 | ctk_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 | **/ | |||
2327 | PangoAttrList * | |||
2328 | ctk_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 | **/ | |||
2345 | void | |||
2346 | ctk_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 | **/ | |||
2370 | const gchar * | |||
2371 | ctk_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 | ||||
2378 | typedef struct | |||
2379 | { | |||
2380 | CtkLabel *label; | |||
2381 | GList *links; | |||
2382 | GString *new_str; | |||
2383 | gsize text_len; | |||
2384 | } UriParserData; | |||
2385 | ||||
2386 | static void | |||
2387 | start_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 | ||||
2505 | static void | |||
2506 | end_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 | ||||
2526 | static void | |||
2527 | text_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 | ||||
2542 | static 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 | ||||
2551 | static gboolean | |||
2552 | xml_isspace (gchar c) | |||
2553 | { | |||
2554 | return (c == ' ' || c == '\t' || c == '\n' || c == '\r'); | |||
2555 | } | |||
2556 | ||||
2557 | static void | |||
2558 | link_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 | ||||
2567 | static gboolean | |||
2568 | parse_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 | ||||
2622 | failed: | |||
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 | ||||
2630 | static void | |||
2631 | ctk_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 | ||||
2650 | static void | |||
2651 | ctk_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 | **/ | |||
2795 | void | |||
2796 | ctk_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 | */ | |||
2827 | void | |||
2828 | ctk_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 | **/ | |||
2855 | const gchar * | |||
2856 | ctk_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 | ||||
2863 | static PangoAttrList * | |||
2864 | ctk_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 | ||||
2904 | static void | |||
2905 | ctk_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 | */ | |||
2950 | void | |||
2951 | ctk_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 | */ | |||
2987 | void | |||
2988 | ctk_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 | **/ | |||
3018 | CtkJustification | |||
3019 | ctk_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 | **/ | |||
3036 | void | |||
3037 | ctk_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 | **/ | |||
3069 | PangoEllipsizeMode | |||
3070 | ctk_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 | **/ | |||
3086 | void | |||
3087 | ctk_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 | **/ | |||
3115 | gint | |||
3116 | ctk_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 | **/ | |||
3132 | void | |||
3133 | ctk_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 | **/ | |||
3162 | gint | |||
3163 | ctk_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 | **/ | |||
3185 | void | |||
3186 | ctk_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 | */ | |||
3216 | gboolean | |||
3217 | ctk_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 | **/ | |||
3235 | void | |||
3236 | ctk_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 | */ | |||
3264 | PangoWrapMode | |||
3265 | ctk_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 | ||||
3272 | static void | |||
3273 | ctk_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 | ||||
3282 | static void | |||
3283 | ctk_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 | ||||
3309 | static void | |||
3310 | ctk_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 | **/ | |||
3328 | static PangoLayout * | |||
3329 | ctk_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 | ||||
3386 | static void | |||
3387 | ctk_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)); | |||
3402 | G_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); | |||
3404 | G_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 | ||||
3478 | static void | |||
3479 | ctk_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 | ||||
3540 | static void | |||
3541 | ctk_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 | ||||
3612 | static CtkSizeRequestMode | |||
3613 | ctk_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 | ||||
3629 | static void | |||
3630 | get_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) | |||
3648 | { | |||
3649 | baseline = pango_layout_get_baseline (layout) / PANGO_SCALE1024; | |||
3650 | *minimum_baseline = baseline; | |||
| ||||
3651 | *natural_baseline = baseline; | |||
3652 | } | |||
3653 | ||||
3654 | g_object_unref (layout); | |||
3655 | } | |||
3656 | ||||
3657 | static gint | |||
3658 | get_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 | ||||
3676 | static void | |||
3677 | ctk_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 | ||||
3746 | static void | |||
3747 | ctk_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 | ||||
3760 | G_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); | |||
3762 | G_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 | ||||
3873 | static void | |||
3874 | ctk_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 | ||||
3892 | G_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); | |||
3894 | G_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)) || | |||
| ||||
3897 | (orientation == CTK_ORIENTATION_HORIZONTAL && priv->wrap && (priv->angle == 90 || priv->angle == 270))) | |||
3898 | { | |||
3899 | gint size; | |||
3900 | ||||
3901 | if (priv->wrap
| |||
3902 | ctk_label_clear_layout (label); | |||
3903 | ||||
3904 | if (orientation
| |||
3905 | size = MAX (1, for_size)(((1) > (for_size)) ? (1) : (for_size)) - 2 * ypad; | |||
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); | |||
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 | ||||
3926 | static void | |||
3927 | ctk_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 | ||||
3938 | static void | |||
3939 | ctk_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 | ||||
3950 | static void | |||
3951 | ctk_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 | ||||
3963 | static void | |||
3964 | ctk_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 | ||||
3976 | static void | |||
3977 | ctk_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 | ||||
3991 | static void | |||
3992 | get_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 | ||||
4012 | G_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); | |||
4014 | G_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 | ||||
4075 | static void | |||
4076 | ctk_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 | ||||
4097 | static void | |||
4098 | ctk_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 | ||||
4127 | static void | |||
4128 | ctk_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 | ||||
4164 | static void | |||
4165 | update_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 | ||||
4194 | static void | |||
4195 | ctk_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 | ||||
4214 | static void | |||
4215 | ctk_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 | ||||
4232 | static PangoDirection | |||
4233 | get_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 | ||||
4260 | static CtkLabelLink * | |||
4261 | ctk_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 | ||||
4284 | static gboolean | |||
4285 | ctk_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 | ||||
4293 | static void layout_to_window_coords (CtkLabel *label, | |||
4294 | gint *x, | |||
4295 | gint *y); | |||
4296 | ||||
4297 | static gboolean | |||
4298 | ctk_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 | ||||
4430 | static gboolean | |||
4431 | separate_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 | ||||
4506 | static void | |||
4507 | ctk_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 | **/ | |||
4542 | void | |||
4543 | ctk_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 | ||||
4560 | static void | |||
4561 | ctk_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 | ||||
4572 | static void | |||
4573 | ctk_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 | ||||
4584 | static void | |||
4585 | ctk_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 | ||||
4596 | static void | |||
4597 | ctk_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 | ||||
4616 | static void | |||
4617 | window_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 | ||||
4635 | static void | |||
4636 | layout_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 | ||||
4654 | static gboolean | |||
4655 | get_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 | ||||
4692 | static gboolean | |||
4693 | range_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 | ||||
4747 | static gboolean | |||
4748 | range_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 | ||||
4755 | static void | |||
4756 | ctk_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 | ||||
4775 | static void | |||
4776 | ctk_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 | ||||
4818 | static gboolean | |||
4819 | ctk_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 | ||||
4950 | out: | |||
4951 | ||||
4952 | return FALSE(0); | |||
4953 | } | |||
4954 | ||||
4955 | static void | |||
4956 | ctk_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 | ||||
5039 | static void | |||
5040 | ctk_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 | ||||
5077 | static void | |||
5078 | connect_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 | ||||
5108 | static void | |||
5109 | drag_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 | ||||
5155 | static void | |||
5156 | ctk_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 | ||||
5224 | static void | |||
5225 | ctk_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 | ||||
5319 | static void | |||
5320 | ctk_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 | ||||
5380 | static gboolean | |||
5381 | ctk_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 | ||||
5392 | static gboolean | |||
5393 | ctk_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 | ||||
5412 | static void | |||
5413 | ctk_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 | ||||
5460 | static void | |||
5461 | ctk_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 | ||||
5475 | static void | |||
5476 | ctk_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 | ||||
5509 | static void | |||
5510 | ctk_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 | **/ | |||
5539 | void | |||
5540 | ctk_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 | **/ | |||
5590 | gboolean | |||
5591 | ctk_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 | **/ | |||
5615 | void | |||
5616 | ctk_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 | **/ | |||
5654 | gdouble | |||
5655 | ctk_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 | ||||
5662 | static void | |||
5663 | ctk_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 | ||||
5695 | static void | |||
5696 | ctk_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 | ||||
5705 | static void | |||
5706 | get_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 | ||||
5714 | static void | |||
5715 | clear_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 | ||||
5732 | static void | |||
5733 | ctk_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 | **/ | |||
5883 | void | |||
5884 | ctk_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 | **/ | |||
5919 | gboolean | |||
5920 | ctk_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 | **/ | |||
5993 | PangoLayout* | |||
5994 | ctk_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 | **/ | |||
6023 | void | |||
6024 | ctk_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 | **/ | |||
6044 | void | |||
6045 | ctk_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 | **/ | |||
6068 | gboolean | |||
6069 | ctk_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 | */ | |||
6084 | void | |||
6085 | ctk_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 | **/ | |||
6108 | gboolean | |||
6109 | ctk_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 | */ | |||
6125 | void | |||
6126 | ctk_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 | **/ | |||
6158 | gboolean | |||
6159 | ctk_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 | */ | |||
6171 | static void | |||
6172 | get_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 | ||||
6214 | static gint | |||
6215 | ctk_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 | ||||
6258 | static gint | |||
6259 | ctk_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 | ||||
6313 | static gint | |||
6314 | ctk_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 | ||||
6344 | static gint | |||
6345 | ctk_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 | ||||
6373 | static void | |||
6374 | ctk_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 | ||||
6502 | static void | |||
6503 | ctk_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 | ||||
6541 | static void | |||
6542 | ctk_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 | */ | |||
6551 | static void | |||
6552 | activate_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 | ||||
6559 | static void | |||
6560 | append_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 | ||||
6578 | static void | |||
6579 | popup_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 | ||||
6589 | static void | |||
6590 | open_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 | ||||
6599 | static void | |||
6600 | copy_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 | ||||
6611 | static gboolean | |||
6612 | ctk_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 | ||||
6619 | static void | |||
6620 | ctk_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 | ||||
6712 | static void | |||
6713 | ctk_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 | ||||
6727 | static gboolean | |||
6728 | ctk_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 | ||||
6745 | static void | |||
6746 | emit_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 | ||||
6770 | static void | |||
6771 | ctk_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 | ||||
6806 | static CtkLabelLink * | |||
6807 | ctk_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 | */ | |||
6840 | const gchar * | |||
6841 | ctk_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 | */ | |||
6865 | void | |||
6866 | ctk_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 | */ | |||
6899 | gboolean | |||
6900 | ctk_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 | ||||
6907 | static gboolean | |||
6908 | ctk_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 | ||||
6957 | gint | |||
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 | ||||
6969 | gint | |||
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 | */ | |||
6993 | void | |||
6994 | ctk_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 | */ | |||
7023 | gint | |||
7024 | ctk_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 | ||||
7031 | gint | |||
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 | ||||
7042 | const 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 | ||||
7058 | void | |||
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 | ||||
7085 | gint | |||
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 | ||||
7105 | void | |||
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 | ||||
7120 | gboolean | |||
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 | ||||
7135 | gboolean | |||
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 | */ | |||
7174 | void | |||
7175 | ctk_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 | */ | |||
7201 | gfloat | |||
7202 | ctk_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 | */ | |||
7218 | void | |||
7219 | ctk_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 | */ | |||
7245 | gfloat | |||
7246 | ctk_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 | } |